diff --git a/.gitignore b/.gitignore index 4caeb6cc533a35a4f14e5b4ca8e038fe6f60b61b..d9ba8ac2b411f21befe040b38e08732c5ead9d28 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,7 @@ node/runtime/wasm/target/ polkadot.* .DS_Store .idea/ +nohup.out +rls*.log +*.orig +*.rej diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 12c019b3e260a66280a2d7dd9bba8e1545366f87..f4f42ef49ae1dda63a300a450f80ea5cc220bbc3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,9 @@ # .gitlab-ci.yml - +# +# substrate +# +# pipelines can be triggered manually in the web +# setting DEPLOY_TAG will only deploy the tagged image stages: @@ -22,7 +26,7 @@ variables: cache: {} -.collect_artifacts: &collect_artifacts +.collect-artifacts: &collect-artifacts artifacts: name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}" when: on_success @@ -32,7 +36,7 @@ cache: {} -.kubernetes_build: &kubernetes_build +.kubernetes-build: &kubernetes-build tags: - kubernetes-parity-build environment: @@ -42,11 +46,11 @@ cache: {} #### stage: merge-test -check:merge:conflict: +check-merge-conflict: stage: merge-test image: parity/tools:latest cache: {} - <<: *kubernetes_build + <<: *kubernetes-build only: - /^[0-9]+$/ variables: @@ -61,11 +65,11 @@ check:merge:conflict: #### stage: test -check:runtime: +check-runtime: stage: test image: parity/tools:latest cache: {} - <<: *kubernetes_build + <<: *kubernetes-build only: - /^[0-9]+$/ variables: @@ -77,10 +81,10 @@ check:runtime: -test:rust:stable: &test +test-linux-stable: &test stage: test cache: - key: "${CI_JOB_NAME}-test" + key: "${CI_JOB_NAME}" paths: - ${CARGO_HOME} - ./target @@ -98,6 +102,9 @@ test:rust:stable: &test - schedules - web - /^[0-9]+$/ + except: + variables: + - $DEPLOY_TAG before_script: - test -d ${CARGO_HOME} -a -d ./target && echo "build cache size:" && @@ -110,7 +117,7 @@ test:rust:stable: &test -.build_only: &build_only +.build-only: &build-only only: - master - tags @@ -119,15 +126,18 @@ test:rust:stable: &test #### stage: build -build:rust:linux:release: &build +build-linux-release: &build stage: build cache: - key: "${CI_JOB_NAME}-build" + key: "${CI_JOB_NAME}" paths: - ${CARGO_HOME} - ./target - <<: *collect_artifacts - <<: *build_only + <<: *collect-artifacts + <<: *build-only + except: + variables: + - $DEPLOY_TAG tags: - linux-docker before_script: @@ -151,7 +161,7 @@ build:rust:linux:release: &build -build:rust:doc:release: &build +build-rust-doc-release: &build stage: build allow_failure: true artifacts: @@ -160,12 +170,12 @@ build:rust:doc:release: &build expire_in: 7 days paths: - ./crate-docs - <<: *build_only + <<: *build-only tags: - linux-docker script: - rm -f ./crate-docs/index.html # use it as an indicator if the job succeeds - - time cargo doc --release --verbose + - time cargo +nightly doc --release --verbose - cp -R ./target/doc ./crate-docs - echo "" > ./crate-docs/index.html @@ -174,35 +184,38 @@ build:rust:doc:release: &build #### stage: publish -.publish_build: &publish_build +.publish-build: &publish-build stage: publish dependencies: - - build:rust:linux:release + - build-linux-release cache: {} - <<: *build_only - <<: *kubernetes_build + <<: *build-only + <<: *kubernetes-build -publish:docker:release: - <<: *publish_build +publish-docker-release: + <<: *publish-build image: docker:stable services: - docker:dind # collect VERSION artifact here to pass it on to kubernetes - <<: *collect_artifacts + <<: *collect-artifacts variables: DOCKER_HOST: tcp://localhost:2375 DOCKER_DRIVER: overlay2 GIT_STRATEGY: none # DOCKERFILE: scripts/docker/Dockerfile CONTAINER_IMAGE: parity/substrate - script: - - VERSION="$(cat ./artifacts/VERSION)" + before_script: - test "$Docker_Hub_User_Parity" -a "$Docker_Hub_Pass_Parity" || ( echo "no docker credentials provided"; exit 1 ) - docker login -u "$Docker_Hub_User_Parity" -p "$Docker_Hub_Pass_Parity" - docker info + script: + - VERSION="$(cat ./artifacts/VERSION)" + - echo "Substrate version = ${VERSION}" + - test -z "${VERSION}" && exit 1 - cd ./artifacts - docker build --tag $CONTAINER_IMAGE:$VERSION --tag $CONTAINER_IMAGE:latest . - docker push $CONTAINER_IMAGE:$VERSION @@ -215,8 +228,8 @@ publish:docker:release: -publish:s3:release: - <<: *publish_build +publish-s3-release: + <<: *publish-build image: parity/awscli:latest variables: GIT_STRATEGY: none @@ -237,14 +250,14 @@ publish:s3:release: -publish:s3:doc: +publish-s3-doc: stage: publish allow_failure: true dependencies: - - build:rust:doc:release + - build-rust-doc-release cache: {} - <<: *build_only - <<: *kubernetes_build + <<: *build-only + <<: *kubernetes-build variables: GIT_STRATEGY: none BUCKET: "releases.parity.io" @@ -264,20 +277,15 @@ publish:s3:doc: - - -.deploy:template: &deploy +.deploy-template: &deploy stage: deploy when: manual cache: {} - dependencies: - - publish:docker:release retry: 1 image: parity/kubectl-helm:$HELM_VERSION - <<: *build_only - # variables: - # DEPLOY_TAG: "latest" + <<: *build-only tags: + # this is the runner that is used to deploy it - kubernetes-parity-build before_script: - test -z "${DEPLOY_TAG}" && @@ -292,28 +300,56 @@ publish:s3:doc: --set image.tag=${DEPLOY_TAG} --set validator.keys=${VALIDATOR_KEYS} ./scripts/kubernetes | kubectl apply -f - --dry-run=false - - echo "# substrate namespace" - - kubectl -n substrate get all + - echo "# substrate namespace ${KUBE_NAMESPACE}" + - kubectl -n ${KUBE_NAMESPACE} get all - echo "# substrate's nodes' external ip addresses:" - kubectl get nodes -l node=substrate -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range @.status.addresses[?(@.type=="ExternalIP")]}{.address}{"\n"}{end}' - echo "# substrate' nodes" - - kubectl -n substrate get pods + - kubectl -n ${KUBE_NAMESPACE} get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}' + - echo "# wait for the rollout to complete" + - kubectl -n ${KUBE_NAMESPACE} rollout status statefulset/substrate # have environment:url eventually point to the logs -deploy:ew3: + +.deploy-cibuild: &deploy-cibuild + <<: *deploy + dependencies: + - publish-docker-release + +.deploy-tag: &deploy-tag <<: *deploy + only: + variables: + - $DEPLOY_TAG + + + +# have environment:url eventually point to the logs +deploy-ew3: + <<: *deploy-cibuild environment: name: parity-prod-ew3 -deploy:ue1: - <<: *deploy +deploy-ue1: + <<: *deploy-cibuild environment: name: parity-prod-ue1 +deploy-ew3-tag: + <<: *deploy-tag + environment: + name: parity-prod-ew3 + +deploy-ue1-tag: + <<: *deploy-tag + environment: + name: parity-prod-ue1 + + diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc index 811e83e9fa973d4a35d791beebafc37602ba18c1..7cb0210e8efac2575e23bd46a000af59bb36cb3e 100644 --- a/CODE_OF_CONDUCT.adoc +++ b/CODE_OF_CONDUCT.adoc @@ -24,7 +24,7 @@ Examples of unacceptable behavior by participants include: === Facilitation, Not Strongarming -We recognise that this software is merely a tool for users to create and maintain their blockchain of preference. We see that blockchains are naturally community platforms with users being the ultimate decision makers. We assert that good software will maximise user agency by facilitate user-expression on the network. As such: +We recognize that this software is merely a tool for users to create and maintain their blockchain of preference. We see that blockchains are naturally community platforms with users being the ultimate decision makers. We assert that good software will maximize user agency by facilitate user-expression on the network. As such: * This project will strive to give users as much choice as is both reasonable and possible over what protocol they adhere to; but * use of the project's technical forums, commenting systems, pull requests and issue trackers as a means to express individual protocol preferences is forbidden. diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc index 30bf3a1bb2cb63e2988d041f3304677d6b563a27..b797e72e82b542fa06724a0d0eceaa7a92b6e779 100644 --- a/CONTRIBUTING.adoc +++ b/CONTRIBUTING.adoc @@ -33,10 +33,10 @@ Merging pull requests once CI is successful: When reviewing a pull request, the end-goal is to suggest useful changes to the author. Reviews should finish with approval unless there are issues that would result in: -. Buggy behaviour. +. Buggy behavior. . Undue maintenance burden. . Breaking with house coding style. -. Pessimisation (i.e. reduction of speed as measured in the projects benchmarks). +. Pessimization (i.e. reduction of speed as measured in the projects benchmarks). . Feature reduction (i.e. it removes some aspect of functionality that a significant minority of users rely on). . Uselessness (i.e. it does not strictly add a feature or fix a known issue). @@ -47,7 +47,7 @@ When reviewing a pull request, the end-goal is to suggest useful changes to the == Helping out -We use https://github.com/paritytech/substrate/labels[labels] to manage PRs and issues and communicate state of a PR. Please familiarize yourself with them. Further more we are organising issues in https://github.com/paritytech/substrate/milestones[milestones]. Best way to get started is to a pick a ticket from the current milestone tagged https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ2-easy[`easy`] or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ3-medium[`medium`] and get going or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AX1-mentor[`mentor`] and get in contact with the mentor offering their support on that larger task. +We use https://github.com/paritytech/substrate/labels[labels] to manage PRs and issues and communicate state of a PR. Please familiarize yourself with them. Furthermore we are organizing issues in https://github.com/paritytech/substrate/milestones[milestones]. Best way to get started is to a pick a ticket from the current milestone tagged https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ2-easy[`easy`] or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ3-medium[`medium`] and get going or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AX1-mentor[`mentor`] and get in contact with the mentor offering their support on that larger task. == Releases diff --git a/Cargo.lock b/Cargo.lock index 7b7cdd902113b6ede422005384128f8bc6840338..9666ce55eaad5c37e4731118f2915258df49ae9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,7 +136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -194,11 +194,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -212,6 +212,11 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitmask" +version = "0.5.0" +source = "git+https://github.com/paritytech/bitmask#c2d8d196e30b018d1385be8357fdca61b978facf" + [[package]] name = "blake2" version = "0.8.0" @@ -325,7 +330,7 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -420,7 +425,7 @@ dependencies = [ "criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -448,12 +453,12 @@ name = "crossbeam" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -491,9 +496,9 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -505,9 +510,9 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -517,7 +522,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -525,8 +530,8 @@ name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -692,7 +697,7 @@ dependencies = [ [[package]] name = "environmental" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -753,7 +758,7 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -793,7 +798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "fork-tree" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -801,7 +806,7 @@ name = "fs-swap" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -898,17 +903,26 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "heapsize" version = "0.4.2" @@ -1058,7 +1072,7 @@ name = "impl-codec" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1161,7 +1175,7 @@ dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1190,11 +1204,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "keccak-hasher" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1248,7 +1262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1272,29 +1286,29 @@ dependencies = [ [[package]] name = "libp2p" -version = "0.4.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-dns 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-floodsub 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-identify 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-kad 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mdns 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mplex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-noise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ping 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-plaintext 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ratelimit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-secio 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-tcp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-uds 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-websocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-yamux 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core-derive 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-dns 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-floodsub 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-kad 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mdns 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mplex 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-noise 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-plaintext 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ratelimit 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-secio 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-tcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-uds 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-websocket 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-yamux 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1307,34 +1321,42 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multistream-select 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-core-derive" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1343,11 +1365,11 @@ dependencies = [ [[package]] name = "libp2p-dns" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1356,7 +1378,7 @@ dependencies = [ [[package]] name = "libp2p-floodsub" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1364,7 +1386,7 @@ dependencies = [ "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1375,13 +1397,13 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1396,18 +1418,19 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-identify 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ping 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1424,13 +1447,13 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1445,13 +1468,13 @@ dependencies = [ [[package]] name = "libp2p-mplex" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1461,28 +1484,31 @@ dependencies = [ [[package]] name = "libp2p-noise" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "snow 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-ping" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1495,22 +1521,22 @@ dependencies = [ [[package]] name = "libp2p-plaintext" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-ratelimit" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1518,23 +1544,22 @@ dependencies = [ [[package]] name = "libp2p-secio" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1545,11 +1570,11 @@ dependencies = [ [[package]] name = "libp2p-tcp" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1559,11 +1584,11 @@ dependencies = [ [[package]] name = "libp2p-uds" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1571,14 +1596,14 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "websocket 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1586,14 +1611,14 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "yamux 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1661,7 +1686,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1687,7 +1712,7 @@ name = "memchr" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1698,10 +1723,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memory-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1782,7 +1807,7 @@ dependencies = [ [[package]] name = "multistream-select" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1807,7 +1832,7 @@ name = "native-tls" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1824,7 +1849,7 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1836,7 +1861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1852,8 +1877,7 @@ dependencies = [ "node-executor 0.1.0", "node-primitives 0.1.0", "node-runtime 0.1.0", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1879,13 +1903,12 @@ version = "0.1.0" dependencies = [ "node-primitives 0.1.0", "node-runtime 0.1.0", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "srml-balances 0.1.0", "srml-consensus 0.1.0", "srml-contract 0.1.0", - "srml-fees 0.1.0", "srml-grandpa 0.1.0", "srml-indices 0.1.0", "srml-session 0.1.0", @@ -1899,7 +1922,7 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1907,7 +1930,7 @@ dependencies = [ name = "node-primitives" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1925,7 +1948,7 @@ dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 0.1.0", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1939,7 +1962,6 @@ dependencies = [ "srml-council 0.1.0", "srml-democracy 0.1.0", "srml-executive 0.1.0", - "srml-fees 0.1.0", "srml-finality-tracker 0.1.0", "srml-grandpa 0.1.0", "srml-indices 0.1.0", @@ -1950,10 +1972,11 @@ dependencies = [ "srml-system 0.1.0", "srml-timestamp 0.1.0", "srml-treasury 0.1.0", - "srml-upgrade-key 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-authorities 0.1.0", "substrate-keyring 0.1.0", + "substrate-offchain-primitives 0.1.0", "substrate-primitives 0.1.0", ] @@ -1967,11 +1990,9 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "node-executor 0.1.0", "node-template-runtime 0.9.0", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "substrate-basic-authorship 0.1.0", "substrate-cli 0.3.0", @@ -1984,7 +2005,7 @@ dependencies = [ "substrate-service 0.3.0", "substrate-transaction-pool 0.1.0", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1992,7 +2013,7 @@ dependencies = [ name = "node-template-runtime" version = "0.9.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2004,7 +2025,6 @@ dependencies = [ "srml-balances 0.1.0", "srml-consensus 0.1.0", "srml-executive 0.1.0", - "srml-fees 0.1.0", "srml-indices 0.1.0", "srml-sudo 0.1.0", "srml-support 0.1.0", @@ -2012,6 +2032,8 @@ dependencies = [ "srml-timestamp 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-authorities 0.1.0", + "substrate-offchain-primitives 0.1.0", "substrate-primitives 0.1.0", ] @@ -2068,6 +2090,9 @@ dependencies = [ name = "once_cell" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "opaque-debug" @@ -2080,9 +2105,9 @@ version = "0.10.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2126,7 +2151,7 @@ source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7 [[package]] name = "parity-codec" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2290,6 +2315,16 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -2567,7 +2602,7 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2634,7 +2669,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2644,7 +2679,7 @@ version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2697,7 +2732,7 @@ dependencies = [ [[package]] name = "rw-stream-sink" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2736,13 +2771,13 @@ name = "schannel" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "schnorrkel" -version = "0.0.0" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2752,6 +2787,7 @@ dependencies = [ "merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2915,7 +2951,7 @@ version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2970,10 +3006,10 @@ dependencies = [ name = "sr-io" version = "0.1.0" dependencies = [ - "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -2989,7 +3025,7 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3003,7 +3039,7 @@ name = "sr-sandbox" version = "0.1.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -3023,7 +3059,7 @@ name = "sr-version" version = "0.1.0" dependencies = [ "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", @@ -3035,7 +3071,7 @@ name = "srml-assets" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", @@ -3050,8 +3086,9 @@ name = "srml-aura" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -3072,7 +3109,7 @@ name = "srml-balances" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -3089,7 +3126,7 @@ name = "srml-consensus" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -3107,7 +3144,7 @@ version = "0.1.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3118,7 +3155,6 @@ dependencies = [ "sr-std 0.1.0", "srml-balances 0.1.0", "srml-consensus 0.1.0", - "srml-fees 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "srml-timestamp 0.1.0", @@ -3131,7 +3167,7 @@ name = "srml-council" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3150,7 +3186,7 @@ name = "srml-democracy" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3168,7 +3204,7 @@ name = "srml-example" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", @@ -3183,51 +3219,32 @@ name = "srml-executive" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-balances 0.1.0", - "srml-fees 0.1.0", "srml-indices 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "substrate-primitives 0.1.0", ] -[[package]] -name = "srml-fees" -version = "0.1.0" -dependencies = [ - "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", - "sr-primitives 0.1.0", - "sr-std 0.1.0", - "srml-support 0.1.0", - "srml-system 0.1.0", - "substrate-primitives 0.1.0", -] - [[package]] name = "srml-finality-tracker" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-session 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "substrate-inherents 0.1.0", @@ -3238,12 +3255,13 @@ dependencies = [ name = "srml-grandpa" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", + "srml-consensus 0.1.0", "srml-finality-tracker 0.1.0", "srml-session 0.1.0", "srml-support 0.1.0", @@ -3257,7 +3275,7 @@ name = "srml-indices" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3275,7 +3293,7 @@ dependencies = [ name = "srml-metadata" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", @@ -3287,7 +3305,8 @@ name = "srml-session" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3306,7 +3325,7 @@ name = "srml-staking" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -3327,7 +3346,7 @@ name = "srml-sudo" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -3343,9 +3362,10 @@ dependencies = [ name = "srml-support" version = "0.1.0" dependencies = [ + "bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3389,12 +3409,25 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "srml-support-test" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "srml-support 0.1.0", + "substrate-inherents 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "srml-system" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3410,12 +3443,11 @@ name = "srml-timestamp" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-consensus 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "substrate-inherents 0.1.0", @@ -3427,7 +3459,7 @@ name = "srml-treasury" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -3439,19 +3471,6 @@ dependencies = [ "substrate-primitives 0.1.0", ] -[[package]] -name = "srml-upgrade-key" -version = "0.1.0" -dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 0.1.0", - "sr-std 0.1.0", - "srml-consensus 0.1.0", - "srml-support 0.1.0", - "srml-system 0.1.0", -] - [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -3549,18 +3568,39 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "strum" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strum_macros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "subkey" -version = "0.1.0" +version = "0.2.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", "substrate-primitives 0.1.0", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate" -version = "0.10.0" +version = "0.11.0" dependencies = [ "ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3574,17 +3614,29 @@ name = "substrate-basic-authorship" version = "0.1.0" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", "substrate-consensus-common 0.1.0", "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", + "substrate-telemetry 0.3.1", "substrate-test-client 0.1.0", "substrate-transaction-pool 0.1.0", ] +[[package]] +name = "substrate-bip39" +version = "0.2.0" +source = "git+https://github.com/paritytech/substrate-bip39#080da45923885cfec2379cef3dee4e7f43e6c260" +dependencies = [ + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-cli" version = "0.3.0" @@ -3598,13 +3650,15 @@ dependencies = [ "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0", + "substrate-keyring 0.1.0", "substrate-network 0.1.0", "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", @@ -3612,6 +3666,7 @@ dependencies = [ "substrate-state-machine 0.1.0", "substrate-telemetry 0.3.1", "sysinfo 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3623,13 +3678,13 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "sr-primitives 0.1.0", @@ -3651,16 +3706,17 @@ name = "substrate-client-db" version = "0.1.0" dependencies = [ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", + "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", @@ -3678,7 +3734,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", @@ -3689,6 +3745,7 @@ dependencies = [ "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", "substrate-consensus-aura-slots 0.1.0", + "substrate-consensus-authorities 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", "substrate-inherents 0.1.0", @@ -3705,6 +3762,7 @@ dependencies = [ name = "substrate-consensus-aura-primitives" version = "0.1.0" dependencies = [ + "sr-primitives 0.1.0", "substrate-client 0.1.0", ] @@ -3715,7 +3773,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", @@ -3726,6 +3784,20 @@ dependencies = [ "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-consensus-authorities" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", + "srml-support 0.1.0", + "substrate-client 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "substrate-consensus-common" version = "0.1.0" @@ -3733,8 +3805,9 @@ dependencies = [ "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", @@ -3752,7 +3825,7 @@ dependencies = [ "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rhododendron 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -3777,10 +3850,10 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3805,7 +3878,7 @@ dependencies = [ "fork-tree 0.1.0", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", @@ -3827,7 +3900,7 @@ dependencies = [ name = "substrate-finality-grandpa-primitives" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "substrate-client 0.1.0", @@ -3838,7 +3911,7 @@ dependencies = [ name = "substrate-inherents" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -3849,7 +3922,9 @@ name = "substrate-keyring" version = "0.1.0" dependencies = [ "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] @@ -3883,7 +3958,7 @@ dependencies = [ "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3892,6 +3967,7 @@ dependencies = [ "substrate-consensus-common 0.1.0", "substrate-keyring 0.1.0", "substrate-network-libp2p 0.1.0", + "substrate-peerset 0.1.0", "substrate-primitives 0.1.0", "substrate-test-client 0.1.0", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3906,8 +3982,8 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3915,6 +3991,8 @@ dependencies = [ "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-peerset 0.1.0", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3922,6 +4000,33 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-offchain" +version = "0.1.0" +dependencies = [ + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "substrate-client 0.1.0", + "substrate-consensus-common 0.1.0", + "substrate-inherents 0.1.0", + "substrate-offchain-primitives 0.1.0", + "substrate-primitives 0.1.0", + "substrate-test-client 0.1.0", + "substrate-transaction-pool 0.1.0", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-offchain-primitives" +version = "0.1.0" +dependencies = [ + "sr-primitives 0.1.0", + "substrate-client 0.1.0", +] + [[package]] name = "substrate-panic-handler" version = "0.1.0" @@ -3930,6 +4035,22 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-peerset" +version = "0.1.0" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-primitives" version = "0.1.0" @@ -3937,23 +4058,27 @@ dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", "substrate-serializer 0.1.0", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3971,12 +4096,13 @@ dependencies = [ "jsonrpc-derive 10.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-client 0.1.0", @@ -3986,6 +4112,7 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-test-client 0.1.0", + "substrate-test-runtime 0.1.0", "substrate-transaction-pool 0.1.0", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4018,9 +4145,9 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4032,8 +4159,10 @@ dependencies = [ "substrate-client-db 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", "substrate-keystore 0.1.0", "substrate-network 0.1.0", + "substrate-offchain 0.1.0", "substrate-primitives 0.1.0", "substrate-rpc-servers 0.1.0", "substrate-telemetry 0.3.1", @@ -4067,7 +4196,7 @@ version = "0.1.0" dependencies = [ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] @@ -4076,24 +4205,24 @@ dependencies = [ name = "substrate-state-machine" version = "0.1.0" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-telemetry" version = "0.3.1" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4111,7 +4240,7 @@ name = "substrate-test-client" version = "0.1.0" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-client-db 0.1.0", @@ -4127,23 +4256,27 @@ dependencies = [ name = "substrate-test-runtime" version = "0.1.0" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", + "srml-executive 0.1.0", "srml-support 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-authorities 0.1.0", "substrate-executor 0.1.0", "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", + "substrate-offchain-primitives 0.1.0", "substrate-primitives 0.1.0", + "substrate-test-client 0.1.0", ] [[package]] @@ -4151,14 +4284,16 @@ name = "substrate-transaction-graph" version = "0.1.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", + "substrate-primitives 0.1.0", "substrate-test-runtime 0.1.0", ] @@ -4169,7 +4304,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", @@ -4184,16 +4319,16 @@ name = "substrate-trie" version = "0.4.0" dependencies = [ "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", - "trie-bench 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-standardmap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-bench 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-standardmap 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4232,7 +4367,7 @@ name = "sysinfo" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4262,7 +4397,7 @@ name = "tempfile" version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4301,7 +4436,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4314,6 +4449,20 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tiny-keccak" version = "1.4.2" @@ -4391,7 +4540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4431,7 +4580,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4546,46 +4695,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "trie-bench" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-standardmap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-standardmap 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-standardmap" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4608,7 +4757,7 @@ name = "twox-hash" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4903,6 +5052,16 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "x25519-dalek" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "xdg" version = "2.2.0" @@ -4915,7 +5074,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "yamux" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4929,6 +5088,11 @@ dependencies = [ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "zeroize" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] "checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" "checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" @@ -4954,6 +5118,7 @@ dependencies = [ "checksum bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebecac13b3c745150d7b6c3ea7572d372f09d627c2077e893bf26c5c7f70d282" "checksum bindgen 0.43.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d52d263eacd15d26cbcf215d254b410bd58212aaa2d3c453a04b2d3b3adcf41" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)" = "" "checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" @@ -4969,7 +5134,7 @@ dependencies = [ "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" "checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" @@ -5009,7 +5174,7 @@ dependencies = [ "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" -"checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" +"checksum environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c7464757b80de8930c91c9afe77ddce501826bf9d134a87db2c67d9dc177e2c" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "87559b08e99a81a92bbb867d237543e43495857749f688e0773390a20d56c61c" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -5033,8 +5198,9 @@ dependencies = [ "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" -"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" -"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07463834729d0ce8d475e7dd6d302e407093ad9a9c02d77eb07fb74b5373829d" +"checksum hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1224388a21c88a80ae7087a2a245ca6d80acc97a9186b75789fb3eeefd0609af" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" @@ -5064,34 +5230,34 @@ dependencies = [ "checksum jsonrpc-server-utils 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5521613b31ea22d36d9f95ad642058dccec846a94ed8690957652d479f620707" "checksum jsonrpc-ws-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20b8333a5a6e6ccbcf5c90f90919de557cba4929efa164e9bd0e8e497eb20e46" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" -"checksum keccak-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb9d3670023f4c04153d90b8a557a822d1b27ed702bb015a87cf7bffead5b611" +"checksum keccak-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a02fb74dc1b613522069b5f2023c014756ce121c6c6fb39364c139b0efc39a2d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" -"checksum libp2p 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395d54c4c96fa175eabf4505e8a7bd616d916fa49fa27c60ceaa6d5d9b51bc" -"checksum libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c8dc95c7fda9de223bc195b637290918e8decb18e63fd3d03005f84b8ce380b" -"checksum libp2p-core-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e9ff3bb639d0be41e1aff9d0d28715e54474e4d15e43aa4865bdec44867d8d3" -"checksum libp2p-dns 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d310aa56671539a2bce6124cf4326482278b0d0b841c3ba1514e44d8597096" -"checksum libp2p-floodsub 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8256d778f0dc087be409d8cbd081a11bc41ea27ddcd4862814e50e8cfa9c6df0" -"checksum libp2p-identify 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d128febfc8fe57b597e627f545bafea43ae009bf85cc9480b583996f244ab685" -"checksum libp2p-kad 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0691fcca7648369798c6466c61139d31dbb7e2afad311e44fcc4e220ce1e4d78" -"checksum libp2p-mdns 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63289f296e39752180d8a45e024cc38d1028a6db41deab3943ff2ccb9d1224cd" -"checksum libp2p-mplex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "791e375a6a230568f0d8f56f6236403de8e4bf4bd870c3c5f605fd1778da70b2" -"checksum libp2p-noise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70d28b0ca9eb9818d45e037b4a8a0915553c5c1f8d878d8d6170f60451ad37d2" -"checksum libp2p-ping 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "53db5fafd4ca0a32f339371198196795b8e14d8ecb360d8d03ada03299c12a10" -"checksum libp2p-plaintext 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4383404cba7e4483e0b7d78b3ac5e66f8b024233a5095df9da65d5a1e975d692" -"checksum libp2p-ratelimit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bad4fe925d50cc886608ab3b3a7a962b5064ecc49db8b66fd063a950d469c757" -"checksum libp2p-secio 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f9a7641a314d54ad7797f0445685818edb4d3c2f21690cea900f12ea73501b" -"checksum libp2p-tcp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4625bedbb083d676903a8ede4c5c42f9bf7bd5dee788f3cba29d8e01b785d253" -"checksum libp2p-uds 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac5f5d900e381b02ebea2f0621555a2f25a7735772355291aeb70fd9e0da3692" -"checksum libp2p-websocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96b6dfdd776a248d7494aeaf22f149b4d5f6784146546bc34f7b094c7162e141" -"checksum libp2p-yamux 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5a6197ae647c963f5a711c6fb00ba07b9a2812df26f6284870221f654fe9313" +"checksum libp2p 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5b9cd37b1ca54fa2fd0bbf0486adf2f55f8994f2be9410b65265050b24709b2" +"checksum libp2p-core 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf9c56e6f04cb649fdeb806e963d2da223e3ed17748d9e924fdb836c09f76307" +"checksum libp2p-core-derive 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "debea88a3d5de9fdaf7082bd6d238f2c4c6a0420f14bdf9e1c1083b3e7c69286" +"checksum libp2p-dns 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350d0018af3668d954f61ce7311e7d64ab7c40f19a8eb895e4750efe24c3455f" +"checksum libp2p-floodsub 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bfbcf36cc58ad5d0252d8ebe9c1a87190693fe2cdbe40fb01d8046779f9a75ad" +"checksum libp2p-identify 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82e98435973e958d7dea3f5074d7fca53d0dfce2e1ac6924119a21c2991fe443" +"checksum libp2p-kad 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92bb0153418eaf0ea549008d1e22748a956c9c36af9374fbe7189d44607c14be" +"checksum libp2p-mdns 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc915d0cde68a05d26a0dcb125eddce7dd2a425e97c5172ac300c1ee8716f55a" +"checksum libp2p-mplex 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "355bb370dd12809792dc020638b280e7aaf8625318018abd311c51affd0a612d" +"checksum libp2p-noise 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e86291401f4a83f9fa81c03f8a7ccf0b03ce6aaa40cba058a7ec1026a65a6fe4" +"checksum libp2p-ping 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3277f1f7eaadf5cdde6a76fb4afbf24e0eda6e2b04f288f526c6fa2e4293a6e" +"checksum libp2p-plaintext 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4842a7ab54c12459b58b9e59cbeb03e3e1fd393fef48079472856f934352772" +"checksum libp2p-ratelimit 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32ba52ee76aaa94af533526ce5a22fbfcc69a560174fccee82f4cdb557411d33" +"checksum libp2p-secio 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00f416e1e3d0214bd7df2be2b6be8ef61771d44292b973c9e02bfbbd7f62fe46" +"checksum libp2p-tcp 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af47af9997d69fc70aa13e6e7cd0d766614ebe74005e69e763221a64d9a0a5ef" +"checksum libp2p-uds 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa72d81501aad6998d3b1b964f68f438ef99c3aaf54d921e144e0477fa87568" +"checksum libp2p-websocket 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "647bd8862afe6e912eb34b7614f731c0ff89e8777b57d9f2f5f0fd593ecc8d9a" +"checksum libp2p-yamux 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbb8d08cb536a964727e77b868a026c6d92993f08e387d49163565575a478d9" "checksum librocksdb-sys 5.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9024327233e7fac7982440f73301c00046d438c5b1011e8f4e394226ce19007" "checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" @@ -5105,7 +5271,7 @@ dependencies = [ "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" +"checksum memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd87d4d64f7b86d8804bbb419f8ecb187cb8f40a50e91c72848075c604ba88d" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" "checksum merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9e97b439f6d38cbe2a4a4aa93f6770c5305f62761b78b1851406c09c87ee2a" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" @@ -5113,7 +5279,7 @@ dependencies = [ "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multistream-select 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ed84364f0e921a32204896952ee80c7befc14a7a39f2c56cd955d71e8dae6" +"checksum multistream-select 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f989d40aab0ed0d83c1cdb4856b5790e980b96548d1a921f280e985eb049f38d" "checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" @@ -5133,7 +5299,7 @@ dependencies = [ "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67a4d27831e31e27f1454d6e3d3bb34bcac6bf7ad7032eed0ad0070dc8cf55c1" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" "checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" "checksum parity-crypto 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b9db194dfbcfe3b398d63d765437a5c7232d59906e203055f0e993f6458ff1" "checksum parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61ae6944d4435d41f4d0f12108c5cbb9207cbb14bc8f2b4984c6e930dc9c8e41" @@ -5148,6 +5314,7 @@ dependencies = [ "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" "checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" @@ -5196,13 +5363,13 @@ dependencies = [ "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "108ad7c3d65ba866ec50a224b7b3b0cb6c682c3d805015cea859d491232346a5" +"checksum rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d548a40fe17c3a77d54b82457b79fcc9b8a288d509ca20fbf5aa1dac386d22d6" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" -"checksum schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe554f318830b48e5da8ab1ccb1ffd02b79228364dac7766b7cd1ec461ca5116" +"checksum schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a700659388785588c75b197cecda0f23c7112a9281ef703e8ffc651061ce014c" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaccd3a23619349e0878d9a241f34b1982343cdf67367058cd7d078d326b63e" "checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" @@ -5237,6 +5404,9 @@ dependencies = [ "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" "checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1810e25f576e7ffce1ff5243b37066da5ded0310b3274c20baaeccb1145b2806" +"checksum strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "572a2f4e53dd4c3483fd79e5cc10ddd773a3acb1169bbfe8762365e107110579" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" @@ -5251,6 +5421,7 @@ dependencies = [ "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1415431cb2398d84da64173f8473c792808314427d4a6f2f3ea85ae67239fe3" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" "checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115" "checksum tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5462b0f968c0457efe38fcd2df7e487096b992419e4f5337b06775a614bbda4b" @@ -5271,10 +5442,10 @@ dependencies = [ "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum trie-bench 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77087d1bce467cf8371a5c0e10e4d925b065ec6cfad8b9cdff1fad4f218c6750" -"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" -"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" -"checksum trie-standardmap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e4729504b8102acb1bef3f16e6b64d41aeb1ff0e329081451e8191df0f61ab2" +"checksum trie-bench 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eafa32a8662c06f5bf135984bc1a12821fd38770b5c2f2f9e8750327fcbe3955" +"checksum trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "843af112ba3a8c919cd961edf3cac9272353f5e277ad8678c7023fa70e5c0e2d" +"checksum trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e45632ecaf2b8b4a40b5208383cd659b4e66f58ccd40086467a4614b45781430" +"checksum trie-standardmap 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006314f54f2ea7944a878e66fd93ad7978095bc355f30a2f26ec40f664d86c86" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" @@ -5315,6 +5486,8 @@ dependencies = [ "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" "checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4aca1ba6bec2719576bd20dfe5b24d9359552e616d10bff257e50cd85f745d17" "checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" -"checksum yamux 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2269402a82beb59192319ad64a199850b6dcf3a14ef941206cdad3d7b9cfb598" +"checksum yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "302defd1bed8a9a6d43b82f0e5a50510dfdfbbd02c270c93ff9d6f3f5e2dea89" +"checksum zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddfeb6eee2fb3b262ef6e0898a52b7563bb8e0d5955a313b3cf2f808246ea14" diff --git a/Cargo.toml b/Cargo.toml index 699f9a158981f0b98c9e511cb81b95892343da1b..b6eac3e381e075e69c457d732a353b287023b16a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ path = "node/src/main.rs" [package] name = "substrate" -version = "0.10.0" +version = "0.11.0" authors = ["Parity Technologies "] build = "build.rs" edition = "2018" @@ -57,6 +57,7 @@ members = [ "srml/support/procedural", "srml/support/procedural/tools", "srml/support/procedural/tools/derive", + "srml/support/test", "srml/assets", "srml/aura", "srml/balances", @@ -66,7 +67,6 @@ members = [ "srml/democracy", "srml/example", "srml/executive", - "srml/fees", "srml/finality-tracker", "srml/grandpa", "srml/indices", @@ -77,7 +77,6 @@ members = [ "srml/system", "srml/timestamp", "srml/treasury", - "srml/upgrade-key", "node/cli", "node/executor", "node/primitives", @@ -101,3 +100,4 @@ is-it-maintained-open-issues = { repository = "paritytech/substrate" } [profile.release] # Substrate runtime requires unwinding. panic = "unwind" + diff --git a/README.adoc b/README.adoc index 4c3fdaf6cc63389052aa8862068426461c8baa82..92a5418170fb961f69424645d8bdb0b3626e7322 100644 --- a/README.adoc +++ b/README.adoc @@ -10,9 +10,9 @@ Substrate is a next-generation framework for blockchain innovation. == Description -At its heart, Substrate is a combination of three technologies: https://webassembly.org/[WebAssembly], https://libp2p.io/[Libp2p] and GRANDPA Consensus. About GRANDPA, see this https://hackmd.io/Jd0byWX0RiqFiXUVC78Bdw?view#GRANDPA[definition], https://medium.com/polkadot-network/grandpa-block-finality-in-polkadot-an-introduction-part-1-d08a24a021b5[introduction] and https://github.com/w3f/consensus/blob/master/pdf/grandpa.pdf[formal specification]. It is both a library for building new blockchains and a "skeleton key" of a blockchain client, able to synchronise to any Substrate-based chain. +At its heart, Substrate is a combination of three technologies: https://webassembly.org/[WebAssembly], https://libp2p.io/[Libp2p] and GRANDPA Consensus. About GRANDPA, see this https://hackmd.io/Jd0byWX0RiqFiXUVC78Bdw?view#GRANDPA[definition], https://medium.com/polkadot-network/grandpa-block-finality-in-polkadot-an-introduction-part-1-d08a24a021b5[introduction] and https://github.com/w3f/consensus/blob/master/pdf/grandpa.pdf[formal specification]. It is both a library for building new blockchains and a "skeleton key" of a blockchain client, able to synchronize to any Substrate-based chain. -Substrate chains have three distinct features that make them "next-generation": a dynamic, self-defining state-transition function; light-client functionality from day one; and a progressive consensus algorithm with fast block production and adaptive, definite finality. The STF, encoded in WebAssembly, is known as the "runtime". This defines the `execute_block` function, and can specify everything from the staking algorithm, transaction semantics, logging mechanisms and procedures for replacing any aspect of itself or of the blockchain's state ("governance"). Because the runtime is entirely dynamic all of these can be switched out or upgraded at any time. A Substrate chain is very much a "living organism". +Substrate chains have three distinct features that make them "next-generation": a dynamic, self-defining state-transition function; light-client functionality from day one; and a progressive consensus algorithm with fast block production and adaptive, definite finality. The STF, encoded in WebAssembly, is known as the "runtime". This defines the `execute_block` function, and can specify everything from the staking algorithm, transaction semantics, logging mechanisms and procedures for replacing any aspect of itself or of the blockchain's state ("governance"). Because the runtime is entirely dynamic all of these can be switched out or upgraded at any time. A Substrate chain is very much a "living organizm". See also https://www.parity.io/what-is-substrate/. @@ -39,7 +39,7 @@ Block := Header + Extrinsics + Justifications === Extrinsics -Extrinsics in Substrate are pieces of information from "the outside world" that are contained in the blocks of the chain. You might think "ahh, that means *transactions*": in fact, no. Extrinsics fall into two broad categories of which only one is *transactions*. The other is known as *inherents*. The difference between these two is that transactions are signed and gossipped on the network and can be deemed useful *per se*. This fits the mould of what you would call transactions in Bitcoin or Ethereum. +Extrinsics in Substrate are pieces of information from "the outside world" that are contained in the blocks of the chain. You might think "ahh, that means *transactions*": in fact, no. Extrinsics fall into two broad categories of which only one is *transactions*. The other is known as *inherents*. The difference between these two is that transactions are signed and gossipped on the network and can be deemed useful *per se*. This fits the mold of what you would call transactions in Bitcoin or Ethereum. Inherents, meanwhile, are not passed on the network and are not signed. They represent data which describes the environment but which cannot call upon anything to prove it such as a signature. Rather they are assumed to be "true" simply because a sufficiently large number of validators have agreed on them being reasonable. @@ -63,16 +63,12 @@ impl_runtime_apis! { VERSION } - fn authorities() -> Vec { - Consensus::authorities() - } - fn execute_block(block: Block) { Executive::execute_block(block) } - fn initialise_block(header: ::Header) { - Executive::initialise_block(&header) + fn initialize_block(header: ::Header) { + Executive::initialize_block(&header) } } // ---snip--- @@ -86,9 +82,9 @@ The Substrate Runtime Module Library includes functionality for timestamps and s === Block-authoring Logic -In Substrate, there is a major distinction between blockchain *syncing* and block *authoring* ("authoring" is a more general term for what is called "mining" in Bitcoin). The first case might be referred to as a "full node" (or "light node" - Substrate supports both): authoring necessarily requires a synced node and, therefore, all authoring clients must necessarily be able to synchronise. However, the reverse is not true. The primary functionality that authoring nodes have which is not in "sync nodes" is threefold: transaction queue logic, inherent transaction knowledge and BFT consensus logic. BFT consensus logic is provided as a core element of Substrate and can be ignored since it is only exposed in the SDK under the `authorities()` API entry. +In Substrate, there is a major distinction between blockchain *syncing* and block *authoring* ("authoring" is a more general term for what is called "mining" in Bitcoin). The first case might be referred to as a "full node" (or "light node" - Substrate supports both): authoring necessarily requires a synced node and, therefore, all authoring clients must necessarily be able to synchronize. However, the reverse is not true. The primary functionality that authoring nodes have which is not in "sync nodes" is threefold: transaction queue logic, inherent transaction knowledge and BFT consensus logic. BFT consensus logic is provided as a core element of Substrate and can be ignored since it is only exposed in the SDK under the `authorities()` API entry. -Transaction queue logic in Substrate is designed to be as generic as possible, allowing a runtime to express which transactions are fit for inclusion in a block through the `initialize_block` and `apply_extrinsic` calls. However, more subtle aspects like prioritisation and replacement policy must currently be expressed "hard coded" as part of the blockchain's authoring code. That said, Substrate's reference implementation for a transaction queue should be sufficient for an initial chain implementation. +Transaction queue logic in Substrate is designed to be as generic as possible, allowing a runtime to express which transactions are fit for inclusion in a block through the `initialize_block` and `apply_extrinsic` calls. However, more subtle aspects like prioritization and replacement policy must currently be expressed "hard coded" as part of the blockchain's authoring code. That said, Substrate's reference implementation for a transaction queue should be sufficient for an initial chain implementation. Inherent extrinsic knowledge is again somewhat generic, and the actual construction of the extrinsics is, by convention, delegated to the "soft code" in the runtime. If ever there needs to be additional extrinsic information in the chain, then both the block authoring logic will need to be altered to provide it into the runtime and the runtime's `inherent_extrinsics` call will need to use this extra information in order to construct any additional extrinsic transactions for inclusion in the block. @@ -167,7 +163,7 @@ It won't do much until you start producing blocks though, so to do that you'll n substrate --chain ~/mychain.json --validator --key ... ---- -You can distribute `mychain.json` so that everyone can synchronise and (depending on your authorities list) validate on your chain. +You can distribute `mychain.json` so that everyone can synchronize and (depending on your authorities list) validate on your chain. == Building @@ -237,11 +233,13 @@ Then build the code: cargo build # Builds all native code ---- -You can run the tests if you like: +You can run all the tests if you like: [source, shell] cargo test --all +Or just run the tests of a specific package (i.e. `cargo test -p srml-assets`) + You can start a development chain with: [source, shell] @@ -257,8 +255,7 @@ We'll start Alice's substrate node first on default TCP port 30333 with her chai cargo run --release \-- \ --base-path /tmp/alice \ --chain=local \ - --key Alice \ - --name "ALICE" \ + --alice \ --node-key 0000000000000000000000000000000000000000000000000000000000000001 \ --telemetry-url ws://telemetry.polkadot.io:1024 \ --validator @@ -270,8 +267,7 @@ cargo run --release \-- \ --base-path /tmp/bob \ --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/QmQZ8TjTqeDj3ciwr93EJ95hxfDsb9pEYDizUAbWpigtQN \ --chain=local \ - --key Bob \ - --name "BOB" \ + --bob \ --port 30334 \ --telemetry-url ws://telemetry.polkadot.io:1024 \ --validator diff --git a/build.rs b/build.rs index 7dd666310f77449dcc2605bd58b50cef763722a4..273700c525c883579880be28b231a5f14e43c6d7 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ use vergen::{ConstantsFlags, generate_cargo_keys}; -const ERROR_MSG: &'static str = "Failed to generate metadata files"; +const ERROR_MSG: &str = "Failed to generate metadata files"; fn main() { generate_cargo_keys(ConstantsFlags::all()).expect(ERROR_MSG); diff --git a/core/basic-authorship/Cargo.toml b/core/basic-authorship/Cargo.toml index 82187db8031f853dd0518e2c2aaf3d9e185803e2..d173ac66ee2439da99f2257663c030bbe58c13e3 100644 --- a/core/basic-authorship/Cargo.toml +++ b/core/basic-authorship/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] log = "0.4" -codec = { package = "parity-codec", version = "3.0" } +codec = { package = "parity-codec", version = "3.2" } runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } client = { package = "substrate-client", path = "../../core/client" } aura_primitives = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives" } @@ -14,6 +14,7 @@ consensus_common = { package = "substrate-consensus-common", path = "../../core/ primitives = { package = "substrate-primitives", path = "../../core/primitives" } inherents = { package = "substrate-inherents", path = "../inherents" } transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +substrate-telemetry = { path = "../telemetry" } [dev-dependencies] test-client = { package = "substrate-test-client", path = "../../core/test-client" } diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index 728ef3c0679952e263d451d13effd52474f125ac..e9b6c909ad41f556488bd8ad6cb6ca7452896450 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ // use std::{self, time, sync::Arc}; -use log::{info, debug}; +use log::{info, debug, warn, trace}; use client::{ self, error, Client as SubstrateClient, CallExecutor, @@ -28,15 +28,15 @@ use client::{ }; use codec::Decode; use consensus_common::{self, evaluation}; -use primitives::{H256, Blake2Hasher}; +use primitives::{H256, Blake2Hasher, ExecutionContext}; use runtime_primitives::traits::{ Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, AuthorityIdFor }; -use runtime_primitives::ExecutionContext; use runtime_primitives::generic::BlockId; use runtime_primitives::ApplyError; use transaction_pool::txpool::{self, Pool as TransactionPool}; -use inherents::InherentData; +use inherents::{InherentData, pool::InherentsPool}; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; /// Build new blocks. pub trait BlockBuilder { @@ -114,6 +114,8 @@ pub struct ProposerFactory where A: txpool::ChainApi { pub client: Arc, /// The transaction pool. pub transaction_pool: Arc>, + /// The inherents pool + pub inherents_pool: Arc::Extrinsic>>, } impl consensus_common::Environment<::Block> for ProposerFactory where @@ -143,6 +145,7 @@ impl consensus_common::Environment<::Block> for Propose parent_id: id, parent_number: *parent_header.number(), transaction_pool: self.transaction_pool.clone(), + inherents_pool: self.inherents_pool.clone(), now: Box::new(time::Instant::now), }; @@ -157,6 +160,7 @@ pub struct Proposer { parent_id: BlockId, parent_number: <::Header as HeaderT>::Number, transaction_pool: Arc>, + inherents_pool: Arc::Extrinsic>>, now: Box time::Instant>, } @@ -173,7 +177,7 @@ impl consensus_common::Proposer<::Block> for Pro fn propose(&self, inherent_data: InherentData, max_duration: time::Duration) -> Result<::Block, error::Error> { - // leave some time for evaluation and block finalisation (33%) + // leave some time for evaluation and block finalization (33%) let deadline = (self.now)() + max_duration - max_duration / 3; self.propose_with(inherent_data, deadline) } @@ -193,24 +197,37 @@ impl Proposer where /// If the block is full we will attempt to push at most /// this number of transactions before quitting for real. - /// It allows us to increase block utilisation. + /// It allows us to increase block utilization. const MAX_SKIPPED_TRANSACTIONS: usize = 8; let block = self.client.build_block( &self.parent_id, inherent_data, |block_builder| { + // Add inherents from the internal pool + + let inherents = self.inherents_pool.drain(); + debug!("Pushing {} queued inherents.", inherents.len()); + for i in inherents { + if let Err(e) = block_builder.push_extrinsic(i) { + warn!("Error while pushing inherent extrinsic from the pool: {:?}", e); + } + } + + // proceed with transactions let mut is_first = true; let mut skipped = 0; let mut unqueue_invalid = Vec::new(); let pending_iterator = self.transaction_pool.ready(); + debug!("Attempting to push transactions from the pool."); for pending in pending_iterator { if (self.now)() > deadline { debug!("Consensus deadline reached when pushing block transactions, proceeding with proposing."); break; } + trace!("[{:?}] Pushing to the block.", pending.hash); match block_builder.push_extrinsic(pending.data.clone()) { Ok(()) => { debug!("[{:?}] Pushed to the block.", pending.hash); @@ -252,6 +269,10 @@ impl Proposer where .collect::>() .join(", ") ); + telemetry!(CONSENSUS_INFO; "prepared_block_for_proposing"; + "number" => ?block.header().number(), + "hash" => ?<::Block as BlockT>::Hash::from(block.header().hash()), + ); let substrate_block = Decode::decode(&mut block.encode().as_slice()) .expect("blocks are defined to serialize to substrate blocks correctly; qed"); @@ -273,17 +294,16 @@ mod tests { use codec::Encode; use std::cell::RefCell; use consensus_common::{Environment, Proposer}; - use test_client::keyring::Keyring; - use test_client::{self, runtime::{Extrinsic, Transfer}}; + use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; fn extrinsic(nonce: u64) -> Extrinsic { let tx = Transfer { amount: Default::default(), nonce, - from: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) } @@ -299,6 +319,7 @@ mod tests { let proposer_factory = ProposerFactory { client: client.clone(), transaction_pool: txpool.clone(), + inherents_pool: Default::default(), }; let mut proposer = proposer_factory.init( @@ -321,4 +342,32 @@ mod tests { assert_eq!(txpool.ready().count(), 2); } + #[test] + fn should_include_inherents_from_the_pool() { + // given + let client = Arc::new(test_client::new()); + let chain_api = transaction_pool::ChainApi::new(client.clone()); + let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); + let inpool = Arc::new(InherentsPool::default()); + + let proposer_factory = ProposerFactory { + client: client.clone(), + transaction_pool: txpool.clone(), + inherents_pool: inpool.clone(), + }; + + inpool.add(extrinsic(0)); + + let proposer = proposer_factory.init( + &client.header(&BlockId::number(0)).unwrap().unwrap(), + &[] + ).unwrap(); + + // when + let deadline = time::Duration::from_secs(3); + let block = proposer.propose(Default::default(), deadline).unwrap(); + + // then + assert_eq!(block.extrinsics().len(), 1); + } } diff --git a/core/basic-authorship/src/lib.rs b/core/basic-authorship/src/lib.rs index a4f6afb8f86102ce137eb99cf5d85802c28d8e89..88a55c3bac4fa22bb21e42e9c66398a6e286b575 100644 --- a/core/basic-authorship/src/lib.rs +++ b/core/basic-authorship/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/cli/Cargo.toml b/core/cli/Cargo.toml index fa117969026a6c30cad62aa6859e2eb48393a9d1..c5bf34063d8066fff85fd6954b3d67c52399f9e8 100644 --- a/core/cli/Cargo.toml +++ b/core/cli/Cargo.toml @@ -14,12 +14,13 @@ atty = "0.2" regex = "1" time = "0.1" ansi_term = "0.11" -lazy_static = "1.0" +lazy_static = "1.3" app_dirs = "1.2" tokio = "0.1.7" futures = "0.1.17" fdlimit = "0.1" exit-future = "0.1" +serde_json = "1.0" sysinfo = "0.8.0" panic-handler = { package = "substrate-panic-handler", path = "../../core/panic-handler" } client = { package = "substrate-client", path = "../../core/client" } @@ -29,5 +30,9 @@ primitives = { package = "substrate-primitives", path = "../../core/primitives" service = { package = "substrate-service", path = "../../core/service" } state-machine = { package = "substrate-state-machine", path = "../../core/state-machine" } substrate-telemetry = { path = "../../core/telemetry" } +keyring = { package = "substrate-keyring", path = "../keyring" } names = "0.11.0" structopt = "0.2" + +[dev-dependencies] +tempdir = "0.3" diff --git a/core/cli/src/error.rs b/core/cli/src/error.rs index b9a036ce1c7a2e02550be81f16317c858f54e124..e368cc6d9670a59adaf2975de4f69421948fbb14 100644 --- a/core/cli/src/error.rs +++ b/core/cli/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/cli/src/informant.rs b/core/cli/src/informant.rs index 6b65606bba5332173df917c70a6eaeab5502483f..260615b2c1cb626429c14e95cc51baceda08d4b1 100644 --- a/core/cli/src/informant.rs +++ b/core/cli/src/informant.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -82,9 +82,12 @@ pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExe (proc.cpu_usage(), proc.memory()) } else { (0.0, 0) }; + let network_state = serde_json::to_string(&network.network_state()).unwrap_or_default(); + telemetry!( SUBSTRATE_INFO; "system.interval"; + "network_state" => network_state, "status" => format!("{}{}", status, target), "peers" => num_peers, "height" => best_number, diff --git a/core/cli/src/lib.rs b/core/cli/src/lib.rs index 4fb0647cad303a95a473d511aba0eda266e15ae1..d2c3cccebeccb8ffc1705090540421ae3b3e4551 100644 --- a/core/cli/src/lib.rs +++ b/core/cli/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -32,7 +32,8 @@ use service::{ FactoryGenesis, PruningMode, ChainSpec, }; use network::{ - Protocol, config::{NetworkConfiguration, NonReservedPeerMode, Secret}, + self, multiaddr::Protocol, + config::{NetworkConfiguration, NonReservedPeerMode, NodeKeyConfig}, build_multiaddr, }; use primitives::H256; @@ -50,6 +51,7 @@ pub use structopt::clap::App; use params::{ RunCmd, PurgeChainCmd, RevertCmd, ImportBlocksCmd, ExportBlocksCmd, BuildSpecCmd, NetworkConfigurationParams, SharedParams, MergeParameters, TransactionPoolParams, + NodeKeyParams, NodeKeyType }; pub use params::{NoCustom, CoreParams}; pub use traits::{GetLogFilter, AugmentClap}; @@ -61,7 +63,18 @@ use lazy_static::lazy_static; use futures::Future; use substrate_telemetry::TelemetryEndpoints; -const MAX_NODE_NAME_LENGTH: usize = 32; +/// The maximum number of characters for a node name. +const NODE_NAME_MAX_LENGTH: usize = 32; + +/// The file name of the node's Secp256k1 secret key inside the chain-specific +/// network config directory, if neither `--node-key` nor `--node-key-file` +/// is specified in combination with `--node-key-type=secp256k1`. +const NODE_KEY_SECP256K1_FILE: &str = "secret"; + +/// The file name of the node's Ed25519 secret key inside the chain-specific +/// network config directory, if neither `--node-key` nor `--node-key-file` +/// is specified in combination with `--node-key-type=ed25519`. +const NODE_KEY_ED25519_FILE: &str = "secret_ed25519"; /// Executable version. Used to pass version information from the root crate. pub struct VersionInfo { @@ -101,7 +114,7 @@ fn generate_node_name() -> String { let node_name = Generator::with_naming(Name::Numbered).next().unwrap(); let count = node_name.chars().count(); - if count < MAX_NODE_NAME_LENGTH { + if count < NODE_NAME_MAX_LENGTH { break node_name } }; @@ -133,14 +146,14 @@ fn base_path(cli: &SharedParams, version: &VersionInfo) -> PathBuf { ) } -fn create_input_err>(msg: T) -> error::Error { +fn input_err>(msg: T) -> error::Error { error::ErrorKind::Input(msg.into()).into() } /// Check whether a node name is considered as valid fn is_node_name_valid(_name: &str) -> Result<(), &str> { let name = _name.to_string(); - if name.chars().count() >= MAX_NODE_NAME_LENGTH { + if name.chars().count() >= NODE_NAME_MAX_LENGTH { return Err("Node name too long"); } @@ -231,14 +244,60 @@ where } } -fn parse_node_key(key: Option) -> error::Result> { - match key.map(|k| H256::from_str(&k)) { - Some(Ok(secret)) => Ok(Some(secret.into())), - Some(Err(err)) => Err(create_input_err(format!("Error parsing node key: {}", err))), - None => Ok(None), +/// Create a `NodeKeyConfig` from the given `NodeKeyParams` in the context +/// of an optional network config storage directory. +fn node_key_config

(params: NodeKeyParams, net_config_dir: &Option

) + -> error::Result +where + P: AsRef +{ + match params.node_key_type { + NodeKeyType::Secp256k1 => + params.node_key.as_ref().map(parse_secp256k1_secret).unwrap_or_else(|| + Ok(params.node_key_file + .or_else(|| net_config_file(net_config_dir, NODE_KEY_SECP256K1_FILE)) + .map(network::Secret::File) + .unwrap_or(network::Secret::New))) + .map(NodeKeyConfig::Secp256k1), + + NodeKeyType::Ed25519 => + params.node_key.as_ref().map(parse_ed25519_secret).unwrap_or_else(|| + Ok(params.node_key_file + .or_else(|| net_config_file(net_config_dir, NODE_KEY_ED25519_FILE)) + .map(network::Secret::File) + .unwrap_or(network::Secret::New))) + .map(NodeKeyConfig::Ed25519) } } +fn net_config_file

(net_config_dir: &Option

, name: &str) -> Option +where + P: AsRef +{ + net_config_dir.as_ref().map(|d| d.as_ref().join(name)) +} + +/// Create an error caused by an invalid node key argument. +fn invalid_node_key(e: impl std::fmt::Display) -> error::Error { + input_err(format!("Invalid node key: {}", e)) +} + +/// Parse a Secp256k1 secret key from a hex string into a `network::Secret`. +fn parse_secp256k1_secret(hex: &String) -> error::Result { + H256::from_str(hex).map_err(invalid_node_key).and_then(|bytes| + network::identity::secp256k1::SecretKey::from_bytes(bytes) + .map(network::Secret::Input) + .map_err(invalid_node_key)) +} + +/// Parse a Ed25519 secret key from a hex string into a `network::Secret`. +fn parse_ed25519_secret(hex: &String) -> error::Result { + H256::from_str(&hex).map_err(invalid_node_key).and_then(|bytes| + network::identity::ed25519::SecretKey::from_bytes(bytes) + .map(network::Secret::Input) + .map_err(invalid_node_key)) +} + /// Fill the given `PoolConfiguration` by looking at the cli parameters. fn fill_transaction_pool_configuration( options: &mut FactoryFullConfiguration, @@ -295,11 +354,13 @@ fn fill_network_configuration( config.public_addresses = Vec::new(); config.client_version = client_id; - config.use_secret = parse_node_key(cli.node_key)?; + config.node_key = node_key_config(cli.node_key_params, &config.net_config_path)?; config.in_peers = cli.in_peers; config.out_peers = cli.out_peers; + config.enable_mdns = !cli.no_mdns; + Ok(()) } @@ -317,14 +378,14 @@ where config.impl_commit = version.commit; config.impl_version = version.version; - config.name = match cli.name { + config.name = match cli.name.or(cli.keyring.account.map(|a| a.to_string())) { None => generate_node_name(), Some(name) => name, }; match is_node_name_valid(&config.name) { Ok(_) => (), Err(msg) => bail!( - create_input_err( + input_err( format!("Invalid node name '{}'. Reason: {}. If unsure, use none.", config.name, msg @@ -347,7 +408,7 @@ where Some(ref s) if s == "archive" => PruningMode::ArchiveAll, None => PruningMode::default(), Some(s) => PruningMode::keep_blocks( - s.parse().map_err(|_| create_input_err("Invalid pruning mode specified"))? + s.parse().map_err(|_| input_err("Invalid pruning mode specified"))? ), }; @@ -360,14 +421,25 @@ where service::Roles::FULL }; + let exec = cli.execution_strategies; config.execution_strategies = ExecutionStrategies { - syncing: cli.syncing_execution.into(), - importing: cli.importing_execution.into(), - block_construction: cli.block_construction_execution.into(), - other: cli.other_execution.into(), + syncing: exec.syncing_execution.into(), + importing: exec.importing_execution.into(), + block_construction: exec.block_construction_execution.into(), + offchain_worker: exec.offchain_worker_execution.into(), + other: exec.other_execution.into(), + }; + + config.offchain_worker = match (cli.offchain_worker, role) { + (params::OffchainWorkerEnabled::WhenValidating, service::Roles::AUTHORITY) => true, + (params::OffchainWorkerEnabled::Always, _) => true, + (params::OffchainWorkerEnabled::Never, _) => false, + (params::OffchainWorkerEnabled::WhenValidating, _) => false, }; config.roles = role; + config.disable_grandpa = cli.no_grandpa; + let client_id = config.client_id(); fill_network_configuration( cli.network_config, @@ -387,7 +459,11 @@ where } if cli.shared_params.dev { - config.keys.push("Alice".into()); + config.keys.push("//Alice".into()); + } + + if let Some(account) = cli.keyring.account { + config.keys.push(format!("//{}", account)); } let rpc_interface: &str = if cli.rpc_external { "0.0.0.0" } else { "127.0.0.1" }; @@ -407,6 +483,8 @@ where config.telemetry_endpoints = Some(TelemetryEndpoints::new(cli.telemetry_endpoints)); } + config.force_authoring = cli.force_authoring; + Ok(config) } @@ -439,23 +517,19 @@ where // 9926-9949 Unassigned fn with_default_boot_node( - mut spec: ChainSpec>, - cli: &BuildSpecCmd, + spec: &mut ChainSpec>, + cli: BuildSpecCmd, version: &VersionInfo, -) -> error::Result>> +) -> error::Result<()> where F: ServiceFactory { if spec.boot_nodes().is_empty() { - let network_path = - Some(network_path(&base_path(&cli.shared_params, version), spec.id()).to_string_lossy().into()); - let network_key = parse_node_key(cli.node_key.clone())?; - - let network_keys = - network::obtain_private_key(&network_key, &network_path) - .map_err(|err| format!("Error obtaining network key: {}", err))?; - - let peer_id = network_keys.to_peer_id(); + let base_path = base_path(&cli.shared_params, version); + let storage_path = network_path(&base_path, spec.id()); + let node_key = node_key_config(cli.node_key_params, &Some(storage_path))?; + let keys = node_key.into_keypair()?; + let peer_id = keys.public().into_peer_id(); let addr = build_multiaddr![ Ip4([127, 0, 0, 1]), Tcp(30333u16), @@ -463,7 +537,7 @@ where ]; spec.add_boot_node(addr) } - Ok(spec) + Ok(()) } fn build_spec( @@ -476,9 +550,10 @@ where S: FnOnce(&str) -> Result>>, String>, { info!("Building chain spec"); - let spec = load_spec(&cli.shared_params, spec_factory)?; - let spec = with_default_boot_node::(spec, &cli, version)?; - let json = service::chain_ops::build_spec::>(spec, cli.raw)?; + let raw_output = cli.raw; + let mut spec = load_spec(&cli.shared_params, spec_factory)?; + with_default_boot_node::(&mut spec, cli, version)?; + let json = service::chain_ops::build_spec::>(spec, raw_output)?; print!("{}", json); @@ -574,23 +649,28 @@ where S: FnOnce(&str) -> Result>>, String>, { let config = create_config_with_db_path::(spec_factory, &cli.shared_params, version)?; - let db_path = config.database_path; - print!("Are you sure to remove {:?}? (y/n)", &db_path); - stdout().flush().expect("failed to flush stdout"); - - let mut input = String::new(); - stdin().read_line(&mut input)?; - let input = input.trim(); - - match input.chars().nth(0) { - Some('y') | Some('Y') => { - fs::remove_dir_all(&db_path)?; - println!("{:?} removed.", &db_path); - }, - _ => println!("Aborted"), + + if cli.yes == false { + print!("Are you sure to remove {:?}? (y/n)", &db_path); + stdout().flush().expect("failed to flush stdout"); + + let mut input = String::new(); + stdin().read_line(&mut input)?; + let input = input.trim(); + + match input.chars().nth(0) { + Some('y') | Some('Y') => {}, + _ => { + println!("Aborted"); + return Ok(()); + }, + } } + fs::remove_dir_all(&db_path)?; + println!("{:?} removed.", &db_path); + Ok(()) } @@ -698,6 +778,8 @@ fn kill_color(s: &str) -> String { #[cfg(test)] mod tests { use super::*; + use tempdir::TempDir; + use network::identity::{secp256k1, ed25519}; #[test] fn tests_node_name_good() { @@ -713,4 +795,111 @@ mod tests { assert!(is_node_name_valid("www.visit.me").is_err()); assert!(is_node_name_valid("email@domain").is_err()); } + + #[test] + fn test_node_key_config_input() { + fn secret_input(net_config_dir: Option) -> error::Result<()> { + NodeKeyType::variants().into_iter().try_for_each(|t| { + let node_key_type = NodeKeyType::from_str(t).unwrap(); + let sk = match node_key_type { + NodeKeyType::Secp256k1 => secp256k1::SecretKey::generate().as_ref().to_vec(), + NodeKeyType::Ed25519 => ed25519::SecretKey::generate().as_ref().to_vec() + }; + let params = NodeKeyParams { + node_key_type, + node_key: Some(format!("{:x}", H256::from_slice(sk.as_ref()))), + node_key_file: None + }; + node_key_config(params, &net_config_dir).and_then(|c| match c { + NodeKeyConfig::Secp256k1(network::Secret::Input(ref ski)) + if node_key_type == NodeKeyType::Secp256k1 && + &sk[..] == ski.as_ref() => Ok(()), + NodeKeyConfig::Ed25519(network::Secret::Input(ref ski)) + if node_key_type == NodeKeyType::Ed25519 && + &sk[..] == ski.as_ref() => Ok(()), + _ => Err(input_err("Unexpected node key config")) + }) + }) + } + + assert!(secret_input(None).is_ok()); + assert!(secret_input(Some("x".to_string())).is_ok()); + } + + #[test] + fn test_node_key_config_file() { + fn secret_file(net_config_dir: Option) -> error::Result<()> { + NodeKeyType::variants().into_iter().try_for_each(|t| { + let node_key_type = NodeKeyType::from_str(t).unwrap(); + let tmp = TempDir::new("alice")?; + let file = tmp.path().join(format!("{}_mysecret", t)).to_path_buf(); + let params = NodeKeyParams { + node_key_type, + node_key: None, + node_key_file: Some(file.clone()) + }; + node_key_config(params, &net_config_dir).and_then(|c| match c { + NodeKeyConfig::Secp256k1(network::Secret::File(ref f)) + if node_key_type == NodeKeyType::Secp256k1 && f == &file => Ok(()), + NodeKeyConfig::Ed25519(network::Secret::File(ref f)) + if node_key_type == NodeKeyType::Ed25519 && f == &file => Ok(()), + _ => Err(input_err("Unexpected node key config")) + }) + }) + } + + assert!(secret_file(None).is_ok()); + assert!(secret_file(Some("x".to_string())).is_ok()); + } + + #[test] + fn test_node_key_config_default() { + fn with_def_params(f: F) -> error::Result<()> + where + F: Fn(NodeKeyParams) -> error::Result<()> + { + NodeKeyType::variants().into_iter().try_for_each(|t| { + let node_key_type = NodeKeyType::from_str(t).unwrap(); + f(NodeKeyParams { + node_key_type, + node_key: None, + node_key_file: None + }) + }) + } + + fn no_config_dir() -> error::Result<()> { + with_def_params(|params| { + let typ = params.node_key_type; + node_key_config::(params, &None) + .and_then(|c| match c { + NodeKeyConfig::Secp256k1(network::Secret::New) + if typ == NodeKeyType::Secp256k1 => Ok(()), + NodeKeyConfig::Ed25519(network::Secret::New) + if typ == NodeKeyType::Ed25519 => Ok(()), + _ => Err(input_err("Unexpected node key config")) + }) + }) + } + + fn some_config_dir(net_config_dir: String) -> error::Result<()> { + with_def_params(|params| { + let dir = PathBuf::from(net_config_dir.clone()); + let typ = params.node_key_type; + node_key_config(params, &Some(net_config_dir.clone())) + .and_then(move |c| match c { + NodeKeyConfig::Secp256k1(network::Secret::File(ref f)) + if typ == NodeKeyType::Secp256k1 && + f == &dir.join(NODE_KEY_SECP256K1_FILE) => Ok(()), + NodeKeyConfig::Ed25519(network::Secret::File(ref f)) + if typ == NodeKeyType::Ed25519 && + f == &dir.join(NODE_KEY_ED25519_FILE) => Ok(()), + _ => Err(input_err("Unexpected node key config")) + }) + }) + } + + assert!(no_config_dir().is_ok()); + assert!(some_config_dir("x".to_string()).is_ok()); + } } diff --git a/core/cli/src/params.rs b/core/cli/src/params.rs index 26a9a00ebf0a00d271b0036a2ff2958054962680..321cf17efb39cff59dd950dcd4d6b95df4cb7388 100644 --- a/core/cli/src/params.rs +++ b/core/cli/src/params.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ use crate::traits::{AugmentClap, GetLogFilter}; use std::path::PathBuf; -use structopt::{StructOpt, clap::{arg_enum, _clap_count_exprs, App, AppSettings, SubCommand}}; +use structopt::{StructOpt, clap::{arg_enum, _clap_count_exprs, App, AppSettings, SubCommand, Arg}}; use client; /// Auxialary macro to implement `GetLogFilter` for all types that have the `shared_params` field. @@ -39,6 +39,7 @@ arg_enum! { Wasm, Both, NativeElseWasm, + NativeWhenPossible, } } @@ -49,10 +50,21 @@ impl Into for ExecutionStrategy { ExecutionStrategy::Wasm => client::ExecutionStrategy::AlwaysWasm, ExecutionStrategy::Both => client::ExecutionStrategy::Both, ExecutionStrategy::NativeElseWasm => client::ExecutionStrategy::NativeElseWasm, + ExecutionStrategy::NativeWhenPossible => client::ExecutionStrategy::NativeWhenPossible, } } } +arg_enum! { + /// How to execute blocks + #[derive(Debug, Clone)] + pub enum OffchainWorkerEnabled { + Always, + Never, + WhenValidating, + } +} + /// Shared parameters used by all `CoreParams`. #[derive(Debug, StructOpt, Clone)] pub struct SharedParams { @@ -68,7 +80,7 @@ pub struct SharedParams { #[structopt(long = "base-path", short = "d", value_name = "PATH", parse(from_os_str))] pub base_path: Option, - ///Sets a custom logging filter + /// Sets a custom logging filter #[structopt(short = "l", long = "log", value_name = "LOG_PATTERN")] pub log: Option, } @@ -98,10 +110,6 @@ pub struct NetworkConfigurationParams { #[structopt(long = "port", value_name = "PORT")] pub port: Option, - /// Specify node secret key (64-character hex string) - #[structopt(long = "node-key", value_name = "KEY")] - pub node_key: Option, - /// Specify the number of outgoing connections we're trying to maintain #[structopt(long = "out-peers", value_name = "OUT_PEERS", default_value = "25")] pub out_peers: u32, @@ -109,6 +117,98 @@ pub struct NetworkConfigurationParams { /// Specify the maximum number of incoming connections we're accepting #[structopt(long = "in-peers", value_name = "IN_PEERS", default_value = "25")] pub in_peers: u32, + + /// By default, the network will use mDNS to discover other nodes on the local network. This + /// disables it. + #[structopt(long = "no-mdns")] + pub no_mdns: bool, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub node_key_params: NodeKeyParams +} + +arg_enum! { + #[derive(Debug, Copy, Clone, PartialEq, Eq)] + pub enum NodeKeyType { + Secp256k1, + Ed25519 + } +} + +/// Parameters used to create the `NodeKeyConfig`, which determines the keypair +/// used for libp2p networking. +#[derive(Debug, StructOpt, Clone)] +pub struct NodeKeyParams { + /// The secret key to use for libp2p networking. + /// + /// The value is a string that is parsed according to the choice of + /// `--node-key-type` as follows: + /// + /// `secp256k1`: + /// The value is parsed as a hex-encoded Secp256k1 32 bytes secret key, + /// i.e. 64 hex characters. + /// + /// `ed25519`: + /// The value is parsed as a hex-encoded Ed25519 32 bytes secret key, + /// i.e. 64 hex characters. + /// + /// The value of this option takes precedence over `--node-key-file`. + /// + /// WARNING: Secrets provided as command-line arguments are easily exposed. + /// Use of this option should be limited to development and testing. To use + /// an externally managed secret key, use `--node-key-file` instead. + #[structopt(long = "node-key", value_name = "KEY")] + pub node_key: Option, + + /// The type of secret key to use for libp2p networking. + /// + /// The secret key of the node is obtained as follows: + /// + /// * If the `--node-key` option is given, the value is parsed as a secret key + /// according to the type. See the documentation for `--node-key`. + /// + /// * If the `--node-key-file` option is given, the secret key is read from the + /// specified file. See the documentation for `--node-key-file`. + /// + /// * Otherwise, the secret key is read from a file with a predetermined, + /// type-specific name from the chain-specific network config directory + /// inside the base directory specified by `--base-dir`. If this file does + /// not exist, it is created with a newly generated secret key of the + /// chosen type. + /// + /// The node's secret key determines the corresponding public key and hence the + /// node's peer ID in the context of libp2p. + /// + /// NOTE: The current default key type is `secp256k1` for a transition period only + /// but will eventually change to `ed25519` in a future release. To continue using + /// `secp256k1` keys, use `--node-key-type=secp256k1`. + #[structopt( + long = "node-key-type", + value_name = "TYPE", + raw( + possible_values = "&NodeKeyType::variants()", + case_insensitive = "true", + default_value = r#""Secp256k1""# + ) + )] + pub node_key_type: NodeKeyType, + + /// The file from which to read the node's secret key to use for libp2p networking. + /// + /// The contents of the file are parsed according to the choice of `--node-key-type` + /// as follows: + /// + /// `secp256k1`: + /// The file must contain an unencoded 32 bytes Secp256k1 secret key. + /// + /// `ed25519`: + /// The file must contain an unencoded 32 bytes Ed25519 secret key. + /// + /// If the file does not exist, it is created with a newly generated secret key of + /// the chosen type. + #[structopt(long = "node-key-file", value_name = "FILE")] + pub node_key_file: Option } /// Parameters used to create the pool configuration. @@ -122,6 +222,70 @@ pub struct TransactionPoolParams { pub pool_kbytes: usize, } +/// Execution strategies parameters. +#[derive(Debug, StructOpt, Clone)] +pub struct ExecutionStrategies { + /// The means of execution used when calling into the runtime while syncing blocks. + #[structopt( + long = "syncing-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""NativeElseWasm""# + ) + )] + pub syncing_execution: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while importing blocks. + #[structopt( + long = "importing-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""NativeElseWasm""# + ) + )] + pub importing_execution: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while constructing blocks. + #[structopt( + long = "block-construction-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""Wasm""# + ) + )] + pub block_construction_execution: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while constructing blocks. + #[structopt( + long = "offchain-worker-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""NativeWhenPossible""# + ) + )] + pub offchain_worker_execution: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while not syncing, importing or constructing blocks. + #[structopt( + long = "other-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""Wasm""# + ) + )] + pub other_execution: ExecutionStrategy, +} + /// The `run` command used to run a node. #[derive(Debug, StructOpt, Clone)] pub struct RunCmd { @@ -137,6 +301,10 @@ pub struct RunCmd { #[structopt(long = "validator")] pub validator: bool, + /// Disable GRANDPA when running in validator mode + #[structopt(long = "no-grandpa")] + pub no_grandpa: bool, + /// Run in light client mode #[structopt(long = "light")] pub light: bool, @@ -169,7 +337,7 @@ pub struct RunCmd { #[structopt(long = "name", value_name = "NAME")] pub name: Option, - /// Should not connect to the Substrate telemetry server (telemetry is on by default on global chains) + /// Disable connecting to the Substrate telemetry server (telemetry is on by default on global chains). #[structopt(long = "no-telemetry")] pub no_telemetry: bool, @@ -179,55 +347,23 @@ pub struct RunCmd { #[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = "parse_telemetry_endpoints"))] pub telemetry_endpoints: Vec<(String, u8)>, - /// The means of execution used when calling into the runtime while syncing blocks. + /// Should execute offchain workers on every block. By default it's only enabled for nodes that are authoring new + /// blocks. #[structopt( - long = "syncing-execution", - value_name = "STRATEGY", + long = "offchain-worker", + value_name = "ENABLED", raw( - possible_values = "&ExecutionStrategy::variants()", + possible_values = "&OffchainWorkerEnabled::variants()", case_insensitive = "true", - default_value = r#""NativeElseWasm""# + default_value = r#""WhenValidating""# ) )] - pub syncing_execution: ExecutionStrategy, + pub offchain_worker: OffchainWorkerEnabled, - /// The means of execution used when calling into the runtime while importing blocks. - #[structopt( - long = "importing-execution", - value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""NativeElseWasm""# - ) - )] - pub importing_execution: ExecutionStrategy, - - /// The means of execution used when calling into the runtime while constructing blocks. - #[structopt( - long = "block-construction-execution", - value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""Wasm""# - ) - )] - pub block_construction_execution: ExecutionStrategy, - - /// The means of execution used when calling into the runtime while not syncing, importing or constructing blocks. - #[structopt( - long = "other-execution", - value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""Wasm""# - ) - )] - pub other_execution: ExecutionStrategy, + #[allow(missing_docs)] + #[structopt(flatten)] + pub execution_strategies: ExecutionStrategies, - #[allow(missing_docs)] #[structopt(flatten)] pub shared_params: SharedParams, @@ -239,6 +375,84 @@ pub struct RunCmd { #[allow(missing_docs)] #[structopt(flatten)] pub pool_config: TransactionPoolParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub keyring: Keyring, + + /// Enable authoring even when offline. + #[structopt(long = "force-authoring")] + pub force_authoring: bool, +} + +/// Stores all required Cli values for a keyring test account. +struct KeyringTestAccountCliValues { + help: String, + conflicts_with: Vec, + name: String, + variant: keyring::AuthorityKeyring, +} + +lazy_static::lazy_static! { + /// The Cli values for all test accounts. + static ref TEST_ACCOUNTS_CLI_VALUES: Vec = { + keyring::AuthorityKeyring::iter().map(|a| { + let help = format!("Shortcut for `--key //{} --name {}`.", a, a); + let conflicts_with = keyring::AuthorityKeyring::iter() + .filter(|b| a != *b) + .map(|b| b.to_string().to_lowercase()) + .chain(["name", "key"].iter().map(|s| s.to_string())) + .collect::>(); + let name = a.to_string().to_lowercase(); + + KeyringTestAccountCliValues { + help, + conflicts_with, + name, + variant: a, + } + }).collect() + }; +} + +/// Wrapper for exposing the keyring test accounts into the Cli. +#[derive(Debug, Clone)] +pub struct Keyring { + pub account: Option, +} + +impl StructOpt for Keyring { + fn clap<'a, 'b>() -> App<'a, 'b> { + unimplemented!("Should not be called for `TestAccounts`.") + } + + fn from_clap(m: &::structopt::clap::ArgMatches) -> Self { + Keyring { + account: TEST_ACCOUNTS_CLI_VALUES.iter().find(|a| m.is_present(&a.name)).map(|a| a.variant), + } + } +} + +impl AugmentClap for Keyring { + fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { + TEST_ACCOUNTS_CLI_VALUES.iter().fold(app, |app, a| { + let conflicts_with_strs = a.conflicts_with.iter().map(|s| s.as_str()).collect::>(); + + app.arg( + Arg::with_name(&a.name) + .long(&a.name) + .help(&a.help) + .conflicts_with_all(&conflicts_with_strs) + .takes_value(false) + ) + }) + } +} + +impl Keyring { + fn is_subcommand() -> bool { + false + } } /// Default to verbosity level 0, if none is provided. @@ -270,9 +484,9 @@ pub struct BuildSpecCmd { #[structopt(flatten)] pub shared_params: SharedParams, - /// Specify node secret key (64-character hex string) - #[structopt(long = "node-key", value_name = "KEY")] - pub node_key: Option, + #[allow(missing_docs)] + #[structopt(flatten)] + pub node_key_params: NodeKeyParams, } impl_get_log_filter!(BuildSpecCmd); @@ -338,6 +552,10 @@ impl_get_log_filter!(RevertCmd); /// The `purge-chain` command used to remove the whole chain. #[derive(Debug, StructOpt, Clone)] pub struct PurgeChainCmd { + /// Skip interactive prompt by answering yes automatically. + #[structopt(short = "y")] + pub yes: bool, + #[allow(missing_docs)] #[structopt(flatten)] pub shared_params: SharedParams, diff --git a/core/client/Cargo.toml b/core/client/Cargo.toml index 495b11b61d5b8aa0ecda2a9507b608db280b254d..cfc7eb3e3447e4f4c2a39d46fb5dcbadac9bdeef 100644 --- a/core/client/Cargo.toml +++ b/core/client/Cargo.toml @@ -18,9 +18,9 @@ state-machine = { package = "substrate-state-machine", path = "../state-machine" keyring = { package = "substrate-keyring", path = "../keyring", optional = true } trie = { package = "substrate-trie", path = "../trie", optional = true } substrate-telemetry = { path = "../telemetry", optional = true } -hash-db = { version = "0.11", optional = true } +hash-db = { version = "0.12", optional = true } kvdb = { git = "https://github.com/paritytech/parity-common", optional = true, rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } runtime-primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } runtime-version = { package = "sr-version", path = "../sr-version", default-features = false } diff --git a/core/client/db/Cargo.toml b/core/client/db/Cargo.toml index 8828eefa4fbf391d21bb4d8fbc3ef2396461c486..2944ab533b551c924d55c7fbf2adc81b36b5857b 100644 --- a/core/client/db/Cargo.toml +++ b/core/client/db/Cargo.toml @@ -12,15 +12,16 @@ kvdb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c kvdb-rocksdb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d", optional = true } lru-cache = "0.1.1" -hash-db = { version = "0.11" } +hash-db = { version = "0.12" } primitives = { package = "substrate-primitives", path = "../../primitives" } runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } client = { package = "substrate-client", path = "../../client" } state-machine = { package = "substrate-state-machine", path = "../../state-machine" } -parity-codec = { version = "3.1", features = ["derive"] } +parity-codec = { version = "3.2", features = ["derive"] } executor = { package = "substrate-executor", path = "../../executor" } state_db = { package = "substrate-state-db", path = "../../state-db" } trie = { package = "substrate-trie", path = "../../trie" } +consensus_common = { package = "substrate-consensus-common", path = "../../consensus/common" } [dev-dependencies] kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } diff --git a/core/client/db/src/cache/list_cache.rs b/core/client/db/src/cache/list_cache.rs index f8e52e14c630f07b421eaff4b69ca1bd0071c4fc..1e641534f969c0d63eefe387e98c9ded8bb3c81a 100644 --- a/core/client/db/src/cache/list_cache.rs +++ b/core/client/db/src/cache/list_cache.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/db/src/cache/list_entry.rs b/core/client/db/src/cache/list_entry.rs index d2d88ab12f38ab341a6b69b51d35fbe989ac23e5..237ae9a268026744b87f6d85b7c6301cb82ee204 100644 --- a/core/client/db/src/cache/list_entry.rs +++ b/core/client/db/src/cache/list_entry.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/db/src/cache/list_storage.rs b/core/client/db/src/cache/list_storage.rs index b9bf99f67b884fba4ae85f358cb9c0b731cb834b..659a30507e136576a844624fa167eb1cfb08ddb9 100644 --- a/core/client/db/src/cache/list_storage.rs +++ b/core/client/db/src/cache/list_storage.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/db/src/cache/mod.rs b/core/client/db/src/cache/mod.rs index 12f8c5e519782a9b2db3e7842176665e41b120f5..b5dd45f11dd52e69ea715243924ac5e799e038b1 100644 --- a/core/client/db/src/cache/mod.rs +++ b/core/client/db/src/cache/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ //! DB-backed cache of blockchain data. -use std::sync::Arc; +use std::{sync::Arc, collections::HashMap}; use parking_lot::RwLock; use kvdb::{KeyValueDB, DBTransaction}; @@ -25,7 +25,8 @@ use client::blockchain::Cache as BlockchainCache; use client::error::Result as ClientResult; use parity_codec::{Encode, Decode}; use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, As, AuthorityIdFor}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, As}; +use consensus_common::well_known_cache_keys::Id as CacheKeyId; use crate::utils::{self, COLUMN_META}; use self::list_cache::ListCache; @@ -64,7 +65,12 @@ impl CacheItemT for T where T: Clone + Decode + Encode + PartialEq {} /// Database-backed blockchain data cache. pub struct DbCache { - authorities_at: ListCache>, self::list_storage::DbStorage>, + cache_at: HashMap, self::list_storage::DbStorage>>, + db: Arc, + key_lookup_column: Option, + header_column: Option, + authorities_column: Option, + best_finalized_block: ComplexBlockId, } impl DbCache { @@ -76,19 +82,13 @@ impl DbCache { authorities_column: Option, best_finalized_block: ComplexBlockId, ) -> Self { - DbCache { - authorities_at: ListCache::new( - self::list_storage::DbStorage::new(b"auth".to_vec(), db, - self::list_storage::DbColumns { - meta: COLUMN_META, - key_lookup: key_lookup_column, - header: header_column, - cache: authorities_column, - }, - ), - As::sa(PRUNE_DEPTH), - best_finalized_block, - ), + Self { + cache_at: HashMap::new(), + db, + key_lookup_column, + header_column, + authorities_column, + best_finalized_block, } } @@ -97,35 +97,82 @@ impl DbCache { DbCacheTransaction { cache: self, tx, - authorities_at_op: None, + cache_at_op: HashMap::new(), + best_finalized_block: None, } } /// Run post-commit cache operations. pub fn commit(&mut self, ops: DbCacheTransactionOps) { - if let Some(authorities_at_op) = ops.authorities_at_op { - self.authorities_at.on_transaction_commit(authorities_at_op); + for (name, op) in ops.cache_at_op.into_iter() { + self.get_cache(name).on_transaction_commit(op); + } + if let Some(best_finalized_block) = ops.best_finalized_block { + self.best_finalized_block = best_finalized_block; } } + + /// Creates `ListCache` with the given name or returns a reference to the existing. + fn get_cache(&mut self, name: CacheKeyId) -> &mut ListCache, self::list_storage::DbStorage> { + get_cache_helper( + &mut self.cache_at, + name, + &self.db, + self.key_lookup_column, + self.header_column, + self.authorities_column, + &self.best_finalized_block + ) + } +} + +// This helper is needed because otherwise the borrow checker will require to +// clone all parameters outside of the closure. +fn get_cache_helper<'a, Block: BlockT>( + cache_at: &'a mut HashMap, self::list_storage::DbStorage>>, + name: CacheKeyId, + db: &Arc, + key_lookup: Option, + header: Option, + cache: Option, + best_finalized_block: &ComplexBlockId, +) -> &'a mut ListCache, self::list_storage::DbStorage> { + cache_at.entry(name).or_insert_with(|| { + ListCache::new( + self::list_storage::DbStorage::new(name.to_vec(), db.clone(), + self::list_storage::DbColumns { + meta: COLUMN_META, + key_lookup, + header, + cache, + }, + ), + As::sa(PRUNE_DEPTH), + best_finalized_block.clone(), + ) + }) } /// Cache operations that are to be committed after database transaction is committed. pub struct DbCacheTransactionOps { - authorities_at_op: Option>>>, + cache_at_op: HashMap>>, + best_finalized_block: Option>, } /// Database-backed blockchain data cache transaction valid for single block import. pub struct DbCacheTransaction<'a, Block: BlockT> { cache: &'a mut DbCache, tx: &'a mut DBTransaction, - authorities_at_op: Option>>>, + cache_at_op: HashMap>>, + best_finalized_block: Option>, } impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { /// Convert transaction into post-commit operations set. pub fn into_ops(self) -> DbCacheTransactionOps { DbCacheTransactionOps { - authorities_at_op: self.authorities_at_op, + cache_at_op: self.cache_at_op, + best_finalized_block: self.best_finalized_block, } } @@ -134,21 +181,42 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { mut self, parent: ComplexBlockId, block: ComplexBlockId, - authorities_at: Option>>, + data_at: HashMap>, is_final: bool, ) -> ClientResult { - assert!(self.authorities_at_op.is_none()); + assert!(self.cache_at_op.is_empty()); - self.authorities_at_op = self.cache.authorities_at.on_block_insert( - &mut self::list_storage::DbStorageTransaction::new( - self.cache.authorities_at.storage(), - &mut self.tx - ), - parent, - block, - authorities_at, - is_final, - )?; + // prepare list of caches that are not update + // (we might still need to do some cache maintenance in this case) + let missed_caches = self.cache.cache_at.keys() + .filter(|cache| !data_at.contains_key(cache.clone())) + .cloned() + .collect::>(); + + let mut insert_op = |name: CacheKeyId, value: Option>| -> Result<(), client::error::Error> { + let cache = self.cache.get_cache(name); + let op = cache.on_block_insert( + &mut self::list_storage::DbStorageTransaction::new( + cache.storage(), + &mut self.tx, + ), + parent.clone(), + block.clone(), + value.or(cache.value_at_block(&parent)?), + is_final, + )?; + if let Some(op) = op { + self.cache_at_op.insert(name, op); + } + Ok(()) + }; + + data_at.into_iter().try_for_each(|(name, data)| insert_op(name, Some(data)))?; + missed_caches.into_iter().try_for_each(|name| insert_op(name, None))?; + + if is_final { + self.best_finalized_block = Some(block); + } Ok(self) } @@ -159,16 +227,24 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { parent: ComplexBlockId, block: ComplexBlockId ) -> ClientResult { - assert!(self.authorities_at_op.is_none()); + assert!(self.cache_at_op.is_empty()); - self.authorities_at_op = self.cache.authorities_at.on_block_finalize( - &mut self::list_storage::DbStorageTransaction::new( - self.cache.authorities_at.storage(), - &mut self.tx - ), - parent, - block, - )?; + for (name, cache_at) in self.cache.cache_at.iter() { + let op = cache_at.on_block_finalize( + &mut self::list_storage::DbStorageTransaction::new( + cache_at.storage(), + &mut self.tx + ), + parent.clone(), + block.clone(), + )?; + + if let Some(op) = op { + self.cache_at_op.insert(name.to_owned(), op); + } + } + + self.best_finalized_block = Some(block); Ok(self) } @@ -178,12 +254,12 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { pub struct DbCacheSync(pub RwLock>); impl BlockchainCache for DbCacheSync { - fn authorities_at(&self, at: BlockId) -> Option>> { + fn get_at(&self, key: &CacheKeyId, at: &BlockId) -> Option> { let cache = self.0.read(); - let storage = cache.authorities_at.storage(); + let storage = cache.cache_at.get(key)?.storage(); let db = storage.db(); let columns = storage.columns(); - let at = match at { + let at = match *at { BlockId::Hash(hash) => { let header = utils::read_header::( &**db, @@ -202,6 +278,7 @@ impl BlockchainCache for DbCacheSync { }, }; - cache.authorities_at.value_at_block(&at).ok()? + cache.cache_at.get(key)?.value_at_block(&at).ok()? } } + diff --git a/core/client/db/src/lib.rs b/core/client/db/src/lib.rs index 36ac3cc3450552cc8e6f4280898ca413a8fb3ec3..7657bfd39691a0e2bec1e89e8ed7d84339ae1446 100644 --- a/core/client/db/src/lib.rs +++ b/core/client/db/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -33,6 +33,7 @@ mod utils; use std::sync::Arc; use std::path::PathBuf; use std::io; +use std::collections::HashMap; use client::backend::NewBlockState; use client::blockchain::HeaderBackend; @@ -40,12 +41,12 @@ use client::ExecutionStrategies; use parity_codec::{Decode, Encode}; use hash_db::Hasher; use kvdb::{KeyValueDB, DBTransaction}; -use trie::MemoryDB; +use trie::{MemoryDB, PrefixedMemoryDB, prefixed_key}; use parking_lot::RwLock; use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash}; use primitives::storage::well_known_keys; use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero, Digest, DigestItem, AuthorityIdFor}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero, Digest, DigestItem}; use runtime_primitives::BuildStorage; use state_machine::backend::Backend as StateBackend; use executor::RuntimeInfo; @@ -54,6 +55,7 @@ use crate::utils::{Meta, db_err, meta_keys, open_database, read_db, block_id_to_ use client::leaves::{LeafSet, FinalizationDisplaced}; use client::children; use state_db::StateDb; +use consensus_common::well_known_cache_keys; use crate::storage_cache::{CachingState, SharedCache, new_shared_cache}; use log::{trace, debug, warn}; pub use state_db::PruningMode; @@ -243,7 +245,7 @@ impl client::blockchain::Backend for BlockchainDb { Ok(self.meta.read().finalized_hash.clone()) } - fn cache(&self) -> Option<&client::blockchain::Cache> { + fn cache(&self) -> Option>> { None } @@ -256,10 +258,16 @@ impl client::blockchain::Backend for BlockchainDb { } } +impl client::blockchain::ProvideCache for BlockchainDb { + fn cache(&self) -> Option>> { + None + } +} + /// Database transaction pub struct BlockImportOperation { old_state: CachingState, - db_updates: MemoryDB, + db_updates: PrefixedMemoryDB, storage_updates: Vec<(Vec, Option>)>, changes_trie_updates: MemoryDB, pending_block: Option>, @@ -306,11 +314,11 @@ where Block: BlockT, Ok(()) } - fn update_authorities(&mut self, _authorities: Vec>) { - // currently authorities are not cached on full nodes + fn update_cache(&mut self, _cache: HashMap>) { + // Currently cache isn't implemented on full nodes. } - fn update_db_storage(&mut self, update: MemoryDB) -> Result<(), client::error::Error> { + fn update_db_storage(&mut self, update: PrefixedMemoryDB) -> Result<(), client::error::Error> { self.db_updates = update; Ok(()) } @@ -321,7 +329,7 @@ where Block: BlockT, return Err(client::error::ErrorKind::GenesisInvalid.into()); } - let mut transaction: MemoryDB = Default::default(); + let mut transaction: PrefixedMemoryDB = Default::default(); for (child_key, child_map) in children { if !well_known_keys::is_child_storage_key(&child_key) { @@ -374,22 +382,23 @@ where Block: BlockT, struct StorageDb { pub db: Arc, - pub state_db: StateDb, + pub state_db: StateDb>, } impl state_machine::Storage for StorageDb { - fn get(&self, key: &H256) -> Result, String> { - self.state_db.get(key, self).map(|r| r.map(|v| DBValue::from_slice(&v))) + fn get(&self, key: &H256, prefix: &[u8]) -> Result, String> { + let key = prefixed_key::(key, prefix); + self.state_db.get(&key, self).map(|r| r.map(|v| DBValue::from_slice(&v))) .map_err(|e| format!("Database backend error: {:?}", e)) } } -impl state_db::HashDb for StorageDb { +impl state_db::NodeDb for StorageDb { type Error = io::Error; - type Hash = H256; + type Key = [u8]; - fn get(&self, key: &H256) -> Result>, Self::Error> { - self.db.get(columns::STATE, key.as_bytes()).map(|r| r.map(|v| v.to_vec())) + fn get(&self, key: &[u8]) -> Result>, Self::Error> { + self.db.get(columns::STATE, key).map(|r| r.map(|v| v.to_vec())) } } @@ -405,7 +414,7 @@ impl DbGenesisStorage { } impl state_machine::Storage for DbGenesisStorage { - fn get(&self, _key: &H256) -> Result, String> { + fn get(&self, _key: &H256, _prefix: &[u8]) -> Result, String> { Ok(None) } } @@ -515,7 +524,7 @@ impl state_machine::ChangesTrieRootsStorage for DbC } impl state_machine::ChangesTrieStorage for DbChangesTrieStorage { - fn get(&self, key: &H256) -> Result, String> { + fn get(&self, key: &H256, _prefix: &[u8]) -> Result, String> { self.db.get(columns::CHANGES_TRIE, &key[..]) .map_err(|err| format!("{}", err)) } @@ -559,7 +568,7 @@ impl> Backend { let blockchain = BlockchainDb::new(db.clone())?; let meta = blockchain.meta.clone(); let map_e = |e: state_db::Error| ::client::error::Error::from(format!("State database error: {:?}", e)); - let state_db: StateDb = StateDb::new(pruning, &StateMetaDb(&*db)).map_err(map_e)?; + let state_db: StateDb<_, _> = StateDb::new(pruning, &StateMetaDb(&*db)).map_err(map_e)?; let storage_db = StorageDb { db: db.clone(), state_db, @@ -832,7 +841,7 @@ impl> Backend { transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); } - let mut changeset: state_db::ChangeSet = state_db::ChangeSet::default(); + let mut changeset: state_db::ChangeSet> = state_db::ChangeSet::default(); for (key, (val, rc)) in operation.db_updates.drain() { if rc > 0 { changeset.inserted.push((key, val.to_vec())); @@ -981,7 +990,7 @@ impl> Backend { } } -fn apply_state_commit(transaction: &mut DBTransaction, commit: state_db::CommitSet) { +fn apply_state_commit(transaction: &mut DBTransaction, commit: state_db::CommitSet>) { for (key, val) in commit.data.inserted.into_iter() { transaction.put(columns::STATE, &key[..], &val); } @@ -1031,7 +1040,7 @@ impl client::backend::Backend for Backend whe Ok(BlockImportOperation { pending_block: None, old_state, - db_updates: MemoryDB::default(), + db_updates: PrefixedMemoryDB::default(), storage_updates: Default::default(), changes_trie_updates: MemoryDB::default(), aux_ops: Vec::new(), @@ -1169,6 +1178,10 @@ impl client::backend::Backend for Backend whe } } + fn have_state_at(&self, hash: &Block::Hash, number: NumberFor) -> bool { + !self.storage.state_db.is_pruned(hash, number.as_()) + } + fn destroy_state(&self, mut state: Self::State) -> Result<(), client::error::Error> { if let Some(hash) = state.parent_hash.clone() { let is_best = || self.blockchain.meta.read().best_hash == hash; @@ -1410,7 +1423,7 @@ mod tests { op.reset_storage(storage.iter().cloned().collect(), Default::default()).unwrap(); - key = op.db_updates.insert(b"hello"); + key = op.db_updates.insert(&[], b"hello"); op.set_block_data( header, Some(vec![]), @@ -1444,8 +1457,8 @@ mod tests { ).0.into(); let hash = header.hash(); - op.db_updates.insert(b"hello"); - op.db_updates.remove(&key); + op.db_updates.insert(&[], b"hello"); + op.db_updates.remove(&key, &[]); op.set_block_data( header, Some(vec![]), @@ -1479,7 +1492,7 @@ mod tests { ).0.into(); let hash = header.hash(); - op.db_updates.remove(&key); + op.db_updates.remove(&key, &[]); op.set_block_data( header, Some(vec![]), @@ -1545,7 +1558,7 @@ mod tests { assert_eq!(backend.changes_tries_storage.root(&anchor, block), Ok(Some(changes_root))); for (key, (val, _)) in changes_trie_update.drain() { - assert_eq!(backend.changes_trie_storage().unwrap().get(&key), Ok(Some(val))); + assert_eq!(backend.changes_trie_storage().unwrap().get(&key, &[]), Ok(Some(val))); } }; @@ -1671,23 +1684,23 @@ mod tests { let mut tx = DBTransaction::new(); backend.changes_tries_storage.prune(Some(config.clone()), &mut tx, Default::default(), 12); backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root1).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root2).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root3).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root4).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root5).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root6).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root7).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root8).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root1, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root2, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root3, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root4, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root5, &[]).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root6, &[]).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root7, &[]).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root8, &[]).unwrap().is_some()); // now simulate finalization of block#16, causing prune of tries at #5..#8 let mut tx = DBTransaction::new(); backend.changes_tries_storage.prune(Some(config.clone()), &mut tx, Default::default(), 16); backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root5).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root6).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root7).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root8).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root5, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root6, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root7, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root8, &[]).unwrap().is_none()); // now "change" pruning mode to archive && simulate finalization of block#20 // => no changes tries are pruned, because we never prune in archive mode @@ -1695,10 +1708,10 @@ mod tests { let mut tx = DBTransaction::new(); backend.changes_tries_storage.prune(Some(config), &mut tx, Default::default(), 20); backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root9).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root10).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root11).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root12).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root9, &[]).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root10, &[]).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root11, &[]).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root12, &[]).unwrap().is_some()); } #[test] @@ -1737,15 +1750,15 @@ mod tests { let mut tx = DBTransaction::new(); backend.changes_tries_storage.prune(Some(config.clone()), &mut tx, block5, 5); backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root1).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root2).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root1, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root2, &[]).unwrap().is_some()); // now simulate finalization of block#6, causing prune of tries at #2 let mut tx = DBTransaction::new(); backend.changes_tries_storage.prune(Some(config.clone()), &mut tx, block6, 6); backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root2).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root3).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root2, &[]).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root3, &[]).unwrap().is_some()); } #[test] diff --git a/core/client/db/src/light.rs b/core/client/db/src/light.rs index 8a3456df69a305c55870617c4147950a517c0da5..62b6486f54d7ea28ac5561a33aa5b374943e26ec 100644 --- a/core/client/db/src/light.rs +++ b/core/client/db/src/light.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ //! RocksDB-based light client blockchain storage. -use std::sync::Arc; +use std::{sync::Arc, collections::HashMap}; use parking_lot::RwLock; use kvdb::{KeyValueDB, DBTransaction}; @@ -32,7 +32,8 @@ use parity_codec::{Decode, Encode}; use primitives::Blake2Hasher; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, - Zero, One, As, NumberFor, Digest, DigestItem, AuthorityIdFor}; + Zero, One, As, NumberFor, Digest, DigestItem}; +use consensus_common::well_known_cache_keys; use crate::cache::{DbCacheSync, DbCache, ComplexBlockId}; use crate::utils::{self, meta_keys, Meta, db_err, open_database, read_db, block_id_to_lookup_key, read_meta}; @@ -59,7 +60,7 @@ pub struct LightStorage { db: Arc, meta: RwLock, Block::Hash>>, leaves: RwLock>>, - cache: DbCacheSync, + cache: Arc>, } impl LightStorage @@ -96,7 +97,7 @@ impl LightStorage Ok(LightStorage { db, meta: RwLock::new(meta), - cache: DbCacheSync(RwLock::new(cache)), + cache: Arc::new(DbCacheSync(RwLock::new(cache))), leaves: RwLock::new(leaves), }) } @@ -370,7 +371,7 @@ impl LightBlockchainStorage for LightStorage fn import_header( &self, header: Block::Header, - authorities: Option>>, + cache_at: HashMap>, leaf_state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, ) -> ClientResult<()> { @@ -432,7 +433,7 @@ impl LightBlockchainStorage for LightStorage .on_block_insert( ComplexBlockId::new(*header.parent_hash(), if number.is_zero() { Zero::zero() } else { number - One::one() }), ComplexBlockId::new(hash, number), - authorities, + cache_at, finalized, )? .into_ops(); @@ -521,8 +522,8 @@ impl LightBlockchainStorage for LightStorage Ok(self.meta.read().finalized_hash.clone()) } - fn cache(&self) -> Option<&BlockchainCache> { - Some(&self.cache) + fn cache(&self) -> Option>> { + Some(self.cache.clone()) } } @@ -538,9 +539,11 @@ pub(crate) mod tests { use client::cht; use runtime_primitives::generic::DigestItem; use runtime_primitives::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper}; + use runtime_primitives::traits::AuthorityIdFor; use super::*; type Block = RawBlock>; + type AuthorityId = AuthorityIdFor; pub fn default_header(parent: &Hash, number: u64) -> Header { Header { @@ -566,41 +569,41 @@ pub(crate) mod tests { pub fn insert_block Header>( db: &LightStorage, - authorities: Option>>, + cache: HashMap>, header: F, ) -> Hash { let header = header(); let hash = header.hash(); - db.import_header(header, authorities, NewBlockState::Best, Vec::new()).unwrap(); + db.import_header(header, cache, NewBlockState::Best, Vec::new()).unwrap(); hash } fn insert_final_block Header>( db: &LightStorage, - authorities: Option>>, + cache: HashMap>, header: F, ) -> Hash { let header = header(); let hash = header.hash(); - db.import_header(header, authorities, NewBlockState::Final, Vec::new()).unwrap(); + db.import_header(header, cache, NewBlockState::Final, Vec::new()).unwrap(); hash } fn insert_non_best_block Header>( db: &LightStorage, - authorities: Option>>, + cache: HashMap>, header: F, ) -> Hash { let header = header(); let hash = header.hash(); - db.import_header(header, authorities, NewBlockState::Normal, Vec::new()).unwrap(); + db.import_header(header, cache, NewBlockState::Normal, Vec::new()).unwrap(); hash } #[test] fn returns_known_header() { let db = LightStorage::new_test(); - let known_hash = insert_block(&db, None, || default_header(&Default::default(), 0)); + let known_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); let header_by_hash = db.header(BlockId::Hash(known_hash)).unwrap().unwrap(); let header_by_number = db.header(BlockId::Number(0)).unwrap().unwrap(); assert_eq!(header_by_hash, header_by_number); @@ -616,12 +619,12 @@ pub(crate) mod tests { #[test] fn returns_info() { let db = LightStorage::new_test(); - let genesis_hash = insert_block(&db, None, || default_header(&Default::default(), 0)); + let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); let info = db.info().unwrap(); assert_eq!(info.best_hash, genesis_hash); assert_eq!(info.best_number, 0); assert_eq!(info.genesis_hash, genesis_hash); - let best_hash = insert_block(&db, None, || default_header(&genesis_hash, 1)); + let best_hash = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); let info = db.info().unwrap(); assert_eq!(info.best_hash, best_hash); assert_eq!(info.best_number, 1); @@ -631,7 +634,7 @@ pub(crate) mod tests { #[test] fn returns_block_status() { let db = LightStorage::new_test(); - let genesis_hash = insert_block(&db, None, || default_header(&Default::default(), 0)); + let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); assert_eq!(db.status(BlockId::Hash(genesis_hash)).unwrap(), BlockStatus::InChain); assert_eq!(db.status(BlockId::Number(0)).unwrap(), BlockStatus::InChain); assert_eq!(db.status(BlockId::Hash(Hash::from_low_u64_be(1))).unwrap(), BlockStatus::Unknown); @@ -641,7 +644,7 @@ pub(crate) mod tests { #[test] fn returns_block_hash() { let db = LightStorage::new_test(); - let genesis_hash = insert_block(&db, None, || default_header(&Default::default(), 0)); + let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); assert_eq!(db.hash(0).unwrap(), Some(genesis_hash)); assert_eq!(db.hash(1).unwrap(), None); } @@ -650,11 +653,11 @@ pub(crate) mod tests { fn import_header_works() { let db = LightStorage::new_test(); - let genesis_hash = insert_block(&db, None, || default_header(&Default::default(), 0)); + let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); assert_eq!(db.db.iter(columns::HEADER).count(), 1); assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), 2); - let _ = insert_block(&db, None, || default_header(&genesis_hash, 1)); + let _ = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); assert_eq!(db.db.iter(columns::HEADER).count(), 2); assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), 4); } @@ -665,25 +668,25 @@ pub(crate) mod tests { let db = LightStorage::new_test(); // insert genesis block header (never pruned) - let mut prev_hash = insert_final_block(&db, None, || header_producer(&Default::default(), 0)); + let mut prev_hash = insert_final_block(&db, HashMap::new(), || header_producer(&Default::default(), 0)); // insert SIZE blocks && ensure that nothing is pruned for number in 0..cht::SIZE { - prev_hash = insert_block(&db, None, || header_producer(&prev_hash, 1 + number)); + prev_hash = insert_block(&db, HashMap::new(), || header_producer(&prev_hash, 1 + number)); } assert_eq!(db.db.iter(columns::HEADER).count(), (1 + cht::SIZE) as usize); assert_eq!(db.db.iter(columns::CHT).count(), 0); // insert next SIZE blocks && ensure that nothing is pruned for number in 0..cht::SIZE { - prev_hash = insert_block(&db, None, || header_producer(&prev_hash, 1 + cht::SIZE + number)); + prev_hash = insert_block(&db, HashMap::new(), || header_producer(&prev_hash, 1 + cht::SIZE + number)); } assert_eq!(db.db.iter(columns::HEADER).count(), (1 + cht::SIZE + cht::SIZE) as usize); assert_eq!(db.db.iter(columns::CHT).count(), 0); // insert block #{2 * cht::SIZE + 1} && check that new CHT is created + headers of this CHT are pruned // nothing is yet finalized, so nothing is pruned. - prev_hash = insert_block(&db, None, || header_producer(&prev_hash, 1 + cht::SIZE + cht::SIZE)); + prev_hash = insert_block(&db, HashMap::new(), || header_producer(&prev_hash, 1 + cht::SIZE + cht::SIZE)); assert_eq!(db.db.iter(columns::HEADER).count(), (2 + cht::SIZE + cht::SIZE) as usize); assert_eq!(db.db.iter(columns::CHT).count(), 0); @@ -732,9 +735,9 @@ pub(crate) mod tests { let db = LightStorage::new_test(); // insert 1 + SIZE + SIZE + 1 blocks so that CHT#0 is created - let mut prev_hash = insert_final_block(&db, None, || header_with_changes_trie(&Default::default(), 0)); + let mut prev_hash = insert_final_block(&db, HashMap::new(), || header_with_changes_trie(&Default::default(), 0)); for i in 1..1 + cht::SIZE + cht::SIZE + 1 { - prev_hash = insert_block(&db, None, || header_with_changes_trie(&prev_hash, i as u64)); + prev_hash = insert_block(&db, HashMap::new(), || header_with_changes_trie(&prev_hash, i as u64)); db.finalize_header(BlockId::Hash(prev_hash)).unwrap(); } @@ -754,16 +757,16 @@ pub(crate) mod tests { #[test] fn tree_route_works() { let db = LightStorage::new_test(); - let block0 = insert_block(&db, None, || default_header(&Default::default(), 0)); + let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); // fork from genesis: 3 prong. - let a1 = insert_block(&db, None, || default_header(&block0, 1)); - let a2 = insert_block(&db, None, || default_header(&a1, 2)); - let a3 = insert_block(&db, None, || default_header(&a2, 3)); + let a1 = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); + let a2 = insert_block(&db, HashMap::new(), || default_header(&a1, 2)); + let a3 = insert_block(&db, HashMap::new(), || default_header(&a2, 3)); // fork from genesis: 2 prong. - let b1 = insert_block(&db, None, || header_with_extrinsics_root(&block0, 1, Hash::from([1; 32]))); - let b2 = insert_block(&db, None, || default_header(&b1, 2)); + let b1 = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block0, 1, Hash::from([1; 32]))); + let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); { let tree_route = ::client::blockchain::tree_route( @@ -815,44 +818,64 @@ pub(crate) mod tests { } #[test] - fn authorites_are_cached() { + fn authorities_are_cached() { let db = LightStorage::new_test(); fn run_checks(db: &LightStorage, max: u64, checks: &[(u64, Option>>)]) { for (at, expected) in checks.iter().take_while(|(at, _)| *at <= max) { - let actual = db.cache().authorities_at(BlockId::Number(*at)); + let actual = get_authorities(db.cache(), BlockId::Number(*at)); assert_eq!(*expected, actual); } } + fn same_authorities() -> HashMap> { + HashMap::new() + } + + fn make_authorities(authorities: Vec) -> HashMap> { + let mut map = HashMap::new(); + map.insert(well_known_cache_keys::AUTHORITIES, authorities.encode()); + map + } + + fn get_authorities(cache: &BlockchainCache, at: BlockId) -> Option> { + cache.get_at(&well_known_cache_keys::AUTHORITIES, &at).and_then(|val| Decode::decode(&mut &val[..])) + } + + let auth1 = || AuthorityId::from_raw([1u8; 32]); + let auth2 = || AuthorityId::from_raw([2u8; 32]); + let auth3 = || AuthorityId::from_raw([3u8; 32]); + let auth4 = || AuthorityId::from_raw([4u8; 32]); + let auth5 = || AuthorityId::from_raw([5u8; 32]); + let auth6 = || AuthorityId::from_raw([6u8; 32]); + let (hash2, hash6) = { // first few blocks are instantly finalized - // B0(None) -> B1(None) -> B2(1) -> B3(1) -> B4(1, 2) -> B5(1, 2) -> B6(None) + // B0(None) -> B1(None) -> B2(1) -> B3(1) -> B4(1, 2) -> B5(1, 2) -> B6(1, 2) let checks = vec![ (0, None), (1, None), - (2, Some(vec![[1u8; 32].into()])), - (3, Some(vec![[1u8; 32].into()])), - (4, Some(vec![[1u8; 32].into(), [2u8; 32].into()])), - (5, Some(vec![[1u8; 32].into(), [2u8; 32].into()])), - (6, None), - (7, None), // block will work for 'future' block too + (2, Some(vec![auth1()])), + (3, Some(vec![auth1()])), + (4, Some(vec![auth1(), auth2()])), + (5, Some(vec![auth1(), auth2()])), + (6, Some(vec![auth1(), auth2()])), ]; - let hash0 = insert_final_block(&db, None, || default_header(&Default::default(), 0)); + let hash0 = insert_final_block(&db, same_authorities(), || default_header(&Default::default(), 0)); run_checks(&db, 0, &checks); - let hash1 = insert_final_block(&db, None, || default_header(&hash0, 1)); + let hash1 = insert_final_block(&db, same_authorities(), || default_header(&hash0, 1)); run_checks(&db, 1, &checks); - let hash2 = insert_final_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash1, 2)); + let hash2 = insert_final_block(&db, make_authorities(vec![auth1()]), || default_header(&hash1, 2)); run_checks(&db, 2, &checks); - let hash3 = insert_final_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash2, 3)); + let hash3 = insert_final_block(&db, make_authorities(vec![auth1()]), || default_header(&hash2, 3)); run_checks(&db, 3, &checks); - let hash4 = insert_final_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash3, 4)); + let hash4 = insert_final_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash3, 4)); run_checks(&db, 4, &checks); - let hash5 = insert_final_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash4, 5)); + let hash5 = insert_final_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash4, 5)); run_checks(&db, 5, &checks); - let hash6 = insert_final_block(&db, None, || default_header(&hash5, 6)); - run_checks(&db, 7, &checks); + let hash6 = insert_final_block(&db, same_authorities(), || default_header(&hash5, 6)); + run_checks(&db, 6, &checks); (hash2, hash6) }; @@ -861,10 +884,10 @@ pub(crate) mod tests { // some older non-best blocks are inserted // ... -> B2(1) -> B2_1(1) -> B2_2(2) // => the cache ignores all writes before best finalized block - let hash2_1 = insert_non_best_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash2, 3)); - assert_eq!(None, db.cache().authorities_at(BlockId::Hash(hash2_1))); - let hash2_2 = insert_non_best_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash2_1, 4)); - assert_eq!(None, db.cache().authorities_at(BlockId::Hash(hash2_2))); + let hash2_1 = insert_non_best_block(&db, make_authorities(vec![auth1()]), || default_header(&hash2, 3)); + assert_eq!(None, get_authorities(db.cache(), BlockId::Hash(hash2_1))); + let hash2_2 = insert_non_best_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash2_1, 4)); + assert_eq!(None, get_authorities(db.cache(), BlockId::Hash(hash2_2))); } let (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) = { @@ -874,39 +897,57 @@ pub(crate) mod tests { // \> B6_1_1(5) // \> B6_1_2(6) -> B6_1_3(7) - let hash7 = insert_block(&db, Some(vec![[3u8; 32].into()]), || default_header(&hash6, 7)); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - let hash8 = insert_block(&db, Some(vec![[3u8; 32].into()]), || default_header(&hash7, 8)); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - let hash6_1 = insert_block(&db, Some(vec![[4u8; 32].into()]), || default_header(&hash6, 7)); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - let hash6_1_1 = insert_non_best_block(&db, Some(vec![[5u8; 32].into()]), || default_header(&hash6_1, 8)); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - let hash6_1_2 = insert_non_best_block(&db, Some(vec![[6u8; 32].into()]), || default_header(&hash6_1, 8)); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - let hash6_2 = insert_block(&db, Some(vec![[4u8; 32].into()]), || default_header(&hash6_1, 8)); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + let hash7 = insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash6, 7)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + let hash8 = insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash7, 8)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + let hash6_1 = insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6, 7)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + let hash6_1_1 = insert_non_best_block(&db, make_authorities(vec![auth5()]), || default_header(&hash6_1, 8)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + let hash6_1_2 = insert_non_best_block(&db, make_authorities(vec![auth6()]), || default_header(&hash6_1, 8)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + let hash6_2 = insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6_1, 8)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) }; @@ -914,29 +955,35 @@ pub(crate) mod tests { { // finalize block hash6_1 db.finalize_header(BlockId::Hash(hash6_1)).unwrap(); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); // finalize block hash6_2 db.finalize_header(BlockId::Hash(hash6_2)).unwrap(); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); } } #[test] fn database_is_reopened() { let db = LightStorage::new_test(); - let hash0 = insert_final_block(&db, None, || default_header(&Default::default(), 0)); + let hash0 = insert_final_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); assert_eq!(db.info().unwrap().best_hash, hash0); assert_eq!(db.header(BlockId::Hash(hash0)).unwrap().unwrap().hash(), hash0); @@ -959,7 +1006,7 @@ pub(crate) mod tests { assert_eq!(db.get_aux(&[3]).unwrap(), None); // delete aux1 + insert aux3 using import operation - db.import_header(default_header(&Default::default(), 0), None, NewBlockState::Best, vec![ + db.import_header(default_header(&Default::default(), 0), HashMap::new(), NewBlockState::Best, vec![ (vec![3], Some(vec![103])), (vec![1], None), ]).unwrap(); @@ -973,17 +1020,17 @@ pub(crate) mod tests { #[test] fn test_leaves_pruned_on_finality() { let db = LightStorage::::new_test(); - let block0 = insert_block(&db, None, || default_header(&Default::default(), 0)); + let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - let block1_a = insert_block(&db, None, || default_header(&block0, 1)); - let block1_b = insert_block(&db, None, || header_with_extrinsics_root(&block0, 1, [1; 32].into())); - let block1_c = insert_block(&db, None, || header_with_extrinsics_root(&block0, 1, [2; 32].into())); + let block1_a = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); + let block1_b = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block0, 1, [1; 32].into())); + let block1_c = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block0, 1, [2; 32].into())); assert_eq!(db.leaves.read().hashes(), vec![block1_a, block1_b, block1_c]); - let block2_a = insert_block(&db, None, || default_header(&block1_a, 2)); - let block2_b = insert_block(&db, None, || header_with_extrinsics_root(&block1_b, 2, [1; 32].into())); - let block2_c = insert_block(&db, None, || header_with_extrinsics_root(&block1_b, 2, [2; 32].into())); + let block2_a = insert_block(&db, HashMap::new(), || default_header(&block1_a, 2)); + let block2_b = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block1_b, 2, [1; 32].into())); + let block2_c = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block1_b, 2, [2; 32].into())); assert_eq!(db.leaves.read().hashes(), vec![block2_a, block2_b, block2_c, block1_c]); diff --git a/core/client/db/src/storage_cache.rs b/core/client/db/src/storage_cache.rs index da07aa4d5a923ebffd5c745438f75e1e399862e8..6cfdbdd09b53db4ea986965550d076831cd07eae 100644 --- a/core/client/db/src/storage_cache.rs +++ b/core/client/db/src/storage_cache.rs @@ -109,7 +109,7 @@ impl, B: Block> CachingState { } } - /// Propagate local cache into the shared cache and synchonize + /// Propagate local cache into the shared cache and synchronize /// the shared cache with the best block state. /// This function updates the shared cache by removing entries /// that are invalidated by chain reorganization. `sync_cache` diff --git a/core/client/db/src/utils.rs b/core/client/db/src/utils.rs index 150c1fdd98ccdef5b596735f2e523bd179a3a35f..ce843a93a2fa4531761d1f94925bb14a23d9f72a 100644 --- a/core/client/db/src/utils.rs +++ b/core/client/db/src/utils.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/src/backend.rs b/core/client/src/backend.rs index 7b1136c92951bec62dffa9ada5047db2653d703b..8a6ffe4384b2e8c2a858002ec7ccc84deb31959c 100644 --- a/core/client/src/backend.rs +++ b/core/client/src/backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,12 +16,14 @@ //! Substrate Client data backend +use std::collections::HashMap; use crate::error; use primitives::ChangesTrieConfiguration; use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; -use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, NumberFor}; +use runtime_primitives::traits::{Block as BlockT, NumberFor}; use state_machine::backend::Backend as StateBackend; use state_machine::ChangesTrieStorage as StateChangesTrieStorage; +use consensus::well_known_cache_keys; use hash_db::Hasher; use trie::MemoryDB; @@ -73,9 +75,8 @@ pub trait BlockImportOperation where state: NewBlockState, ) -> error::Result<()>; - /// Append authorities set to the transaction. This is a set of parent block (set which - /// has been used to check justification of this block). - fn update_authorities(&mut self, authorities: Vec>); + /// Update cached data. + fn update_cache(&mut self, cache: HashMap>); /// Inject storage data into the database. fn update_db_storage(&mut self, update: >::Transaction) -> error::Result<()>; /// Inject storage data into the database replacing any existing data. @@ -142,6 +143,10 @@ pub trait Backend: AuxStore + Send + Sync where fn blockchain(&self) -> &Self::Blockchain; /// Returns reference to changes trie storage. fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage>; + /// Returns true if state for given block is available. + fn have_state_at(&self, hash: &Block::Hash, _number: NumberFor) -> bool { + self.state_at(BlockId::Hash(hash.clone())).is_ok() + } /// Returns state backend with post-state of given block. fn state_at(&self, block: BlockId) -> error::Result; /// Destroy state and save any useful data, such as cache. diff --git a/core/client/src/block_builder/api.rs b/core/client/src/block_builder/api.rs index 9096b8f4692764f6f72df011966641a6914370c6..48abb38024175050af98913ac93ed4dd691abafb 100644 --- a/core/client/src/block_builder/api.rs +++ b/core/client/src/block_builder/api.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,46 +16,10 @@ //! The runtime api for building blocks. -use runtime_primitives::{traits::Block as BlockT, ApplyResult, RuntimeString}; +use runtime_primitives::{traits::Block as BlockT, ApplyResult}; use rstd::vec::Vec; use sr_api_macros::decl_runtime_apis; pub use inherents::{InherentData, CheckInherentsResult}; -use parity_codec::{Encode, Decode}; - -/// The old representation of the inherent data. -#[doc(hide)] -#[derive(Encode, Decode)] -pub struct OldInherentData { - /// Current timestamp. - pub timestamp: u64, - /// Blank report. - pub consensus: (), - /// Aura expected slot. Can take any value during block construction. - pub aura_expected_slot: u64, -} - -impl OldInherentData { - /// Create a new `BasicInherentData` instance. - pub fn new(timestamp: u64, expected_slot: u64) -> Self { - Self { - timestamp, - consensus: (), - aura_expected_slot: expected_slot, - } - } -} - -/// Error type used while checking inherents. -#[doc(hide)] -#[derive(Encode, PartialEq)] -#[cfg_attr(feature = "std", derive(Decode))] -pub enum OldCheckInherentError { - /// The inherents are generally valid but a delay until the given timestamp - /// is required. - ValidAtTimestamp(u64), - /// Some other error has occurred. - Other(RuntimeString), -} decl_runtime_apis! { /// The `BlockBuilder` api trait that provides required functions for building a block for a runtime. @@ -64,16 +28,11 @@ decl_runtime_apis! { /// Apply the given extrinsics. fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult; /// Finish the current block. - fn finalise_block() -> ::Header; + fn finalize_block() -> ::Header; /// Generate inherent extrinsics. The inherent data will vary from chain to chain. fn inherent_extrinsics(inherent: InherentData) -> Vec<::Extrinsic>; /// Check that the inherents are valid. The inherent data will vary from chain to chain. fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; - /// Check that the inherents are valid. The inherent data will vary from chain to chain. - /// - /// Old version that is used by the CC network. - #[changed_in(2)] - fn check_inherents(block: Block, data: OldInherentData) -> ::std::result::Result<(), OldCheckInherentError>; /// Generate a random seed. fn random_seed() -> ::Hash; } diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 1cc3e4c1a9ee171848328d702ccba9eb403d2de0..fd1ce4aefbf85a34bfd6e51bc538e8e139842846 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,15 +17,15 @@ use super::api::BlockBuilder as BlockBuilderApi; use std::vec::Vec; use parity_codec::Encode; -use crate::blockchain::HeaderBackend; +use runtime_primitives::ApplyOutcome; +use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef }; -use primitives::H256; -use runtime_primitives::generic::BlockId; +use primitives::{H256, ExecutionContext}; +use crate::blockchain::HeaderBackend; use crate::runtime_api::Core; use crate::error; -use runtime_primitives::{ApplyOutcome, ExecutionContext}; /// Utility for building new (valid) blocks from a stream of extrinsics. @@ -64,7 +64,7 @@ where Default::default() ); let api = api.runtime_api(); - api.initialise_block_with_context(block_id, ExecutionContext::BlockConstruction, &header)?; + api.initialize_block_with_context(block_id, ExecutionContext::BlockConstruction, &header)?; Ok(BlockBuilder { header, extrinsics: Vec::new(), @@ -97,7 +97,7 @@ where /// Consume the builder to return a valid `Block` containing all pushed extrinsics. pub fn bake(mut self) -> error::Result { - self.header = self.api.finalise_block_with_context(&self.block_id, ExecutionContext::BlockConstruction)?; + self.header = self.api.finalize_block_with_context(&self.block_id, ExecutionContext::BlockConstruction)?; debug_assert_eq!( self.header.extrinsics_root().clone(), diff --git a/core/client/src/block_builder/mod.rs b/core/client/src/block_builder/mod.rs index f22f599ffdd9a2ae356bef3006aff19a4225bd2d..7f617044a42cf7cbb734f516a702591f60742c10 100644 --- a/core/client/src/block_builder/mod.rs +++ b/core/client/src/block_builder/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/src/blockchain.rs b/core/client/src/blockchain.rs index eb9ce1342eade2c58ef154d583a302f4ddb54987..5d7b2a9c231e34ed0b70e9b82013a066f3b27022 100644 --- a/core/client/src/blockchain.rs +++ b/core/client/src/blockchain.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,9 +16,12 @@ //! Substrate blockchain trait -use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Header as HeaderT, NumberFor}; +use std::sync::Arc; + +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use runtime_primitives::generic::BlockId; use runtime_primitives::Justification; +use consensus::well_known_cache_keys; use crate::error::{ErrorKind, Result}; @@ -78,7 +81,7 @@ pub trait Backend: HeaderBackend { /// Get last finalized block hash. fn last_finalized(&self) -> Result; /// Returns data cache reference, if it is enabled on this backend. - fn cache(&self) -> Option<&Cache>; + fn cache(&self) -> Option>>; /// Returns hashes of all blocks that are leaves of the block tree. /// in other words, that have no children, are chain heads. @@ -89,10 +92,16 @@ pub trait Backend: HeaderBackend { fn children(&self, parent_hash: Block::Hash) -> Result>; } +/// Provides access to the optional cache. +pub trait ProvideCache { + /// Returns data cache reference, if it is enabled on this backend. + fn cache(&self) -> Option>>; +} + /// Blockchain optional data cache. pub trait Cache: Send + Sync { - /// Returns the set of authorities, that was active at given block or None if there's no entry in the cache. - fn authorities_at(&self, block: BlockId) -> Option>>; + /// Returns cached value by the given key. + fn get_at(&self, key: &well_known_cache_keys::Id, block: &BlockId) -> Option>; } /// Blockchain info diff --git a/core/client/src/call_executor.rs b/core/client/src/call_executor.rs index 13ff478f3becb1ef271596256eb6659e1e47e1fd..20460f72add74ebf51026353262cabdd96fe2fb7 100644 --- a/core/client/src/call_executor.rs +++ b/core/client/src/call_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,12 +19,12 @@ use parity_codec::{Encode, Decode}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::Block as BlockT; use state_machine::{ - self, OverlayedChanges, Ext, CodeExecutor, ExecutionManager, ExecutionStrategy + self, OverlayedChanges, Ext, CodeExecutor, ExecutionManager, ExecutionStrategy, NeverOffchainExt, }; use executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; use hash_db::Hasher; use trie::MemoryDB; -use primitives::{H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue}; +use primitives::{H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue, OffchainExt}; use crate::backend; use crate::error; @@ -42,12 +42,15 @@ where /// Execute a call to a contract on top of state in a block of given hash. /// /// No changes are made. - fn call( + fn call< + O: OffchainExt, + >( &self, id: &BlockId, method: &str, call_data: &[u8], strategy: ExecutionStrategy, + side_effects_handler: Option<&mut O>, ) -> Result, error::Error>; /// Execute a contextual call on top of state in a block of a given hash. @@ -56,6 +59,7 @@ where /// Before executing the method, passed header is installed as the current header /// of the execution context. fn contextual_call< + O: OffchainExt, PB: Fn() -> error::Result, EM: Fn( Result, Self::Error>, @@ -69,10 +73,11 @@ where method: &str, call_data: &[u8], changes: &mut OverlayedChanges, - initialised_block: &mut Option>, + initialized_block: &mut Option>, prepare_environment_block: PB, execution_manager: ExecutionManager, native_call: Option, + side_effects_handler: Option<&mut O>, ) -> error::Result> where ExecutionManager: Clone; /// Extract RuntimeVersion of given block @@ -84,6 +89,7 @@ where /// /// No changes are made. fn call_at_state< + O: OffchainExt, S: state_machine::Backend, F: FnOnce( Result, Self::Error>, @@ -98,6 +104,7 @@ where call_data: &[u8], manager: ExecutionManager, native_call: Option, + side_effects_handler: Option<&mut O>, ) -> Result<(NativeOrEncoded, S::Transaction, Option>), error::Error>; /// Execute a call to a contract on top of given state, gathering execution proof. @@ -140,7 +147,10 @@ pub struct LocalCallExecutor { impl LocalCallExecutor { /// Creates new instance of local call executor. pub fn new(backend: Arc, executor: E) -> Self { - LocalCallExecutor { backend, executor } + LocalCallExecutor { + backend, + executor, + } } } @@ -161,17 +171,19 @@ where { type Error = E::Error; - fn call(&self, + fn call(&self, id: &BlockId, method: &str, call_data: &[u8], - strategy: ExecutionStrategy + strategy: ExecutionStrategy, + side_effects_handler: Option<&mut O>, ) -> error::Result> { let mut changes = OverlayedChanges::default(); let state = self.backend.state_at(*id)?; let return_data = state_machine::new( &state, self.backend.changes_trie_storage(), + side_effects_handler, &mut changes, &self.executor, method, @@ -187,6 +199,7 @@ where } fn contextual_call< + O: OffchainExt, PB: Fn() -> error::Result, EM: Fn( Result, Self::Error>, @@ -200,32 +213,35 @@ where method: &str, call_data: &[u8], changes: &mut OverlayedChanges, - initialised_block: &mut Option>, + initialized_block: &mut Option>, prepare_environment_block: PB, execution_manager: ExecutionManager, native_call: Option, + mut side_effects_handler: Option<&mut O>, ) -> Result, error::Error> where ExecutionManager: Clone { let state = self.backend.state_at(*at)?; - if method != "Core_initialise_block" && initialised_block.map(|id| id != *at).unwrap_or(true) { + if method != "Core_initialize_block" && initialized_block.map(|id| id != *at).unwrap_or(true) { let header = prepare_environment_block()?; state_machine::new( &state, self.backend.changes_trie_storage(), + side_effects_handler.as_mut().map(|x| &mut **x), changes, &self.executor, - "Core_initialise_block", + "Core_initialize_block", &header.encode(), ).execute_using_consensus_failure_handler::<_, R, fn() -> _>( execution_manager.clone(), false, None, )?; - *initialised_block = Some(*at); + *initialized_block = Some(*at); } let result = state_machine::new( &state, self.backend.changes_trie_storage(), + side_effects_handler, changes, &self.executor, method, @@ -236,9 +252,9 @@ where native_call, ).map(|(result, _, _)| result)?; - // If the method is `initialise_block` we need to set the `initialised_block` - if method == "Core_initialise_block" { - *initialised_block = Some(*at); + // If the method is `initialize_block` we need to set the `initialized_block` + if method == "Core_initialize_block" { + *initialized_block = Some(*at); } self.backend.destroy_state(state)?; @@ -248,12 +264,13 @@ where fn runtime_version(&self, id: &BlockId) -> error::Result { let mut overlay = OverlayedChanges::default(); let state = self.backend.state_at(*id)?; - let mut ext = Ext::new(&mut overlay, &state, self.backend.changes_trie_storage()); + let mut ext = Ext::new(&mut overlay, &state, self.backend.changes_trie_storage(), NeverOffchainExt::new()); self.executor.runtime_version(&mut ext) .ok_or(error::ErrorKind::VersionInvalid.into()) } fn call_at_state< + O: OffchainExt, S: state_machine::Backend, F: FnOnce( Result, Self::Error>, @@ -268,10 +285,12 @@ where call_data: &[u8], manager: ExecutionManager, native_call: Option, + side_effects_handler: Option<&mut O>, ) -> error::Result<(NativeOrEncoded, S::Transaction, Option>)> { state_machine::new( state, self.backend.changes_trie_storage(), + side_effects_handler, changes, &self.executor, method, diff --git a/core/client/src/cht.rs b/core/client/src/cht.rs index 59377b532588ad2bce133c7aac526be6d207305a..d8e7ffbff33a74ab65539913fa9f23839422660f 100644 --- a/core/client/src/cht.rs +++ b/core/client/src/cht.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/src/client.rs b/core/client/src/client.rs index a170c7e202609a241c326f56a261724d6d8368e8..041933cfffaff9f964adf117dba6022bbffd5fa4 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ //! Substrate Client -use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc, panic::UnwindSafe, result}; +use std::{marker::PhantomData, collections::{HashSet, BTreeMap, HashMap}, sync::Arc, panic::UnwindSafe, result}; use crate::error::Error; use futures::sync::mpsc; use parking_lot::{Mutex, RwLock}; @@ -27,15 +27,15 @@ use runtime_primitives::{ }; use consensus::{ Error as ConsensusError, ErrorKind as ConsensusErrorKind, ImportBlock, ImportResult, - BlockOrigin, ForkChoiceStrategy, + BlockOrigin, ForkChoiceStrategy, well_known_cache_keys::Id as CacheKeyId, }; use runtime_primitives::traits::{ Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash, - ApiRef, ProvideRuntimeApi, Digest, DigestItem, AuthorityIdFor + ApiRef, ProvideRuntimeApi, Digest, DigestItem }; -use runtime_primitives::{BuildStorage, ExecutionContext}; +use runtime_primitives::BuildStorage; use crate::runtime_api::{CallRuntimeAt, ConstructRuntimeApi}; -use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue}; +use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue, ExecutionContext}; use primitives::storage::{StorageKey, StorageData}; use primitives::storage::well_known_keys; use parity_codec::{Encode, Decode}; @@ -43,13 +43,14 @@ use state_machine::{ DBValue, Backend as StateBackend, CodeExecutor, ChangesTrieAnchorBlockId, ExecutionStrategy, ExecutionManager, prove_read, ChangesTrieRootsStorage, ChangesTrieStorage, - key_changes, key_changes_proof, OverlayedChanges, + key_changes, key_changes_proof, OverlayedChanges, NeverOffchainExt, }; use hash_db::Hasher; use crate::backend::{self, BlockImportOperation, PrunableStateChangesTrieStorage}; use crate::blockchain::{ - self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend + self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend, + ProvideCache, Cache, }; use crate::call_executor::{CallExecutor, LocalCallExecutor}; use executor::{RuntimeVersion, RuntimeInfo}; @@ -84,6 +85,8 @@ pub struct ExecutionStrategies { pub importing: ExecutionStrategy, /// Execution strategy used when constructing blocks. pub block_construction: ExecutionStrategy, + /// Execution strategy used for offchain workers. + pub offchain_worker: ExecutionStrategy, /// Execution strategy used in other cases. pub other: ExecutionStrategy, } @@ -94,6 +97,7 @@ impl Default for ExecutionStrategies { syncing: ExecutionStrategy::NativeElseWasm, importing: ExecutionStrategy::NativeElseWasm, block_construction: ExecutionStrategy::AlwaysWasm, + offchain_worker: ExecutionStrategy::NativeWhenPossible, other: ExecutionStrategy::NativeElseWasm, } } @@ -167,8 +171,10 @@ pub struct ClientInfo { pub enum BlockStatus { /// Added to the import queue. Queued, - /// Already in the blockchain. - InChain, + /// Already in the blockchain and the state is available. + InChainWithState, + /// In the blockchain, but the state is not available. + InChainPruned, /// Block or parent is known to be bad. KnownBad, /// Not in the queue or the blockchain. @@ -280,7 +286,7 @@ impl Client where backend.begin_state_operation(&mut op, BlockId::Hash(Default::default()))?; let state_root = op.reset_storage(genesis_storage, children_genesis_storage)?; let genesis_block = genesis::construct_genesis_block::(state_root.into()); - info!("Initialising Genesis block/state (state: {}, header-hash: {})", genesis_block.header().state_root(), genesis_block.header().hash()); + info!("Initializing Genesis block/state (state: {}, header-hash: {})", genesis_block.header().state_root(), genesis_block.header().hash()); op.set_block_data( genesis_block.deconstruct().0, Some(vec![]), @@ -337,16 +343,6 @@ impl Client where .expect("None is returned if there's no value stored for the given key; ':code' key is always defined; qed").0) } - /// Get the set of authorities at a given block. - pub fn authorities_at(&self, id: &BlockId) -> error::Result>> { - match self.backend.blockchain().cache().and_then(|cache| cache.authorities_at(*id)) { - Some(cached_value) => Ok(cached_value), - None => self.executor.call(id, "Core_authorities", &[], ExecutionStrategy::NativeElseWasm) - .and_then(|r| Vec::>::decode(&mut &r[..]) - .ok_or_else(|| error::ErrorKind::InvalidAuthoritiesSet.into())) - } - } - /// Get the RuntimeVersion at a given block. pub fn runtime_version_at(&self, id: &BlockId) -> error::Result { self.executor.runtime_version(id) @@ -503,8 +499,8 @@ impl Client where } impl<'a, Block: BlockT> ChangesTrieStorage for AccessedRootsRecorder<'a, Block> { - fn get(&self, key: &H256) -> Result, String> { - self.storage.get(key) + fn get(&self, key: &H256, prefix: &[u8]) -> Result, String> { + self.storage.get(key, prefix) } } @@ -676,7 +672,7 @@ impl Client where &self, operation: &mut ClientImportOperation, import_block: ImportBlock, - new_authorities: Option>>, + new_cache: HashMap>, ) -> error::Result where E: CallExecutor + Send + Sync + Clone, { @@ -724,7 +720,7 @@ impl Client where import_headers, justification, body, - new_authorities, + new_cache, finalized, auxiliary, fork_choice, @@ -747,7 +743,7 @@ impl Client where import_headers: PrePostHeader, justification: Option, body: Option>, - authorities: Option>>, + new_cache: HashMap>, finalized: bool, aux: Vec<(Vec, Option>)>, fork_choice: ForkChoiceStrategy, @@ -805,9 +801,7 @@ impl Client where leaf_state, )?; - if let Some(authorities) = authorities { - operation.op.update_authorities(authorities); - } + operation.op.update_cache(new_cache); if let Some(storage_update) = storage_update { operation.op.update_db_storage(storage_update)?; } @@ -869,7 +863,7 @@ impl Client where }), } }; - let (_, storage_update, changes_update) = self.executor.call_at_state::<_, _, NeverNativeValue, fn() -> _>( + let (_, storage_update, changes_update) = self.executor.call_at_state::<_, _, _, NeverNativeValue, fn() -> _>( transaction_state, &mut overlay, "Core_execute_block", @@ -879,6 +873,7 @@ impl Client where _ => get_execution_manager(self.execution_strategies().importing), }, None, + NeverOffchainExt::new(), )?; overlay.commit_prospective(); @@ -1073,9 +1068,19 @@ impl Client where return Ok(BlockStatus::Queued); } } - match self.backend.blockchain().header(*id).map_err(|e| error::Error::from_blockchain(Box::new(e)))?.is_some() { - true => Ok(BlockStatus::InChain), - false => Ok(BlockStatus::Unknown), + let hash_and_number = match id.clone() { + BlockId::Hash(hash) => self.backend.blockchain().number(hash)?.map(|n| (hash, n)), + BlockId::Number(n) => self.backend.blockchain().hash(n)?.map(|hash| (hash, n)), + }; + match hash_and_number { + Some((hash, number)) => { + if self.backend().have_state_at(&hash, number) { + Ok(BlockStatus::InChainWithState) + } else { + Ok(BlockStatus::InChainPruned) + } + } + None => Ok(BlockStatus::Unknown), } } @@ -1308,6 +1313,15 @@ impl ChainHeaderBackend for Client wher } } +impl ProvideCache for Client where + B: backend::Backend, + Block: BlockT, +{ + fn cache(&self) -> Option>> { + self.backend.blockchain().cache() + } +} + impl ProvideRuntimeApi for Client where B: backend::Backend, E: CallExecutor + Clone + Send + Sync, @@ -1327,32 +1341,41 @@ impl CallRuntimeAt for Client where Block: BlockT { fn call_api_at< - R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result + UnwindSafe + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, at: &BlockId, function: &'static str, args: Vec, changes: &mut OverlayedChanges, - initialised_block: &mut Option>, + initialized_block: &mut Option>, native_call: Option, - context: ExecutionContext + context: ExecutionContext, ) -> error::Result> { let manager = match context { ExecutionContext::BlockConstruction => self.execution_strategies.block_construction.get_manager(), ExecutionContext::Syncing => self.execution_strategies.syncing.get_manager(), ExecutionContext::Importing => self.execution_strategies.importing.get_manager(), + ExecutionContext::OffchainWorker(_) => self.execution_strategies.offchain_worker.get_manager(), ExecutionContext::Other => self.execution_strategies.other.get_manager(), }; - self.executor.contextual_call::<_, fn(_,_) -> _,_,_>( + + let mut offchain_extensions = match context { + ExecutionContext::OffchainWorker(ext) => Some(ext), + _ => None, + }; + + self.executor.contextual_call::<_, _, fn(_,_) -> _,_,_>( at, function, &args, changes, - initialised_block, + initialized_block, || self.prepare_environment_block(at), manager, native_call, + offchain_extensions.as_mut(), ) } @@ -1373,10 +1396,10 @@ impl consensus::BlockImport for Client fn import_block( &self, import_block: ImportBlock, - new_authorities: Option>>, + new_cache: HashMap>, ) -> Result { self.lock_import_and_run(|operation| { - self.apply_block(operation, import_block, new_authorities) + self.apply_block(operation, import_block, new_cache) }).map_err(|e| ConsensusErrorKind::ClientImport(e.to_string()).into()) } @@ -1386,35 +1409,26 @@ impl consensus::BlockImport for Client hash: Block::Hash, parent_hash: Block::Hash, ) -> Result { - match self.backend.blockchain().status(BlockId::Hash(parent_hash)) + match self.block_status(&BlockId::Hash(parent_hash)) .map_err(|e| ConsensusError::from(ConsensusErrorKind::ClientImport(e.to_string())))? { - blockchain::BlockStatus::InChain => {}, - blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent), + BlockStatus::InChainWithState | BlockStatus::Queued => {}, + BlockStatus::Unknown | BlockStatus::InChainPruned => return Ok(ImportResult::UnknownParent), + BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), } - match self.backend.blockchain().status(BlockId::Hash(hash)) + match self.block_status(&BlockId::Hash(hash)) .map_err(|e| ConsensusError::from(ConsensusErrorKind::ClientImport(e.to_string())))? { - blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain), - blockchain::BlockStatus::Unknown => {}, + BlockStatus::InChainWithState | BlockStatus::Queued => return Ok(ImportResult::AlreadyInChain), + BlockStatus::Unknown | BlockStatus::InChainPruned => {}, + BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), } Ok(ImportResult::imported()) } } -impl consensus::Authorities for Client where - B: backend::Backend, - E: CallExecutor + Clone, - Block: BlockT, -{ - type Error = Error; - fn authorities(&self, at: &BlockId) -> Result>, Self::Error> { - self.authorities_at(at).map_err(|e| e.into()) - } -} - impl CurrentHeight for Client where B: backend::Backend, E: CallExecutor, @@ -1520,11 +1534,10 @@ impl backend::AuxStore for Client pub(crate) mod tests { use std::collections::HashMap; use super::*; - use keyring::Keyring; use primitives::twox_128; use runtime_primitives::traits::DigestItem as DigestItemT; use runtime_primitives::generic::DigestItem; - use test_client::{self, TestClient}; + use test_client::{self, TestClient, AccountKeyring}; use consensus::BlockOrigin; use test_client::client::backend::Backend as TestBackend; use test_client::BlockBuilderExt; @@ -1541,10 +1554,10 @@ pub(crate) mod tests { ) { // prepare block structure let blocks_transfers = vec![ - vec![(Keyring::Alice, Keyring::Dave), (Keyring::Bob, Keyring::Dave)], - vec![(Keyring::Charlie, Keyring::Eve)], + vec![(AccountKeyring::Alice, AccountKeyring::Dave), (AccountKeyring::Bob, AccountKeyring::Dave)], + vec![(AccountKeyring::Charlie, AccountKeyring::Eve)], vec![], - vec![(Keyring::Alice, Keyring::Dave)], + vec![(AccountKeyring::Alice, AccountKeyring::Dave)], ]; // prepare client ang import blocks @@ -1555,8 +1568,8 @@ pub(crate) mod tests { let mut builder = remote_client.new_block().unwrap(); for (from, to) in block_transfers { builder.push_transfer(Transfer { - from: from.to_raw_public().into(), - to: to.to_raw_public().into(), + from: from.into(), + to: to.into(), amount: 1, nonce: *nonces.entry(from).and_modify(|n| { *n = *n + 1 }).or_default(), }).unwrap(); @@ -1571,12 +1584,12 @@ pub(crate) mod tests { } // prepare test cases - let alice = twox_128(&runtime::system::balance_of_key(Keyring::Alice.to_raw_public().into())).to_vec(); - let bob = twox_128(&runtime::system::balance_of_key(Keyring::Bob.to_raw_public().into())).to_vec(); - let charlie = twox_128(&runtime::system::balance_of_key(Keyring::Charlie.to_raw_public().into())).to_vec(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); - let eve = twox_128(&runtime::system::balance_of_key(Keyring::Eve.to_raw_public().into())).to_vec(); - let ferdie = twox_128(&runtime::system::balance_of_key(Keyring::Ferdie.to_raw_public().into())).to_vec(); + let alice = twox_128(&runtime::system::balance_of_key(AccountKeyring::Alice.into())).to_vec(); + let bob = twox_128(&runtime::system::balance_of_key(AccountKeyring::Bob.into())).to_vec(); + let charlie = twox_128(&runtime::system::balance_of_key(AccountKeyring::Charlie.into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let eve = twox_128(&runtime::system::balance_of_key(AccountKeyring::Eve.into())).to_vec(); + let ferdie = twox_128(&runtime::system::balance_of_key(AccountKeyring::Ferdie.into())).to_vec(); let test_cases = vec![ (1, 4, alice.clone(), vec![(4, 0), (1, 0)]), (1, 3, alice.clone(), vec![(1, 0)]), @@ -1604,37 +1617,25 @@ pub(crate) mod tests { } #[test] - fn client_initialises_from_genesis_ok() { + fn client_initializes_from_genesis_ok() { let client = test_client::new(); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - Keyring::Alice.to_raw_public().into() + AccountKeyring::Alice.into() ).unwrap(), 1000 ); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - Keyring::Ferdie.to_raw_public().into() + AccountKeyring::Ferdie.into() ).unwrap(), 0 ); } - #[test] - fn authorities_call_works() { - let client = test_client::new(); - - assert_eq!(client.info().unwrap().chain.best_number, 0); - assert_eq!(client.authorities_at(&BlockId::Number(0)).unwrap(), vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Bob.to_raw_public().into(), - Keyring::Charlie.to_raw_public().into() - ]); - } - #[test] fn block_builder_works_with_no_transactions() { let client = test_client::new(); @@ -1653,8 +1654,8 @@ pub(crate) mod tests { let mut builder = client.new_block().unwrap(); builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -1666,28 +1667,19 @@ pub(crate) mod tests { assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - Keyring::Alice.to_raw_public().into() + AccountKeyring::Alice.into() ).unwrap(), 958 ); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - Keyring::Ferdie.to_raw_public().into() + AccountKeyring::Ferdie.into() ).unwrap(), 42 ); } - #[test] - fn client_uses_authorities_from_blockchain_cache() { - let client = test_client::new_light(); - let genesis_hash = client.header(&BlockId::Number(0)).unwrap().unwrap().hash(); - // authorities cache is first filled in genesis block - // => should be read from cache here (remote request will fail in this test) - assert!(!client.authorities_at(&BlockId::Hash(genesis_hash)).unwrap().is_empty()); - } - #[test] fn block_builder_does_not_include_invalid() { let client = test_client::new(); @@ -1695,15 +1687,15 @@ pub(crate) mod tests { let mut builder = client.new_block().unwrap(); builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); assert!(builder.push_transfer(Transfer { - from: Keyring::Eve.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Eve.into(), + to: AccountKeyring::Alice.into(), amount: 42, nonce: 0, }).is_err()); @@ -1789,8 +1781,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -1809,8 +1801,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -1821,8 +1813,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); @@ -1910,8 +1902,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -1930,8 +1922,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -1942,8 +1934,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); diff --git a/core/client/src/error.rs b/core/client/src/error.rs index bfc073f634c1bb0a0e681c96c983de42722c5f3c..3ee3c0e2a1ac52c157a20398beaf3ed5adea62ae 100644 --- a/core/client/src/error.rs +++ b/core/client/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -62,12 +62,6 @@ error_chain! { display("Blockchain: {}", e), } - /// Invalid authorities set received from the runtime. - InvalidAuthoritiesSet { - description("authorities set is invalid"), - display("Current state of blockchain has invalid authorities set"), - } - /// Could not get runtime version. VersionInvalid { description("Runtime version error"), diff --git a/core/client/src/genesis.rs b/core/client/src/genesis.rs index a048433d39b561a1e535b6067ee9e3a043a83b46..eea0a251cac79d45031c12831063598ea4776c4d 100644 --- a/core/client/src/genesis.rs +++ b/core/client/src/genesis.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -41,14 +41,16 @@ pub fn construct_genesis_block< mod tests { use super::*; use parity_codec::{Encode, Decode, Joiner}; - use keyring::Keyring; use executor::{NativeExecutionDispatch, native_executor_instance}; use state_machine::{self, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage}; use state_machine::backend::InMemory; - use test_client::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; - use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic}; + use test_client::{ + runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}, + runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic}, + AccountKeyring, AuthorityKeyring + }; use runtime_primitives::traits::BlakeTwo256; - use primitives::{Blake2Hasher, ed25519::{Public, Pair}}; + use primitives::Blake2Hasher; use hex::*; native_executor_instance!(Executor, test_client::runtime::api::dispatch, test_client::runtime::native_version, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); @@ -67,7 +69,7 @@ mod tests { use trie::ordered_trie_root; let transactions = txs.into_iter().map(|tx| { - let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from.to_fixed_bytes())).unwrap()) + let signature = AccountKeyring::from_public(&tx.from).unwrap() .sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) @@ -75,7 +77,6 @@ mod tests { let extrinsics_root = ordered_trie_root::(transactions.iter().map(Encode::encode)).into(); - println!("root before: {:?}", extrinsics_root); let mut header = Header { parent_hash, number, @@ -89,9 +90,10 @@ mod tests { state_machine::new( backend, Some(&InMemoryChangesTrieStorage::new()), + state_machine::NeverOffchainExt::new(), &mut overlay, &executor(), - "Core_initialise_block", + "Core_initialize_block", &header.encode(), ).execute( ExecutionStrategy::NativeElseWasm, @@ -101,6 +103,7 @@ mod tests { state_machine::new( backend, Some(&InMemoryChangesTrieStorage::new()), + state_machine::NeverOffchainExt::new(), &mut overlay, &executor(), "BlockBuilder_apply_extrinsic", @@ -113,15 +116,15 @@ mod tests { let (ret_data, _, _) = state_machine::new( backend, Some(&InMemoryChangesTrieStorage::new()), + state_machine::NeverOffchainExt::new(), &mut overlay, &executor(), - "BlockBuilder_finalise_block", + "BlockBuilder_finalize_block", &[], ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); header = Header::decode(&mut &ret_data[..]).unwrap(); - println!("root after: {:?}", header.extrinsics_root); (vec![].and(&Block { header, extrinsics: transactions }), hash) } @@ -133,8 +136,8 @@ mod tests { genesis_hash, hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), vec![Transfer { - from: Keyring::One.to_raw_public().into(), - to: Keyring::Two.to_raw_public().into(), + from: AccountKeyring::One.into(), + to: AccountKeyring::Two.into(), amount: 69, nonce: 0, }] @@ -143,8 +146,10 @@ mod tests { #[test] fn construct_genesis_should_work_with_native() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 1000 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -158,6 +163,7 @@ mod tests { let _ = state_machine::new( &backend, Some(&InMemoryChangesTrieStorage::new()), + state_machine::NeverOffchainExt::new(), &mut overlay, &executor(), "Core_execute_block", @@ -169,8 +175,10 @@ mod tests { #[test] fn construct_genesis_should_work_with_wasm() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 1000 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -184,6 +192,7 @@ mod tests { let _ = state_machine::new( &backend, Some(&InMemoryChangesTrieStorage::new()), + state_machine::NeverOffchainExt::new(), &mut overlay, &executor(), "Core_execute_block", @@ -194,10 +203,11 @@ mod tests { } #[test] - #[should_panic] fn construct_genesis_with_bad_transaction_should_panic() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 68 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 68 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -208,15 +218,17 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = state_machine::new( + let r = state_machine::new( &backend, Some(&InMemoryChangesTrieStorage::new()), + state_machine::NeverOffchainExt::new(), &mut overlay, &Executor::new(None), "Core_execute_block", &b1data, ).execute( ExecutionStrategy::NativeElseWasm, - ).unwrap(); + ); + assert!(r.is_err()); } } diff --git a/core/client/src/in_mem.rs b/core/client/src/in_mem.rs index 6c90d9ae3e84fb5d3947d9b7bc03dbf02059db6c..29256169f943425926abb1b8e6761087e2329cd9 100644 --- a/core/client/src/in_mem.rs +++ b/core/client/src/in_mem.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,13 +22,14 @@ use parking_lot::RwLock; use primitives::{ChangesTrieConfiguration, storage::well_known_keys}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, - NumberFor, As, Digest, DigestItem, AuthorityIdFor}; + NumberFor, As, Digest, DigestItem}; use runtime_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay}; use state_machine::backend::{Backend as StateBackend, InMemory, Consolidate}; use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId}; use hash_db::Hasher; use heapsize::HeapSizeOf; use trie::MemoryDB; +use consensus::well_known_cache_keys::Id as CacheKeyId; use crate::error; use crate::backend::{self, NewBlockState}; @@ -104,12 +105,6 @@ struct BlockchainStorage { /// In-memory blockchain. Supports concurrent reads. pub struct Blockchain { storage: Arc>>, - cache: Cache, -} - -struct Cache { - storage: Arc>>, - authorities_at: RwLock>>>>, } impl Clone for Blockchain { @@ -117,10 +112,6 @@ impl Clone for Blockchain { let storage = Arc::new(RwLock::new(self.storage.read().clone())); Blockchain { storage: storage.clone(), - cache: Cache { - storage, - authorities_at: RwLock::new(self.cache.authorities_at.read().clone()), - }, } } } @@ -152,10 +143,6 @@ impl Blockchain { })); Blockchain { storage: storage.clone(), - cache: Cache { - storage: storage, - authorities_at: Default::default(), - }, } } @@ -355,8 +342,8 @@ impl blockchain::Backend for Blockchain { Ok(self.storage.read().finalized_hash.clone()) } - fn cache(&self) -> Option<&blockchain::Cache> { - Some(&self.cache) + fn cache(&self) -> Option>> { + None } fn leaves(&self) -> error::Result> { @@ -368,6 +355,12 @@ impl blockchain::Backend for Blockchain { } } +impl blockchain::ProvideCache for Blockchain { + fn cache(&self) -> Option>> { + None + } +} + impl backend::AuxStore for Blockchain { fn insert_aux< 'a, @@ -398,16 +391,12 @@ impl light::blockchain::Storage for Blockchain fn import_header( &self, header: Block::Header, - authorities: Option>>, + _cache: HashMap>, state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, ) -> error::Result<()> { let hash = header.hash(); - let parent_hash = *header.parent_hash(); self.insert(hash, header, None, None, state)?; - if state.is_best() { - self.cache.insert(parent_hash, authorities); - } self.write_aux(aux_ops); Ok(()) @@ -435,15 +424,15 @@ impl light::blockchain::Storage for Blockchain .ok_or_else(|| error::ErrorKind::Backend(format!("Changes trie CHT for block {} not exists", block)).into()) } - fn cache(&self) -> Option<&blockchain::Cache> { - Some(&self.cache) + fn cache(&self) -> Option>> { + None } } /// In-memory operation. pub struct BlockImportOperation { pending_block: Option>, - pending_authorities: Option>>, + pending_cache: HashMap>, old_state: InMemory, new_state: Option>, changes_trie_update: Option>, @@ -480,8 +469,8 @@ where Ok(()) } - fn update_authorities(&mut self, authorities: Vec>) { - self.pending_authorities = Some(authorities); + fn update_cache(&mut self, cache: HashMap>) { + self.pending_cache = cache; } fn update_db_storage(&mut self, update: as StateBackend>::Transaction) -> error::Result<()> { @@ -602,7 +591,7 @@ where let old_state = self.state_at(BlockId::Hash(Default::default()))?; Ok(BlockImportOperation { pending_block: None, - pending_authorities: None, + pending_cache: Default::default(), old_state, new_state: None, changes_trie_update: None, @@ -629,7 +618,6 @@ where let (header, body, justification) = pending_block.block.into_inner(); let hash = header.hash(); - let parent_hash = *header.parent_hash(); self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone())); @@ -642,10 +630,6 @@ where } self.blockchain.insert(hash, header, justification, body, pending_block.state)?; - // dumb implementation - store value for each block - if pending_block.state.is_best() { - self.blockchain.cache.insert(parent_hash, operation.pending_authorities); - } } if !operation.aux.is_empty() { @@ -710,23 +694,6 @@ where } } -impl Cache { - fn insert(&self, at: Block::Hash, authorities: Option>>) { - self.authorities_at.write().insert(at, authorities); - } -} - -impl blockchain::Cache for Cache { - fn authorities_at(&self, block: BlockId) -> Option>> { - let hash = match block { - BlockId::Hash(hash) => hash, - BlockId::Number(number) => self.storage.read().hashes.get(&number).cloned()?, - }; - - self.authorities_at.read().get(&hash).cloned().unwrap_or(None) - } -} - /// Prunable in-memory changes trie storage. pub struct ChangesTrieStorage(InMemoryChangesTrieStorage) where H::Out: HeapSizeOf; impl backend::PrunableStateChangesTrieStorage for ChangesTrieStorage where H::Out: HeapSizeOf { @@ -742,20 +709,11 @@ impl state_machine::ChangesTrieRootsStorage for ChangesTrieStorage } impl state_machine::ChangesTrieStorage for ChangesTrieStorage where H::Out: HeapSizeOf { - fn get(&self, key: &H::Out) -> Result, String> { - self.0.get(key) + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String> { + self.0.get(key, prefix) } } -/// Insert authorities entry into in-memory blockchain cache. Extracted as a separate function to use it in tests. -pub fn cache_authorities_at( - blockchain: &Blockchain, - at: Block::Hash, - authorities: Option>> -) { - blockchain.cache.insert(at, authorities); -} - /// Check that genesis storage is valid. pub fn check_genesis_storage(top: &StorageOverlay, children: &ChildrenStorageOverlay) -> error::Result<()> { if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { diff --git a/core/client/src/leaves.rs b/core/client/src/leaves.rs index 28053cec44efa9f545ec19ff7734caf94ccb282d..cc906d59a4bb1882211df3de855afe3d683aad7c 100644 --- a/core/client/src/leaves.rs +++ b/core/client/src/leaves.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/src/lib.rs b/core/client/src/lib.rs index 25b863cda4ddb37997cc22beddc3b9845ca7f6db..d2da243d14a4db3980bcc91c200deb80ba0aed0e 100644 --- a/core/client/src/lib.rs +++ b/core/client/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/src/light/backend.rs b/core/client/src/light/backend.rs index 948db23d34ac57b23693349838142c4211ac941d..b4b805f3c6411c1f2c83460f6a8779c0d823c674 100644 --- a/core/client/src/light/backend.rs +++ b/core/client/src/light/backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,7 +24,7 @@ use parking_lot::RwLock; use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; use state_machine::{Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState}; -use runtime_primitives::traits::{Block as BlockT, NumberFor, AuthorityIdFor, Zero, Header}; +use runtime_primitives::traits::{Block as BlockT, NumberFor, Zero, Header}; use crate::in_mem::{self, check_genesis_storage}; use crate::backend::{AuxStore, Backend as ClientBackend, BlockImportOperation, RemoteBackend, NewBlockState}; use crate::blockchain::HeaderBackend as BlockchainHeaderBackend; @@ -34,8 +34,9 @@ use crate::light::fetcher::{Fetcher, RemoteReadRequest}; use hash_db::Hasher; use trie::MemoryDB; use heapsize::HeapSizeOf; +use consensus::well_known_cache_keys; -const IN_MEMORY_EXPECT_PROOF: &'static str = "InMemory state backend has Void error type and always suceeds; qed"; +const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always suceeds; qed"; /// Light client backend. pub struct Backend { @@ -46,7 +47,7 @@ pub struct Backend { /// Light block (header and justification) import operation. pub struct ImportOperation { header: Option, - authorities: Option>>, + cache: HashMap>, leaf_state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, finalized_blocks: Vec>, @@ -117,7 +118,7 @@ impl ClientBackend for Backend where fn begin_operation(&self) -> ClientResult { Ok(ImportOperation { header: None, - authorities: None, + cache: Default::default(), leaf_state: NewBlockState::Normal, aux_ops: Vec::new(), finalized_blocks: Vec::new(), @@ -146,7 +147,7 @@ impl ClientBackend for Backend where let is_genesis_import = header.number().is_zero(); self.blockchain.storage().import_header( header, - operation.authorities, + operation.cache, operation.leaf_state, operation.aux_ops, )?; @@ -254,8 +255,8 @@ where Ok(()) } - fn update_authorities(&mut self, authorities: Vec>) { - self.authorities = Some(authorities); + fn update_cache(&mut self, cache: HashMap>) { + self.cache = cache; } fn update_db_storage(&mut self, _update: >::Transaction) -> ClientResult<()> { diff --git a/core/client/src/light/blockchain.rs b/core/client/src/light/blockchain.rs index 73d530ce455454f8b4295d4403aee137bfde8a90..e081c14d1a5caee3b7d46611f16c35f09925b448 100644 --- a/core/client/src/light/blockchain.rs +++ b/core/client/src/light/blockchain.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,16 +17,17 @@ //! Light client blockchin backend. Only stores headers and justifications of recent //! blocks. CHT roots are stored for headers of ancient blocks. -use std::sync::Weak; +use std::{sync::{Weak, Arc}, collections::HashMap}; use futures::{Future, IntoFuture}; use parking_lot::Mutex; use runtime_primitives::{Justification, generic::BlockId}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero, AuthorityIdFor}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; +use consensus::well_known_cache_keys; use crate::backend::{AuxStore, NewBlockState}; use crate::blockchain::{Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache, - HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo}; + HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo, ProvideCache}; use crate::cht; use crate::error::{ErrorKind as ClientErrorKind, Result as ClientResult}; use crate::light::fetcher::{Fetcher, RemoteHeaderRequest}; @@ -40,7 +41,7 @@ pub trait Storage: AuxStore + BlockchainHeaderBackend { fn import_header( &self, header: Block::Header, - authorities: Option>>, + cache: HashMap>, state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, ) -> ClientResult<()>; @@ -61,7 +62,7 @@ pub trait Storage: AuxStore + BlockchainHeaderBackend { fn changes_trie_cht_root(&self, cht_size: u64, block: NumberFor) -> ClientResult; /// Get storage cache. - fn cache(&self) -> Option<&BlockchainCache>; + fn cache(&self) -> Option>>; } /// Light client blockchain. @@ -109,7 +110,7 @@ impl BlockchainHeaderBackend for Blockchain where Bloc }; // if the header is from future or genesis (we never prune genesis) => return - if number.is_zero() || self.storage.status(BlockId::Number(number))? != BlockStatus::InChain { + if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown { return Ok(None); } @@ -156,7 +157,7 @@ impl BlockchainBackend for Blockchain where Block: Blo self.storage.last_finalized() } - fn cache(&self) -> Option<&BlockchainCache> { + fn cache(&self) -> Option>> { self.storage.cache() } @@ -169,6 +170,12 @@ impl BlockchainBackend for Blockchain where Block: Blo } } +impl, F, Block: BlockT> ProvideCache for Blockchain { + fn cache(&self) -> Option>> { + self.storage.cache() + } +} + #[cfg(test)] pub mod tests { use std::collections::HashMap; @@ -246,7 +253,7 @@ pub mod tests { fn import_header( &self, _header: Header, - _authorities: Option>>, + _cache: HashMap>, _state: NewBlockState, _aux_ops: Vec<(Vec, Option>)>, ) -> ClientResult<()> { @@ -278,7 +285,7 @@ pub mod tests { ).into()) } - fn cache(&self) -> Option<&BlockchainCache> { + fn cache(&self) -> Option>> { None } } diff --git a/core/client/src/light/call_executor.rs b/core/client/src/light/call_executor.rs index c2857e07a08acde0a42e7ada0bb748c56cf26647..1e50d3398ecf725cd79a4d32df38de28f66b05f0 100644 --- a/core/client/src/light/call_executor.rs +++ b/core/client/src/light/call_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,11 +21,11 @@ use std::{collections::HashSet, sync::Arc, panic::UnwindSafe, result, marker::Ph use futures::{IntoFuture, Future}; use parity_codec::{Encode, Decode}; -use primitives::{H256, Blake2Hasher, convert_hash, NativeOrEncoded}; +use primitives::{H256, Blake2Hasher, convert_hash, NativeOrEncoded, OffchainExt}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT}; use state_machine::{self, Backend as StateBackend, CodeExecutor, OverlayedChanges, ExecutionStrategy, - create_proof_check_backend, execution_proof_check_on_trie_backend, ExecutionManager}; + create_proof_check_backend, execution_proof_check_on_trie_backend, ExecutionManager, NeverOffchainExt}; use hash_db::Hasher; use crate::backend::RemoteBackend; @@ -80,7 +80,16 @@ where { type Error = ClientError; - fn call(&self, id: &BlockId, method: &str, call_data: &[u8], _strategy: ExecutionStrategy) + fn call< + O: OffchainExt, + >( + &self, + id: &BlockId, + method: &str, + call_data: &[u8], + _strategy: ExecutionStrategy, + _side_effects_handler: Option<&mut O>, + ) -> ClientResult> { let block_hash = self.blockchain.expect_block_hash_from_id(id)?; let block_header = self.blockchain.expect_header(id.clone())?; @@ -95,6 +104,7 @@ where } fn contextual_call< + O: OffchainExt, PB: Fn() -> ClientResult, EM: Fn( Result, Self::Error>, @@ -108,26 +118,28 @@ where method: &str, call_data: &[u8], changes: &mut OverlayedChanges, - initialised_block: &mut Option>, + initialized_block: &mut Option>, _prepare_environment_block: PB, execution_manager: ExecutionManager, _native_call: Option, + side_effects_handler: Option<&mut O>, ) -> ClientResult> where ExecutionManager: Clone { // it is only possible to execute contextual call if changes are empty - if !changes.is_empty() || initialised_block.is_some() { + if !changes.is_empty() || initialized_block.is_some() { return Err(ClientErrorKind::NotAvailableOnLightClient.into()); } - self.call(at, method, call_data, (&execution_manager).into()).map(NativeOrEncoded::Encoded) + self.call(at, method, call_data, (&execution_manager).into(), side_effects_handler).map(NativeOrEncoded::Encoded) } fn runtime_version(&self, id: &BlockId) -> ClientResult { - let call_result = self.call(id, "version", &[], ExecutionStrategy::NativeElseWasm)?; + let call_result = self.call(id, "version", &[], ExecutionStrategy::NativeElseWasm, NeverOffchainExt::new())?; RuntimeVersion::decode(&mut call_result.as_slice()) .ok_or_else(|| ClientErrorKind::VersionInvalid.into()) } fn call_at_state< + O: OffchainExt, S: StateBackend, FF: FnOnce( Result, Self::Error>, @@ -142,6 +154,7 @@ where _call_data: &[u8], _m: ExecutionManager, _native_call: Option, + _side_effects_handler: Option<&mut O>, ) -> ClientResult<(NativeOrEncoded, S::Transaction, Option>)> { Err(ClientErrorKind::NotAvailableOnLightClient.into()) } @@ -201,15 +214,24 @@ impl CallExecutor for { type Error = ClientError; - fn call(&self, id: &BlockId, method: &str, call_data: &[u8], strategy: ExecutionStrategy) - -> ClientResult> { + fn call< + O: OffchainExt, + >( + &self, + id: &BlockId, + method: &str, + call_data: &[u8], + strategy: ExecutionStrategy, + side_effects_handler: Option<&mut O>, + ) -> ClientResult> { match self.backend.is_local_state_available(id) { - true => self.local.call(id, method, call_data, strategy), - false => self.remote.call(id, method, call_data, strategy), + true => self.local.call(id, method, call_data, strategy, side_effects_handler), + false => self.remote.call(id, method, call_data, strategy, side_effects_handler), } } fn contextual_call< + O: OffchainExt, PB: Fn() -> ClientResult, EM: Fn( Result, Self::Error>, @@ -223,16 +245,18 @@ impl CallExecutor for method: &str, call_data: &[u8], changes: &mut OverlayedChanges, - initialised_block: &mut Option>, + initialized_block: &mut Option>, prepare_environment_block: PB, _manager: ExecutionManager, native_call: Option, + side_effects_handler: Option<&mut O>, ) -> ClientResult> where ExecutionManager: Clone { // there's no actual way/need to specify native/wasm execution strategy on light node // => we can safely ignore passed values match self.backend.is_local_state_available(at) { true => CallExecutor::contextual_call::< + _, _, fn( Result, Local::Error>, @@ -246,12 +270,14 @@ impl CallExecutor for method, call_data, changes, - initialised_block, + initialized_block, prepare_environment_block, ExecutionManager::NativeWhenPossible, native_call, + side_effects_handler, ).map_err(|e| ClientErrorKind::Execution(Box::new(e.to_string())).into()), false => CallExecutor::contextual_call::< + _, _, fn( Result, Remote::Error>, @@ -265,10 +291,11 @@ impl CallExecutor for method, call_data, changes, - initialised_block, + initialized_block, prepare_environment_block, ExecutionManager::NativeWhenPossible, native_call, + side_effects_handler, ).map_err(|e| ClientErrorKind::Execution(Box::new(e.to_string())).into()), } } @@ -281,6 +308,7 @@ impl CallExecutor for } fn call_at_state< + O: OffchainExt, S: StateBackend, FF: FnOnce( Result, Self::Error>, @@ -295,11 +323,13 @@ impl CallExecutor for call_data: &[u8], _manager: ExecutionManager, native_call: Option, + side_effects_handler: Option<&mut O>, ) -> ClientResult<(NativeOrEncoded, S::Transaction, Option>)> { // there's no actual way/need to specify native/wasm execution strategy on light node // => we can safely ignore passed values CallExecutor::call_at_state::< + _, _, fn( Result, Remote::Error>, @@ -315,6 +345,7 @@ impl CallExecutor for call_data, ExecutionManager::NativeWhenPossible, native_call, + side_effects_handler, ).map_err(|e| ClientErrorKind::Execution(Box::new(e.to_string())).into()) } @@ -357,7 +388,7 @@ pub fn prove_execution( let (_, init_proof) = executor.prove_at_trie_state( &trie_state, &mut changes, - "Core_initialise_block", + "Core_initialize_block", &header.encode(), )?; @@ -404,7 +435,7 @@ pub fn check_execution_proof( &trie_backend, &mut changes, executor, - "Core_initialise_block", + "Core_initialize_block", &next_block.encode(), )?; @@ -481,16 +512,16 @@ mod tests { } // check method that doesn't requires environment - let (remote, local) = execute(&remote_client, 0, "Core_authorities"); + let (remote, local) = execute(&remote_client, 0, "Core_version"); assert_eq!(remote, local); // check method that requires environment - let (_, block) = execute(&remote_client, 0, "BlockBuilder_finalise_block"); + let (_, block) = execute(&remote_client, 0, "BlockBuilder_finalize_block"); let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); assert_eq!(local_block.number, 1); // check method that requires environment - let (_, block) = execute(&remote_client, 2, "BlockBuilder_finalise_block"); + let (_, block) = execute(&remote_client, 2, "BlockBuilder_finalize_block"); let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); assert_eq!(local_block.number, 3); } @@ -509,7 +540,7 @@ mod tests { let local_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![1]))); let remote_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![2]))); let remote_or_local = RemoteOrLocalCallExecutor::new(backend, remote_executor, local_executor); - assert_eq!(remote_or_local.call(&BlockId::Number(0), "test_method", &[], ExecutionStrategy::NativeElseWasm).unwrap(), vec![1]); - assert_eq!(remote_or_local.call(&BlockId::Number(1), "test_method", &[], ExecutionStrategy::NativeElseWasm).unwrap(), vec![2]); + assert_eq!(remote_or_local.call(&BlockId::Number(0), "test_method", &[], ExecutionStrategy::NativeElseWasm, NeverOffchainExt::new()).unwrap(), vec![1]); + assert_eq!(remote_or_local.call(&BlockId::Number(1), "test_method", &[], ExecutionStrategy::NativeElseWasm, NeverOffchainExt::new()).unwrap(), vec![2]); } } diff --git a/core/client/src/light/fetcher.rs b/core/client/src/light/fetcher.rs index 1c1697eb34867268b4de3aa05aa93a88a56c5380..4cbbc819b31413e33e4bc33c0772ee42d5b6c6ab 100644 --- a/core/client/src/light/fetcher.rs +++ b/core/client/src/light/fetcher.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -282,7 +282,7 @@ impl, F> LightDataChecker ChangesTrieRootsStorage for RootsStorage<'a, Number pub mod tests { use futures::future::{ok, err, FutureResult}; use parking_lot::Mutex; - use keyring::Keyring; + use parity_codec::Decode; use crate::client::tests::prepare_client_with_key_changes; use executor::{self, NativeExecutionDispatch}; use crate::error::Error as ClientError; - use test_client::{self, TestClient, blockchain::HeaderBackend}; - use test_client::runtime::{self, Hash, Block, Header}; + use test_client::{ + self, TestClient, blockchain::HeaderBackend, AccountKeyring, + runtime::{self, Hash, Block, Header} + }; use consensus::BlockOrigin; use crate::in_mem::{Blockchain as InMemoryBlockchain}; @@ -435,7 +437,7 @@ pub mod tests { type TestChecker = LightDataChecker, Blake2Hasher, Block, DummyStorage, OkCallFetcher>; - fn prepare_for_read_proof_check() -> (TestChecker, Header, Vec>, usize) { + fn prepare_for_read_proof_check() -> (TestChecker, Header, Vec>, u32) { // prepare remote client let remote_client = test_client::new(); let remote_block_id = BlockId::Number(0); @@ -444,7 +446,9 @@ pub mod tests { remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap().storage_root(::std::iter::empty()).0.into(); // 'fetch' read proof from remote node - let authorities_len = remote_client.authorities_at(&remote_block_id).unwrap().len(); + let authorities_len = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::AUTHORITY_COUNT.to_vec())) + .unwrap() + .and_then(|v| Decode::decode(&mut &v.0[..])).unwrap(); let remote_read_proof = remote_client.read_proof(&remote_block_id, well_known_keys::AUTHORITY_COUNT).unwrap(); // check remote read proof locally @@ -583,7 +587,7 @@ pub mod tests { // we're testing this test case here: // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); let dave = StorageKey(dave); // 'fetch' changes proof from remote node: @@ -695,7 +699,7 @@ pub mod tests { let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); let local_cht_root = cht::compute_root::( 4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); let dave = StorageKey(dave); // 'fetch' changes proof from remote node: diff --git a/core/client/src/light/mod.rs b/core/client/src/light/mod.rs index f847d22a0e747c928850ae9119bc14b65ee6cef7..2cdcaf49907ac9c8d2abce6843ff0badb48492b0 100644 --- a/core/client/src/light/mod.rs +++ b/core/client/src/light/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/src/notifications.rs b/core/client/src/notifications.rs index dae0ad25995f8013d25dab12042ad6c420c57040..139238f3435e6e3a96a4a7c11dc3bef5adeaa043 100644 --- a/core/client/src/notifications.rs +++ b/core/client/src/notifications.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/src/runtime_api.rs b/core/client/src/runtime_api.rs index 024816246d200769373b79879ae6e2f4e5e59c8c..6bc43ab270f56364966fb87c8574af16ef6894dc 100644 --- a/core/client/src/runtime_api.rs +++ b/core/client/src/runtime_api.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,10 +24,12 @@ pub use state_machine::OverlayedChanges; pub use primitives::NativeOrEncoded; #[doc(hidden)] pub use runtime_primitives::{ - traits::{AuthorityIdFor, Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, ApiRef, RuntimeApiInfo}, - generic::BlockId, transaction_validity::TransactionValidity, ExecutionContext, + traits::{AuthorityIdFor, Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, Header as HeaderT, ApiRef, RuntimeApiInfo}, + generic::BlockId, transaction_validity::TransactionValidity, }; #[doc(hidden)] +pub use primitives::{ExecutionContext, OffchainExt}; +#[doc(hidden)] pub use runtime_version::{ApiId, RuntimeVersion, ApisVec, create_apis_vec}; #[doc(hidden)] pub use rstd::{slice, mem}; @@ -36,7 +38,6 @@ use rstd::result; pub use parity_codec::{Encode, Decode}; #[cfg(feature = "std")] use crate::error; -use rstd::vec::Vec; use sr_api_macros::decl_runtime_apis; use primitives::OpaqueMetadata; #[cfg(feature = "std")] @@ -91,15 +92,18 @@ pub trait ApiExt { pub trait CallRuntimeAt { /// Calls the given api function with the given encoded arguments at the given block /// and returns the encoded result. - fn call_api_at result::Result + UnwindSafe>( + fn call_api_at< + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >( &self, at: &BlockId, function: &'static str, args: Vec, changes: &mut OverlayedChanges, - initialised_block: &mut Option>, + initialized_block: &mut Option>, native_call: Option, - context: ExecutionContext + context: ExecutionContext, ) -> error::Result>; /// Returns the runtime version at the given block. @@ -107,17 +111,15 @@ pub trait CallRuntimeAt { } decl_runtime_apis! { - /// The `Core` api trait that is mandantory for each runtime. + /// The `Core` api trait that is mandatory for each runtime. #[core_trait] pub trait Core { /// Returns the version of the runtime. fn version() -> RuntimeVersion; - /// Returns the authorities. - fn authorities() -> Vec>; /// Execute the given block. fn execute_block(block: Block); - /// Initialise a block with the given header. - fn initialise_block(header: &::Header); + /// Initialize a block with the given header. + fn initialize_block(header: &::Header); } /// The `Metadata` api trait that returns metadata for the runtime. @@ -132,3 +134,4 @@ decl_runtime_apis! { fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity; } } + diff --git a/core/consensus/aura/Cargo.toml b/core/consensus/aura/Cargo.toml index 10c4122c0ea916e10eca1a626bf8f74f93e9b7fb..190ace413de835a34a7a1e71632279799405daaf 100644 --- a/core/consensus/aura/Cargo.toml +++ b/core/consensus/aura/Cargo.toml @@ -6,7 +6,7 @@ description = "Aura consensus algorithm for substrate" edition = "2018" [dependencies] -parity-codec = "3.1" +parity-codec = "3.2" client = { package = "substrate-client", path = "../../client" } primitives = { package = "substrate-primitives", path = "../../primitives" } runtime_support = { package = "srml-support", path = "../../../srml/support" } @@ -25,6 +25,7 @@ parking_lot = "0.7.1" error-chain = "0.12" log = "0.4" consensus_common = { package = "substrate-consensus-common", path = "../common" } +authorities = { package = "substrate-consensus-authorities", path = "../authorities" } [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../keyring" } diff --git a/core/consensus/aura/primitives/Cargo.toml b/core/consensus/aura/primitives/Cargo.toml index d55db6b1eeb30a295ac7d29d9832b5237ae2a159..cc7fbeb3dd31da0a36d0b843e60bd0bdeacacf64 100644 --- a/core/consensus/aura/primitives/Cargo.toml +++ b/core/consensus/aura/primitives/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] substrate-client = { path = "../../../client", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false } [features] default = ["std"] diff --git a/core/consensus/aura/primitives/src/lib.rs b/core/consensus/aura/primitives/src/lib.rs index 27f9a123bc98ce5004061ecef2789d21225d769d..47b6ec7c1417058583eaa6d1f2a93ff42a1569bf 100644 --- a/core/consensus/aura/primitives/src/lib.rs +++ b/core/consensus/aura/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,6 +19,10 @@ #![cfg_attr(not(feature = "std"), no_std)] use substrate_client::decl_runtime_apis; +use runtime_primitives::ConsensusEngineId; + +/// The `ConsensusEngineId` of AuRa. +pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a']; decl_runtime_apis! { /// API necessary for block authorship with aura. diff --git a/core/consensus/aura/slots/Cargo.toml b/core/consensus/aura/slots/Cargo.toml index fce628161eb493fe86ea8f3acb5820275e9e9a6e..3ad763cc181e128d61f5e2c0c652e930183820d5 100644 --- a/core/consensus/aura/slots/Cargo.toml +++ b/core/consensus/aura/slots/Cargo.toml @@ -6,7 +6,7 @@ description = "Generic slots-based utilities for consensus" edition = "2018" [dependencies] -codec = { package = "parity-codec", version = "3.0" } +codec = { package = "parity-codec", version = "3.2" } client = { package = "substrate-client", path = "../../../client" } primitives = { package = "substrate-primitives", path = "../../../primitives" } runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives" } diff --git a/core/consensus/aura/src/lib.rs b/core/consensus/aura/src/lib.rs index 166066d53d6c9aabbbcaa7580d55ee24fba39ece..fd33228b664b59f6549ff4d69258232a98306704 100644 --- a/core/consensus/aura/src/lib.rs +++ b/core/consensus/aura/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -25,24 +25,27 @@ //! //! Blocks from future steps will be either deferred or rejected depending on how //! far in the future they are. +#![deny(deprecated)] +use std::{sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug}; -use std::{sync::Arc, time::Duration, thread}; - -use parity_codec::Encode; -use consensus_common::{ - Authorities, BlockImport, Environment, Proposer, ForkChoiceStrategy +use parity_codec::{Encode, Decode}; +use consensus_common::{self, Authorities, BlockImport, Environment, Proposer, + ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError, }; +use consensus_common::well_known_cache_keys; use consensus_common::import_queue::{Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport}; use client::ChainHead; -use client::block_builder::api::{BlockBuilder as BlockBuilderApi, self as block_builder_api}; +use client::block_builder::api::BlockBuilder as BlockBuilderApi; +use client::blockchain::ProvideCache; use client::runtime_api::ApiExt; -use consensus_common::{ImportBlock, BlockOrigin}; +use aura_primitives::AURA_ENGINE_ID; use runtime_primitives::{generic, generic::BlockId, Justification}; use runtime_primitives::traits::{ - Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi + Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor, }; -use primitives::{Ed25519AuthorityId, ed25519}; +use primitives::Pair; use inherents::{InherentDataProviders, InherentData, RuntimeString}; +use authorities::AuthoritiesApi; use futures::{Stream, Future, IntoFuture, future}; use tokio::timer::Timeout; @@ -60,6 +63,9 @@ pub use aura_slots::SlotDuration; pub use aura_primitives::*; pub use consensus_common::SyncOracle; +type AuthorityId

=

::Public; +type Signature

=

::Signature; + /// A handle to the network. This is generally implemented by providing some /// handle to a gossip service or similar. /// @@ -73,18 +79,21 @@ pub trait Network: Clone { } /// Get slot author for given block along with authorities. -fn slot_author(slot_num: u64, authorities: &[Ed25519AuthorityId]) -> Option { +fn slot_author(slot_num: u64, authorities: &[AuthorityId

]) -> Option> + where P::Public: Clone, +{ if authorities.is_empty() { return None } let idx = slot_num % (authorities.len() as u64); assert!(idx <= usize::max_value() as u64, "It is impossible to have a vector with length beyond the address space; qed"); - let current_author = *authorities.get(idx as usize) + let current_author = authorities.get(idx as usize) .expect("authorities not empty; index constrained to list length;\ - this is a valid index; qed"); + this is a valid index; qed") + .clone(); - Some(current_author) + Some(current_author.clone()) } fn duration_now() -> Option { @@ -106,26 +115,43 @@ fn inherent_to_common_error(err: RuntimeString) -> consensus_common::Error { } /// A digest item which is usable with aura consensus. -pub trait CompatibleDigestItem: Sized { - /// Construct a digest item which is a slot number and a signature on the +pub trait CompatibleDigestItem: Sized { + /// Construct a digest item which contains a slot number and a signature on the /// hash. - fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self; + fn aura_seal(slot_num: u64, signature: Signature) -> Self; /// If this item is an Aura seal, return the slot number and signature. - fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)>; + fn as_aura_seal(&self) -> Option<(u64, Signature)>; + + /// Return `true` if this seal type is deprecated. Otherwise, return + /// `false`. + fn is_deprecated(&self) -> bool; } -impl CompatibleDigestItem for generic::DigestItem { +impl CompatibleDigestItem

for generic::DigestItem + where P: Pair, P::Signature: Clone + Encode + Decode, +{ /// Construct a digest item which is a slot number and a signature on the /// hash. - fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self { - generic::DigestItem::Seal(slot_number, signature) + fn aura_seal(slot_number: u64, signature: Signature

) -> Self { + generic::DigestItem::Consensus(AURA_ENGINE_ID, (slot_number, signature).encode()) } + /// If this item is an Aura seal, return the slot number and signature. - fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)> { + #[allow(deprecated)] + fn as_aura_seal(&self) -> Option<(u64, Signature

)> { match self { - generic::DigestItem::Seal(slot, ref sign) => Some((*slot, sign)), - _ => None + generic::DigestItem::Seal(slot, ref sig) => Some((*slot, (*sig).clone())), + generic::DigestItem::Consensus(AURA_ENGINE_ID, seal) => Decode::decode(&mut &seal[..]), + _ => None, + } + } + + #[allow(deprecated)] + fn is_deprecated(&self) -> bool { + match self { + generic::DigestItem::Seal(_, _) => true, + _ => false, } } } @@ -143,30 +169,41 @@ impl SlotCompatible for AuraSlotCompatible { } /// Start the aura worker in a separate thread. -pub fn start_aura_thread( +pub fn start_aura_thread( slot_duration: SlotDuration, - local_key: Arc, + local_key: Arc

, client: Arc, block_import: Arc, env: Arc, sync_oracle: SO, on_exit: OnExit, inherent_data_providers: InherentDataProviders, + force_authoring: bool, ) -> Result<(), consensus_common::Error> where B: Block + 'static, - C: Authorities + ChainHead + Send + Sync + 'static, + C: ChainHead + ProvideRuntimeApi + ProvideCache + Send + Sync + 'static, + C::Api: AuthoritiesApi, E: Environment + Send + Sync + 'static, E::Proposer: Proposer + Send + 'static, <>::Create as IntoFuture>::Future: Send + 'static, I: BlockImport + Send + Sync + 'static, - Error: From + From + 'static, + Error: From + 'static, + P: Pair + Send + Sync + 'static, + P::Public: Encode + Decode + Eq + Clone + Debug + Hash + Send + Sync + 'static, + P::Signature: Encode, SO: SyncOracle + Send + Sync + Clone + 'static, OnExit: Future + Send + 'static, - DigestItemFor: CompatibleDigestItem + DigestItem + 'static, + DigestItemFor: CompatibleDigestItem

+ DigestItem> + 'static, Error: ::std::error::Error + Send + From<::consensus_common::Error> + 'static, { let worker = AuraWorker { - client: client.clone(), block_import, env, local_key, inherent_data_providers: inherent_data_providers.clone(), sync_oracle: sync_oracle.clone(), + client: client.clone(), + block_import, + env, + local_key, + inherent_data_providers: inherent_data_providers.clone(), + sync_oracle: sync_oracle.clone(), + force_authoring, }; aura_slots::start_slot_worker_thread::<_, _, _, _, AuraSlotCompatible, _>( @@ -180,30 +217,41 @@ pub fn start_aura_thread( } /// Start the aura worker. The returned future should be run in a tokio runtime. -pub fn start_aura( +pub fn start_aura( slot_duration: SlotDuration, - local_key: Arc, + local_key: Arc

, client: Arc, block_import: Arc, env: Arc, sync_oracle: SO, on_exit: OnExit, inherent_data_providers: InherentDataProviders, + force_authoring: bool, ) -> Result, consensus_common::Error> where B: Block, - C: Authorities + ChainHead, + C: ChainHead + ProvideRuntimeApi + ProvideCache, + C::Api: AuthoritiesApi, E: Environment, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, I: BlockImport + Send + Sync + 'static, - Error: From + From, + Error: From, + P: Pair + Send + Sync + 'static, + P::Public: Hash + Eq + Send + Sync + Clone + Debug + Encode + Decode + 'static, + P::Signature: Encode, SO: SyncOracle + Send + Sync + Clone, - DigestItemFor: CompatibleDigestItem + DigestItem, + DigestItemFor: CompatibleDigestItem

+ DigestItem>, Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>, OnExit: Future, { let worker = AuraWorker { - client: client.clone(), block_import, env, local_key, inherent_data_providers: inherent_data_providers.clone(), sync_oracle: sync_oracle.clone(), + client: client.clone(), + block_import, + env, + local_key, + inherent_data_providers: inherent_data_providers.clone(), + sync_oracle: sync_oracle.clone(), + force_authoring, }; aura_slots::start_slot_worker::<_, _, _, _, AuraSlotCompatible, _>( slot_duration, @@ -215,24 +263,29 @@ pub fn start_aura( ) } -struct AuraWorker { +struct AuraWorker { client: Arc, block_import: Arc, env: Arc, - local_key: Arc, + local_key: Arc

, sync_oracle: SO, inherent_data_providers: InherentDataProviders, + force_authoring: bool, } -impl SlotWorker for AuraWorker where - C: Authorities, +impl SlotWorker for AuraWorker where + C: ProvideRuntimeApi + ProvideCache, + C::Api: AuthoritiesApi, E: Environment, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, I: BlockImport + Send + Sync + 'static, - Error: From + From, + P: Pair + Send + Sync + 'static, + P::Public: Hash + Eq + Send + Sync + Clone + Debug + Encode + Decode + 'static, + P::Signature: Encode, + Error: From, SO: SyncOracle + Send + Clone, - DigestItemFor: CompatibleDigestItem + DigestItem, + DigestItemFor: CompatibleDigestItem

+ DigestItem>, Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>, { type OnSlot = Box + Send>; @@ -258,7 +311,7 @@ impl SlotWorker for AuraWorker whe let (timestamp, slot_num, slot_duration) = (slot_info.timestamp, slot_info.number, slot_info.duration); - let authorities = match client.authorities(&BlockId::Hash(chain_head.hash())) { + let authorities = match authorities(client.as_ref(), &BlockId::Hash(chain_head.hash())) { Ok(authorities) => authorities, Err(e) => { warn!( @@ -273,17 +326,17 @@ impl SlotWorker for AuraWorker whe } }; - if self.sync_oracle.is_offline() && authorities.len() > 1 { + if !self.force_authoring && self.sync_oracle.is_offline() && authorities.len() > 1 { debug!(target: "aura", "Skipping proposal slot. Waiting for the network."); telemetry!(CONSENSUS_DEBUG; "aura.skipping_proposal_slot"; "authorities_len" => authorities.len() ); return Box::new(future::ok(())); } - - let proposal_work = match slot_author(slot_num, &authorities) { + let maybe_author = slot_author::

(slot_num, &authorities); + let proposal_work = match maybe_author { None => return Box::new(future::ok(())), - Some(author) => if author.0 == public_key.0 { + Some(author) => if author == public_key { debug!( target: "aura", "Starting authorship at slot {}; timestamp = {}", slot_num, @@ -343,7 +396,7 @@ impl SlotWorker for AuraWorker whe // add it to a digest item. let to_sign = (slot_num, pre_hash).encode(); let signature = pair.sign(&to_sign[..]); - let item = as CompatibleDigestItem>::aura_seal( + let item = as CompatibleDigestItem

>::aura_seal( slot_num, signature, ); @@ -370,7 +423,7 @@ impl SlotWorker for AuraWorker whe "hash_previously" => ?pre_hash ); - if let Err(e) = block_import.import_block(import_block, None) { + if let Err(e) = block_import.import_block(import_block, Default::default()) { warn!(target: "aura", "Error with block built on {:?}: {:?}", parent_hash, e); telemetry!(CONSENSUS_WARN; "aura.err_with_block_built_on"; @@ -387,18 +440,32 @@ impl SlotWorker for AuraWorker whe /// if it's successful, returns the pre-header, the slot number, and the signat. // // FIXME #1018 needs misbehavior types -fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, authorities: &[Ed25519AuthorityId]) - -> Result, String> - where DigestItemFor: CompatibleDigestItem +#[forbid(deprecated)] +fn check_header( + slot_now: u64, + mut header: B::Header, + hash: B::Hash, + authorities: &[AuthorityId

], + allow_old_seals: bool, +) -> Result, String> + where DigestItemFor: CompatibleDigestItem

, + P::Public: Clone + AsRef, + P::Signature: Decode, { let digest_item = match header.digest_mut().pop() { Some(x) => x, None => return Err(format!("Header {:?} is unsealed", hash)), }; - let (slot_num, &sig) = match digest_item.as_aura_seal() { - Some(x) => x, - None => return Err(format!("Header {:?} is unsealed", hash)), - }; + + if !allow_old_seals && digest_item.is_deprecated() { + debug!(target: "aura", "Header {:?} uses old seal format, rejecting", hash); + return Err(format!("Header {:?} uses old seal format, rejecting", hash)) + } + + let (slot_num, sig) = digest_item.as_aura_seal().ok_or_else(|| { + debug!(target: "aura", "Header {:?} is unsealed", hash); + format!("Header {:?} is unsealed", hash) + })?; if slot_num > slot_now { header.digest_mut().push(digest_item); @@ -406,17 +473,16 @@ fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, a } else { // check the signature is valid under the expected authority and // chain state. - - let expected_author = match slot_author(slot_num, &authorities) { + let expected_author = match slot_author::

(slot_num, &authorities) { None => return Err("Slot Author not found".to_string()), Some(author) => author }; let pre_hash = header.hash(); let to_sign = (slot_num, pre_hash).encode(); - let public = ed25519::Public(expected_author.0); + let public = expected_author; - if ed25519::verify_strong(&sig, &to_sign[..], public) { + if P::verify(&sig, &to_sign[..], public) { Ok(CheckedHeader::Checked(header, slot_num, sig)) } else { Err(format!("Bad signature on {:?}", hash)) @@ -438,13 +504,16 @@ pub trait ExtraVerification: Send + Sync { } /// A verifier for Aura blocks. -pub struct AuraVerifier { +pub struct AuraVerifier { client: Arc, extra: E, + phantom: PhantomData

, inherent_data_providers: inherents::InherentDataProviders, + allow_old_seals: bool, } -impl AuraVerifier +impl AuraVerifier + where P: Send + Sync + 'static { fn check_inherents( &self, @@ -493,51 +562,6 @@ impl AuraVerifier Ok(()) } } - - #[allow(deprecated)] - fn old_check_inherents( - &self, - block: B, - block_id: BlockId, - inherent_data: InherentData, - timestamp_now: u64, - ) -> Result<(), String> - where C: ProvideRuntimeApi, C::Api: BlockBuilderApi - { - use block_builder_api::{OldInherentData, OldCheckInherentError}; - const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; - - let (timestamp, slot) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data).map_err(|e| format!("{:?}", e))?; - let inherent_data = OldInherentData::new(timestamp, slot); - - let inherent_res = self.client.runtime_api().check_inherents_before_version_2( - &block_id, - block, - inherent_data, - ).map_err(|e| format!("{:?}", e))?; - - match inherent_res { - Ok(()) => Ok(()), - Err(OldCheckInherentError::ValidAtTimestamp(timestamp)) => { - // halt import until timestamp is valid. - // reject when too far ahead. - if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { - return Err("Rejecting block too far in future".into()); - } - - let diff = timestamp.saturating_sub(timestamp_now); - info!( - target: "aura", - "halting for block {} seconds in the future", - diff - ); - telemetry!(CONSENSUS_INFO; "aura.halting_for_future_block"; "diff" => ?diff); - thread::sleep(Duration::from_secs(diff)); - Ok(()) - }, - Err(OldCheckInherentError::Other(e)) => Err(e.into()) - } - } } /// No-op extra verification. @@ -552,11 +576,16 @@ impl ExtraVerification for NothingExtra { } } -impl Verifier for AuraVerifier where - C: Authorities + ProvideRuntimeApi + Send + Sync, +#[forbid(deprecated)] +impl Verifier for AuraVerifier where + C: ProvideRuntimeApi + Send + Sync, C::Api: BlockBuilderApi, - DigestItemFor: CompatibleDigestItem + DigestItem, + DigestItemFor: CompatibleDigestItem

+ DigestItem>, E: ExtraVerification, + P: Pair + Send + Sync + 'static, + P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + AsRef + 'static, + P::Signature: Encode + Decode, + Self: Authorities, { fn verify( &self, @@ -564,13 +593,13 @@ impl Verifier for AuraVerifier where header: B::Header, justification: Option, mut body: Option>, - ) -> Result<(ImportBlock, Option>), String> { + ) -> Result<(ImportBlock, Option>>), String> { let mut inherent_data = self.inherent_data_providers.create_inherent_data().map_err(String::from)?; let (timestamp_now, slot_now) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data) .map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?; let hash = header.hash(); let parent_hash = *header.parent_hash(); - let authorities = self.client.authorities(&BlockId::Hash(parent_hash)) + let authorities = self.authorities(&BlockId::Hash(parent_hash)) .map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?; let extra_verification = self.extra.verify( @@ -580,7 +609,13 @@ impl Verifier for AuraVerifier where // we add one to allow for some small drift. // FIXME #1019 in the future, alter this queue to allow deferring of headers - let checked_header = check_header::(slot_now + 1, header, hash, &authorities[..])?; + let checked_header = check_header::( + slot_now + 1, + header, + hash, + &authorities[..], + self.allow_old_seals, + )?; match checked_header { CheckedHeader::Checked(pre_header, slot_num, sig) => { let item = >::aura_seal(slot_num, sig); @@ -592,18 +627,12 @@ impl Verifier for AuraVerifier where inherent_data.aura_replace_inherent_data(slot_num); let block = B::new(pre_header.clone(), inner_body); + // skip the inherents verification if the runtime API is old. if self.client .runtime_api() - .has_api_with::, _>(&BlockId::Hash(parent_hash), |v| v < 2) + .has_api_with::, _>(&BlockId::Hash(parent_hash), |v| v >= 2) .map_err(|e| format!("{:?}", e))? { - self.old_check_inherents( - block.clone(), - BlockId::Hash(parent_hash), - inherent_data, - timestamp_now, - )?; - } else { self.check_inherents( block.clone(), BlockId::Hash(parent_hash), @@ -646,6 +675,31 @@ impl Verifier for AuraVerifier where } } +impl Authorities for AuraVerifier where + B: Block, + C: ProvideRuntimeApi + ProvideCache, + C::Api: AuthoritiesApi, +{ + type Error = ConsensusError; + + fn authorities(&self, at: &BlockId) -> Result>, Self::Error> { + authorities(self.client.as_ref(), at) + } +} + +fn authorities(client: &C, at: &BlockId) -> Result>, ConsensusError> where + B: Block, + C: ProvideRuntimeApi + ProvideCache, + C::Api: AuthoritiesApi, +{ + client + .cache() + .and_then(|cache| cache.get_at(&well_known_cache_keys::AUTHORITIES, at) + .and_then(|v| Decode::decode(&mut &v[..]))) + .or_else(|| client.runtime_api().authorities(at).ok()) + .ok_or_else(|| consensus_common::ErrorKind::InvalidAuthoritiesSet.into()) +} + /// The Aura import queue type. pub type AuraImportQueue = BasicQueue; @@ -664,24 +718,34 @@ fn register_aura_inherent_data_provider( } /// Start an import queue for the Aura consensus algorithm. -pub fn import_queue( +pub fn import_queue( slot_duration: SlotDuration, block_import: SharedBlockImport, justification_import: Option>, client: Arc, extra: E, inherent_data_providers: InherentDataProviders, + allow_old_seals: bool, ) -> Result, consensus_common::Error> where B: Block, - C: 'static + Authorities + ProvideRuntimeApi + Send + Sync, - C::Api: BlockBuilderApi, - DigestItemFor: CompatibleDigestItem + DigestItem, + C: 'static + ProvideRuntimeApi + ProvideCache + Send + Sync, + C::Api: BlockBuilderApi + AuthoritiesApi, + DigestItemFor: CompatibleDigestItem

+ DigestItem>, E: 'static + ExtraVerification, + P: Pair + Send + Sync + 'static, + P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode + AsRef, + P::Signature: Encode + Decode, { register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?; let verifier = Arc::new( - AuraVerifier { client: client.clone(), extra, inherent_data_providers } + AuraVerifier { + client: client.clone(), + extra, + inherent_data_providers, + phantom: PhantomData, + allow_old_seals, + } ); Ok(BasicQueue::new(verifier, block_import, justification_import)) } @@ -696,7 +760,8 @@ mod tests { use network::config::ProtocolConfig; use parking_lot::Mutex; use tokio::runtime::current_thread; - use keyring::Keyring; + use keyring::ed25519::Keyring; + use primitives::ed25519; use client::BlockchainEvents; use test_client; @@ -711,7 +776,7 @@ mod tests { type Proposer = DummyProposer; type Error = Error; - fn init(&self, parent_header: &::Header, _authorities: &[Ed25519AuthorityId]) + fn init(&self, parent_header: &::Header, _authorities: &[AuthorityId]) -> Result { Ok(DummyProposer(parent_header.number + 1, self.0.clone())) @@ -737,7 +802,7 @@ mod tests { impl TestNetFactory for AuraTestNet { type Specialization = DummySpecialization; - type Verifier = AuraVerifier; + type Verifier = AuraVerifier; type PeerData = (); /// Create new test network with peers and given config. @@ -764,6 +829,8 @@ mod tests { client, extra: NothingExtra, inherent_data_providers, + phantom: Default::default(), + allow_old_seals: false, }) } @@ -822,7 +889,7 @@ mod tests { &inherent_data_providers, slot_duration.get() ).expect("Registers aura inherent data provider"); - let aura = start_aura( + let aura = start_aura::<_, _, _, _, ed25519::Pair, _, _, _>( slot_duration, Arc::new(key.clone().into()), client.clone(), @@ -831,6 +898,7 @@ mod tests { DummyOracle, futures::empty(), inherent_data_providers, + false, ).expect("Starts aura"); runtime.spawn(aura); @@ -852,4 +920,16 @@ mod tests { runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap(); } + + #[test] + fn authorities_call_works() { + let client = test_client::new(); + + assert_eq!(client.info().unwrap().chain.best_number, 0); + assert_eq!(authorities(&client, &BlockId::Number(0)).unwrap(), vec![ + Keyring::Alice.into(), + Keyring::Bob.into(), + Keyring::Charlie.into() + ]); + } } diff --git a/core/consensus/authorities/Cargo.toml b/core/consensus/authorities/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..0800656f76f6ef3c193d1ea9307a23e89575711e --- /dev/null +++ b/core/consensus/authorities/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "substrate-consensus-authorities" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Primitives for Aura consensus" +edition = "2018" + +[dependencies] +parity-codec = { version = "3.0", default-features = false } +substrate-client = { path = "../../client", default-features = false } +primitives = { package = "substrate-primitives", path = "../../primitives", default-features = false } +runtime_support = { package = "srml-support", path = "../../../srml/support", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives", default-features = false } +sr-version = { path = "../../sr-version", default-features = false } +runtime_io = { package = "sr-io", path = "../../sr-io", default-features = false } +rstd = { package = "sr-std", path = "../../sr-std", default-features = false } + +[features] +default = ["std"] +std = [ + "parity-codec/std", + "substrate-client/std", + "primitives/std", + "runtime_support/std", + "runtime_primitives/std", + "sr-version/std", + "runtime_io/std", + "rstd/std" +] diff --git a/core/consensus/authorities/src/lib.rs b/core/consensus/authorities/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..a5ad974f5b40e833c3677c14e2fa332751c06eb7 --- /dev/null +++ b/core/consensus/authorities/src/lib.rs @@ -0,0 +1,31 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Authorities API. + +#![cfg_attr(not(feature = "std"), no_std)] + +use substrate_client::decl_runtime_apis; +use runtime_primitives::traits::AuthorityIdFor; +use rstd::vec::Vec; + +decl_runtime_apis! { + /// Authorities API. + pub trait AuthoritiesApi { + /// Returns the authorities at the given block. + fn authorities() -> Vec>; + } +} diff --git a/core/consensus/common/Cargo.toml b/core/consensus/common/Cargo.toml index 37184e3c0be7c32a2182d881d1f4d3cf40fe1db0..185d80dadb64e3c971fa8993a5734d4ac9faee64 100644 --- a/core/consensus/common/Cargo.toml +++ b/core/consensus/common/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] crossbeam-channel = "0.3.4" +libp2p = { version = "0.6.0", default-features = false } log = "0.4" primitives = { package = "substrate-primitives", path= "../../primitives" } inherents = { package = "substrate-inherents", path = "../../inherents" } @@ -15,7 +16,7 @@ futures = "0.1" runtime_version = { package = "sr-version", path = "../../sr-version" } runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } tokio = "0.1.7" -parity-codec = "3.1" +parity-codec = "3.2" parity-codec-derive = "3.1" [dev-dependencies] diff --git a/core/consensus/common/src/block_import.rs b/core/consensus/common/src/block_import.rs index 0c2b5330b415d0686ebd06f3c6a584dd271874b0..7debe1acfec7fd89d76e3026cbaf1f8979f76f49 100644 --- a/core/consensus/common/src/block_import.rs +++ b/core/consensus/common/src/block_import.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,9 +16,11 @@ //! Block import helpers. -use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, DigestItemFor, Header as HeaderT, NumberFor}; +use runtime_primitives::traits::{Block as BlockT, DigestItemFor, Header as HeaderT, NumberFor}; use runtime_primitives::Justification; use std::borrow::Cow; +use std::collections::HashMap; +use crate::well_known_cache_keys; /// Block import result. #[derive(Debug, PartialEq, Eq)] @@ -40,6 +42,8 @@ pub struct ImportedAux { pub clear_justification_requests: bool, /// Request a justification for the given block. pub needs_justification: bool, + /// Received a bad justification. + pub bad_justification: bool, } impl Default for ImportedAux { @@ -47,6 +51,7 @@ impl Default for ImportedAux { ImportedAux { clear_justification_requests: false, needs_justification: false, + bad_justification: false, } } } @@ -172,11 +177,13 @@ pub trait BlockImport { parent_hash: B::Hash, ) -> Result; - /// Import a Block alongside the new authorities valid from this block forward + /// Import a block. + /// + /// Cached data can be accessed through the blockchain cache. fn import_block( &self, block: ImportBlock, - new_authorities: Option>>, + cache: HashMap>, ) -> Result; } diff --git a/core/consensus/common/src/error.rs b/core/consensus/common/src/error.rs index 337bbeeea55d8eb700fceb3a2b7cc9be01bd36c6..0f1914087bf8c979441dc907a2694fc80138e305 100644 --- a/core/consensus/common/src/error.rs +++ b/core/consensus/common/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,6 +18,7 @@ use runtime_version::RuntimeVersion; use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, impl_extract_backtrace, impl_error_chain_kind}; +use primitives::ed25519::{Public, Signature}; error_chain! { errors { @@ -52,13 +53,19 @@ error_chain! { } /// Error checking signature - InvalidSignature(s: ::primitives::ed25519::Signature, a: ::primitives::Ed25519AuthorityId) { + InvalidSignature(s: Signature, a: Public) { description("Message signature is invalid"), display("Message signature {:?} by {:?} is invalid.", s, a), } + /// Invalid authorities set received from the runtime. + InvalidAuthoritiesSet { + description("authorities set is invalid"), + display("Current state of blockchain has invalid authorities set"), + } + /// Account is not an authority. - InvalidAuthority(a: ::primitives::Ed25519AuthorityId) { + InvalidAuthority(a: Public) { description("Message sender is not a valid authority"), display("Message sender {:?} is not a valid authority.", a), } diff --git a/core/consensus/common/src/evaluation.rs b/core/consensus/common/src/evaluation.rs index c0fdcc45f1af2f56656af0bceff0efe34dd71fac..48016b1e94c93f0b55e8806d8e28cdcc79e6a6bc 100644 --- a/core/consensus/common/src/evaluation.rs +++ b/core/consensus/common/src/evaluation.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/consensus/common/src/import_queue.rs b/core/consensus/common/src/import_queue.rs index dfacb2292f1b3727595aee69cf0876f507cc9ba3..7a418ae9f444986911db44b5e5b04d57a91827e0 100644 --- a/core/consensus/common/src/import_queue.rs +++ b/core/consensus/common/src/import_queue.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ use crate::block_import::{ BlockImport, BlockOrigin, ImportBlock, ImportedAux, ImportResult, JustificationImport, }; use crossbeam_channel::{self as channel, Receiver, Sender}; +use parity_codec::Encode; use std::sync::Arc; use std::thread; @@ -38,6 +39,7 @@ use runtime_primitives::traits::{ use runtime_primitives::Justification; use crate::error::Error as ConsensusError; +use parity_codec::alloc::collections::hash_map::HashMap; /// Shared block import struct used by the queue. pub type SharedBlockImport = Arc + Send + Sync>; @@ -46,7 +48,7 @@ pub type SharedBlockImport = Arc + pub type SharedJustificationImport = Arc + Send + Sync>; /// Maps to the Origin used by the network. -pub type Origin = usize; +pub type Origin = libp2p::PeerId; /// Block data used by the queue. #[derive(Debug, PartialEq, Eq, Clone)] @@ -179,7 +181,7 @@ impl ImportQueue for BasicQueue { fn import_justification(&self, who: Origin, hash: B::Hash, number: NumberFor, justification: Justification) { let _ = self .sender - .send(BlockImportMsg::ImportJustification(who, hash, number, justification)) + .send(BlockImportMsg::ImportJustification(who.clone(), hash, number, justification)) .expect("1. self is holding a sender to the Importer, 2. Importer should handle messages while there are senders around; qed"); } } @@ -309,7 +311,7 @@ impl BlockImporter { match result { Ok(BlockImportResult::ImportedKnown(number)) => link.block_imported(&hash, number), - Ok(BlockImportResult::ImportedUnknown(number, aux)) => { + Ok(BlockImportResult::ImportedUnknown(number, aux, who)) => { link.block_imported(&hash, number); if aux.clear_justification_requests { @@ -321,6 +323,12 @@ impl BlockImporter { trace!(target: "sync", "Block imported but requires justification {}: {:?}", number, hash); link.request_justification(&hash, number); } + + if aux.bad_justification { + if let Some(peer) = who { + link.useless_peer(peer, "Sent block with bad justification to import"); + } + } }, Err(BlockImportError::IncompleteHeader(who)) => { if let Some(peer) = who { @@ -352,17 +360,18 @@ impl BlockImporter { let success = self.justification_import.as_ref().map(|justification_import| { justification_import.import_justification(hash, number, justification) .map_err(|e| { - debug!("Justification import failed with {:?} for hash: {:?} number: {:?} coming from node: {:?}", e, hash, number, who); + debug!(target: "sync", "Justification import failed with {:?} for hash: {:?} number: {:?} coming from node: {:?}", e, hash, number, who); e }).is_ok() }).unwrap_or(false); + if let Some(link) = self.link.as_ref() { link.justification_imported(who, &hash, number, success); } } fn handle_import_blocks(&mut self, origin: BlockOrigin, blocks: Vec>) { - trace!(target:"sync", "Scheduling {} blocks for import", blocks.len()); + trace!(target: "sync", "Scheduling {} blocks for import", blocks.len()); self.worker_sender .send(BlockImportWorkerMsg::ImportBlocks(origin, blocks)) .expect("1. This is holding a sender to the worker, 2. the worker should not quit while a sender is still held; qed"); @@ -417,7 +426,7 @@ impl> BlockImportWorker { _ => Default::default(), }; - trace!(target:"sync", "Starting import of {} blocks {}", count, blocks_range); + trace!(target: "sync", "Starting import of {} blocks {}", count, blocks_range); let mut results = vec![]; @@ -428,12 +437,12 @@ impl> BlockImportWorker { let import_result = if has_error { Err(BlockImportError::Error) } else { - import_single_block( - &*self.block_import, - origin.clone(), - block.clone(), - self.verifier.clone(), - ) + import_single_block( + &*self.block_import, + origin.clone(), + block.clone(), + self.verifier.clone(), + ) }; let was_ok = import_result.is_ok(); results.push((import_result, block.hash)); @@ -479,7 +488,7 @@ pub enum BlockImportResult { /// Imported known block. ImportedKnown(N), /// Imported unknown block. - ImportedUnknown(N, ImportedAux), + ImportedUnknown(N, ImportedAux, Option), } /// Block import error. @@ -509,7 +518,7 @@ pub fn import_single_block>( let (header, justification) = match (block.header, block.justification) { (Some(header), justification) => (header, justification), (None, _) => { - if let Some(peer) = peer { + if let Some(ref peer) = peer { debug!(target: "sync", "Header {} was not provided by {} ", block.hash, peer); } else { debug!(target: "sync", "Header {} was not provided ", block.hash); @@ -528,14 +537,14 @@ pub fn import_single_block>( trace!(target: "sync", "Block already in chain {}: {:?}", number, hash); Ok(BlockImportResult::ImportedKnown(number)) }, - Ok(ImportResult::Imported(aux)) => Ok(BlockImportResult::ImportedUnknown(number, aux)), + Ok(ImportResult::Imported(aux)) => Ok(BlockImportResult::ImportedUnknown(number, aux, peer.clone())), Ok(ImportResult::UnknownParent) => { debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent); Err(BlockImportError::UnknownParent) }, Ok(ImportResult::KnownBad) => { debug!(target: "sync", "Peer gave us a bad block {}: {:?}", number, hash); - Err(BlockImportError::BadBlock(peer)) + Err(BlockImportError::BadBlock(peer.clone())) }, Err(e) => { debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e); @@ -551,20 +560,26 @@ pub fn import_single_block>( let (import_block, new_authorities) = verifier.verify(block_origin, header, justification, block.body) .map_err(|msg| { - if let Some(peer) = peer { + if let Some(ref peer) = peer { trace!(target: "sync", "Verifying {}({}) from {} failed: {}", number, hash, peer, msg); } else { trace!(target: "sync", "Verifying {}({}) failed: {}", number, hash, msg); } - BlockImportError::VerificationFailed(peer, msg) + BlockImportError::VerificationFailed(peer.clone(), msg) })?; - import_error(import_handle.import_block(import_block, new_authorities)) + let mut cache = HashMap::new(); + if let Some(authorities) = new_authorities { + cache.insert(crate::well_known_cache_keys::AUTHORITIES, authorities.encode()); + } + + import_error(import_handle.import_block(import_block, cache)) } #[cfg(test)] mod tests { use super::*; + use libp2p::PeerId; use test_client::runtime::{Block, Hash}; #[derive(Debug, PartialEq)] @@ -627,12 +642,21 @@ mod tests { assert_eq!(link_port.recv(), Ok(LinkMsg::BlockImported)); // Send an unknown - let results = vec![(Ok(BlockImportResult::ImportedUnknown(Default::default(), Default::default())), Default::default())]; + let results = vec![(Ok(BlockImportResult::ImportedUnknown(Default::default(), Default::default(), None)), Default::default())]; let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); assert_eq!(link_port.recv(), Ok(LinkMsg::BlockImported)); + // Send an unknown with peer and bad justification + let peer_id = PeerId::random(); + let results = vec![(Ok(BlockImportResult::ImportedUnknown(Default::default(), + ImportedAux { needs_justification: true, clear_justification_requests: false, bad_justification: true }, + Some(peer_id.clone()))), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::BlockImported)); + assert_eq!(link_port.recv(), Ok(LinkMsg::Disconnected)); + // Send an incomplete header - let results = vec![(Err(BlockImportError::IncompleteHeader(Some(Default::default()))), Default::default())]; + let results = vec![(Err(BlockImportError::IncompleteHeader(Some(peer_id.clone()))), Default::default())]; let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); assert_eq!(link_port.recv(), Ok(LinkMsg::Disconnected)); assert_eq!(link_port.recv(), Ok(LinkMsg::Restarted)); @@ -643,7 +667,7 @@ mod tests { assert_eq!(link_port.recv(), Ok(LinkMsg::Restarted)); // Send a verification failed - let results = vec![(Err(BlockImportError::VerificationFailed(Some(0), String::new())), Default::default())]; + let results = vec![(Err(BlockImportError::VerificationFailed(Some(peer_id.clone()), String::new())), Default::default())]; let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); assert_eq!(link_port.recv(), Ok(LinkMsg::Disconnected)); assert_eq!(link_port.recv(), Ok(LinkMsg::Restarted)); diff --git a/core/consensus/common/src/lib.rs b/core/consensus/common/src/lib.rs index fb777b837a6a6b5ba0ccf87ea36d3fc1cf12b2f5..134a34454edf1f57a348afa949b16a67ede7d5ba 100644 --- a/core/consensus/common/src/lib.rs +++ b/core/consensus/common/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate Consensus Common. // Substrate Demo is free software: you can redistribute it and/or modify @@ -53,7 +53,9 @@ pub use block_import::{ /// Trait for getting the authorities at a given block. pub trait Authorities { - type Error: ::std::error::Error + Send + 'static; /// Get the authorities at the given block. + type Error: std::error::Error + Send + 'static; + + /// Get the authorities at the given block. fn authorities(&self, at: &BlockId) -> Result>, Self::Error>; } @@ -115,3 +117,12 @@ impl SyncOracle for Arc { T::is_offline(&*self) } } + +/// A list of all well known keys in the cache. +pub mod well_known_cache_keys { + /// The type representing cache keys. + pub type Id = [u8; 4]; + + /// A list of authorities. + pub const AUTHORITIES: Id = *b"auth"; +} diff --git a/core/consensus/common/src/offline_tracker.rs b/core/consensus/common/src/offline_tracker.rs index 1ed923da2c590e64ce1b54f63f76801bfaaa3cb0..3c6755d9411d7230bc2aaaa575737a208a13953d 100644 --- a/core/consensus/common/src/offline_tracker.rs +++ b/core/consensus/common/src/offline_tracker.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -112,25 +112,25 @@ impl OfflineTracker { #[cfg(test)] mod tests { use super::*; - use primitives::Ed25519AuthorityId; + use primitives::ed25519::Public as AuthorityId; #[test] fn validator_offline() { - let mut tracker = OfflineTracker::::new(); - let v = [0; 32].into(); - let v2 = [1; 32].into(); - let v3 = [2; 32].into(); - tracker.note_round_end(v, true); - tracker.note_round_end(v2, true); - tracker.note_round_end(v3, true); + let mut tracker = OfflineTracker::::new(); + let v = AuthorityId::from_raw([0; 32]); + let v2 = AuthorityId::from_raw([1; 32]); + let v3 = AuthorityId::from_raw([2; 32]); + tracker.note_round_end(v.clone(), true); + tracker.note_round_end(v2.clone(), true); + tracker.note_round_end(v3.clone(), true); let slash_time = REPORT_TIME + Duration::from_secs(5); tracker.observed.get_mut(&v).unwrap().offline_since -= slash_time; tracker.observed.get_mut(&v2).unwrap().offline_since -= slash_time; - assert_eq!(tracker.reports(&[v, v2, v3]), vec![0, 1]); + assert_eq!(tracker.reports(&[v.clone(), v2.clone(), v3.clone()]), vec![0, 1]); - tracker.note_new_block(&[v, v3]); + tracker.note_new_block(&[v.clone(), v3.clone()]); assert_eq!(tracker.reports(&[v, v2, v3]), vec![0]); } } diff --git a/core/consensus/rhd/Cargo.toml b/core/consensus/rhd/Cargo.toml index 22d847e80ed12d142ecbfac85beadcff06920069..71b45cf41b6749f419a9b9d9093fbee2b93b412d 100644 --- a/core/consensus/rhd/Cargo.toml +++ b/core/consensus/rhd/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] futures = "0.1.17" -codec = { package = "parity-codec", version = "3.1", features = ["derive"] } +codec = { package = "parity-codec", version = "3.2", features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../primitives" } consensus = { package = "substrate-consensus-common", path = "../common" } client = { package = "substrate-client", path = "../../client" } diff --git a/core/consensus/rhd/src/error.rs b/core/consensus/rhd/src/error.rs index 7a97bbcace83741939813b1620aa2db3d42a3ffc..38081109754555b73c02c48f2c51bb1404425cf7 100644 --- a/core/consensus/rhd/src/error.rs +++ b/core/consensus/rhd/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/consensus/rhd/src/lib.rs b/core/consensus/rhd/src/lib.rs index a2a06fec901cd4c05f5076196e257a048a807a05..cbdf95d987578ff5a574d6cdbaefe4bcbd7c199b 100644 --- a/core/consensus/rhd/src/lib.rs +++ b/core/consensus/rhd/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -66,7 +66,7 @@ pub use rhododendron::{ }; pub use self::error::{Error, ErrorKind}; -// pub mod misbehaviour_check; +// pub mod misbehavior_check; mod error; mod service; @@ -762,7 +762,7 @@ fn check_justification_signed_message( let auth_id = sig.signer.clone().into(); if !authorities.contains(&auth_id) { return None } - if ed25519::verify_strong(&sig.signature, message, &sig.signer) { + if ed25519::Pair::verify(&sig.signature, message, &sig.signer) { Some(sig.signer.0) } else { None @@ -838,7 +838,7 @@ pub fn check_vote( fn check_action(action: Action, parent_hash: &B::Hash, sig: &LocalizedSignature) -> Result<(), Error> { let message = localized_encode(*parent_hash, action); - if ed25519::verify_strong(&sig.signature, &message, &sig.signer) { + if ed25519::Pair::verify(&sig.signature, &message, &sig.signer) { Ok(()) } else { Err(CommonErrorKind::InvalidSignature(sig.signature.into(), sig.signer.clone().into()).into()) @@ -1315,7 +1315,7 @@ mod tests { use runtime_primitives::testing::{Block as GenericTestBlock, Header as TestHeader}; use primitives::H256; - use self::keyring::Keyring; + use keyring::AuthorityKeyring; type TestBlock = GenericTestBlock<()>; @@ -1420,7 +1420,7 @@ mod tests { start_round: 0, })), round_timeout_multiplier: 10, - key: Arc::new(Keyring::One.into()), + key: Arc::new(AuthorityKeyring::One.into()), factory: DummyFactory } } @@ -1446,10 +1446,10 @@ mod tests { fn future_gets_preempted() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; @@ -1493,17 +1493,17 @@ mod tests { let hash = [0xff; 32].into(); let authorities = vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let authorities_keys = vec![ - Keyring::One.into(), - Keyring::Two.into(), - Keyring::Alice.into(), - Keyring::Eve.into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { @@ -1554,8 +1554,8 @@ mod tests { let parent_hash = Default::default(); let authorities = vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let block = TestBlock { @@ -1563,7 +1563,7 @@ mod tests { extrinsics: Default::default() }; - let proposal = sign_message(rhododendron::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);; + let proposal = sign_message(rhododendron::Message::Propose(1, block.clone()), &AuthorityKeyring::Alice.pair(), parent_hash);; if let rhododendron::LocalizedMessage::Propose(proposal) = proposal { assert!(check_proposal(&authorities, &parent_hash, &proposal).is_ok()); let mut invalid_round = proposal.clone(); @@ -1577,7 +1577,7 @@ mod tests { } // Not an authority - let proposal = sign_message::(rhododendron::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);; + let proposal = sign_message::(rhododendron::Message::Propose(1, block), &AuthorityKeyring::Bob.pair(), parent_hash);; if let rhododendron::LocalizedMessage::Propose(proposal) = proposal { assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err()); } else { @@ -1591,8 +1591,8 @@ mod tests { let hash: H256 = [0xff; 32].into(); let authorities = vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let vote = sign_message::(rhododendron::Message::Vote(rhododendron::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);; @@ -1618,10 +1618,10 @@ mod tests { fn drop_bft_future_does_not_deadlock() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; @@ -1643,10 +1643,10 @@ mod tests { fn bft_can_build_though_skipped() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; diff --git a/core/consensus/rhd/src/misbehaviour_check.rs b/core/consensus/rhd/src/misbehaviour_check.rs index be8e25ccc9e2984bdc51323e25c095a51ccc139e..58b36542f692bfe16dda219a1d5fd53cb83bf160 100644 --- a/core/consensus/rhd/src/misbehaviour_check.rs +++ b/core/consensus/rhd/src/misbehaviour_check.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -74,8 +74,7 @@ pub fn evaluate_misbehavior( mod tests { use super::*; - use keyring::ed25519; - use keyring::Keyring; + use keyring::AuthorityKeyring; use rhododendron; use runtime_primitives::testing::{H256, Block as RawBlock}; @@ -110,7 +109,7 @@ mod tests { #[test] fn evaluates_double_prepare() { - let key: ed25519::Pair = Keyring::One.into(); + let key = AuthorityKeyring::One.pair(); let parent_hash = [0xff; 32].into(); let hash_1 = [0; 32].into(); let hash_2 = [1; 32].into(); @@ -127,7 +126,7 @@ mod tests { // same signature twice is not misbehavior. let signed = sign_prepare(&key, 1, hash_1, parent_hash); - assert!(evaluate_misbehavior::( + assert!(!evaluate_misbehavior::( &key.public().into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( @@ -135,23 +134,23 @@ mod tests { signed, signed, ) - ) == false); + )); // misbehavior has wrong target. - assert!(evaluate_misbehavior::( - &Keyring::Two.to_raw_public().into(), + assert!(!evaluate_misbehavior::( + &AuthorityKeyring::Two.into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( 1, sign_prepare(&key, 1, hash_1, parent_hash), sign_prepare(&key, 1, hash_2, parent_hash), ) - ) == false); + )); } #[test] fn evaluates_double_commit() { - let key: ed25519::Pair = Keyring::One.into(); + let key = AuthorityKeyring::One.pair(); let parent_hash = [0xff; 32].into(); let hash_1 = [0; 32].into(); let hash_2 = [1; 32].into(); @@ -168,7 +167,7 @@ mod tests { // same signature twice is not misbehavior. let signed = sign_commit(&key, 1, hash_1, parent_hash); - assert!(evaluate_misbehavior::( + assert!(!evaluate_misbehavior::( &key.public().into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( @@ -176,17 +175,17 @@ mod tests { signed, signed, ) - ) == false); + )); // misbehavior has wrong target. - assert!(evaluate_misbehavior::( - &Keyring::Two.to_raw_public().into(), + assert!(!evaluate_misbehavior::( + &AuthorityKeyring::Two.into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( 1, sign_commit(&key, 1, hash_1, parent_hash), sign_commit(&key, 1, hash_2, parent_hash), ) - ) == false); + )); } } diff --git a/core/consensus/rhd/src/service.rs b/core/consensus/rhd/src/service.rs index 34efc942d4dae2a4e77b58d023ea5405be30e0e9..e2858f767a8c08d3977803a68ce6bab46188cb60 100644 --- a/core/consensus/rhd/src/service.rs +++ b/core/consensus/rhd/src/service.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/executor/Cargo.toml b/core/executor/Cargo.toml index 836386d77d807833dc77f58d9c24ad97eb49578f..f34bfbbe916414b58b3a1a81cc0e3c143559d9d0 100644 --- a/core/executor/Cargo.toml +++ b/core/executor/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] error-chain = "0.12" -parity-codec = "3.1" +parity-codec = "3.2" runtime_io = { package = "sr-io", path = "../sr-io" } primitives = { package = "substrate-primitives", path = "../primitives" } trie = { package = "substrate-trie", path = "../trie" } diff --git a/core/executor/src/error.rs b/core/executor/src/error.rs index 98993519f4399ddfecd3e0caef5b1304ab41d732..b27ccf01bf4cef520c3e22d0d9ce8923f7456f5c 100644 --- a/core/executor/src/error.rs +++ b/core/executor/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/executor/src/lib.rs b/core/executor/src/lib.rs index 774850d5d1bda0c37a6259069d9e07c28b90b025..fa7cc71eea6d6273866f9ac53244cf548629c6cf 100644 --- a/core/executor/src/lib.rs +++ b/core/executor/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/executor/src/native_executor.rs b/core/executor/src/native_executor.rs index 4ee58e4493d7a986a329ed8b206487a436f273c4..0944cbdbbdd608007486921673533100641fa4a0 100644 --- a/core/executor/src/native_executor.rs +++ b/core/executor/src/native_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/executor/src/sandbox.rs b/core/executor/src/sandbox.rs index aa7ecac7128ddec1bb318a88717b064c98bfd827..cc21d762bec11fd13645a5a971640e5ddedd155b 100644 --- a/core/executor/src/sandbox.rs +++ b/core/executor/src/sandbox.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/executor/src/wasm_executor.rs b/core/executor/src/wasm_executor.rs index 200403873f28e2eb9202e4e3efe02ceff084f820..42af29e9bae033b3210f987403fcde2cf6d51ffe 100644 --- a/core/executor/src/wasm_executor.rs +++ b/core/executor/src/wasm_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,12 +23,12 @@ use secp256k1; use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, }; -use wasmi::RuntimeValue::{I32, I64}; +use wasmi::RuntimeValue::{I32, I64, self}; use wasmi::memory_units::{Pages}; use state_machine::Externalities; use crate::error::{Error, ErrorKind, Result}; use crate::wasm_utils::UserError; -use primitives::{blake2_256, twox_128, twox_256, ed25519, sr25519}; +use primitives::{blake2_256, twox_128, twox_256, ed25519, sr25519, Pair}; use primitives::hexdisplay::HexDisplay; use primitives::sandbox as sandbox_primitives; use primitives::{H256, Blake2Hasher}; @@ -393,10 +393,12 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, .map_err(|_| UserError("Invalid attempt to get parent_hash in ext_storage_changes_root"))?; parent_hash.as_mut().copy_from_slice(&raw_parent_hash[..]); let r = this.ext.storage_changes_root(parent_hash, parent_number); - if let Some(ref r) = r { + if let Some(r) = r { this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_changes_root"))?; + Ok(1) + } else { + Ok(0) } - Ok(if r.is_some() { 1u32 } else { 0u32 }) }, ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8) => { let values = (0..lens_len) @@ -474,7 +476,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?; let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?; - Ok(if ed25519::verify(&sig, &msg, &pubkey) { + Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) { 0 } else { 5 @@ -487,7 +489,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_sr25519_verify"))?; let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_sr25519_verify"))?; - Ok(if sr25519::verify(&sig, &msg, &pubkey) { + Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) { 0 } else { 5 @@ -518,6 +520,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(0) }, + ext_submit_extrinsic(msg_data: *const u8, len: u32) => { + let extrinsic = this.memory.get(msg_data, len as usize) + .map_err(|_| UserError("OOB while ext_submit_extrinsic: wasm"))?; + + this.ext.submit_extrinsic(extrinsic) + .map_err(|_| UserError("Calling unavailable API ext_submit_extrinsic: wasm"))?; + + Ok(()) + }, ext_sandbox_instantiate( dispatch_thunk_idx: usize, wasm_ptr: *const u8, @@ -637,17 +648,19 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, /// /// Executes the provided code in a sandboxed wasm runtime. #[derive(Debug, Clone)] -pub struct WasmExecutor { -} +pub struct WasmExecutor; impl WasmExecutor { /// Create a new instance. pub fn new() -> Self { - WasmExecutor{} + WasmExecutor } /// Call a given method in the given code. + /// + /// Signature of this method needs to be `(I32, I32) -> I64`. + /// /// This should be used for tests only. pub fn call>( &self, @@ -656,12 +669,34 @@ impl WasmExecutor { code: &[u8], method: &str, data: &[u8], - ) -> Result> { + ) -> Result> { let module = ::wasmi::Module::from_buffer(code)?; let module = self.prepare_module(ext, heap_pages, &module)?; self.call_in_wasm_module(ext, &module, method, data) } + /// Call a given method with a custom signature in the given code. + /// + /// This should be used for tests only. + pub fn call_with_custom_signature< + E: Externalities, + F: FnOnce(&mut FnMut(&[u8]) -> Result) -> Result>, + FR: FnOnce(Option, &MemoryRef) -> Result>, + R, + >( + &self, + ext: &mut E, + heap_pages: usize, + code: &[u8], + method: &str, + create_parameters: F, + filter_result: FR, + ) -> Result { + let module = wasmi::Module::from_buffer(code)?; + let module = self.prepare_module(ext, heap_pages, &module)?; + self.call_in_wasm_module_with_custom_signature(ext, &module, method, create_parameters, filter_result) + } + fn get_mem_instance(module: &ModuleRef) -> Result { Ok(module .export_by_name("memory") @@ -679,6 +714,40 @@ impl WasmExecutor { method: &str, data: &[u8], ) -> Result> { + self.call_in_wasm_module_with_custom_signature( + ext, + module_instance, + method, + |alloc| { + let offset = alloc(data)?; + Ok(vec![I32(offset as i32), I32(data.len() as i32)]) + }, + |res, memory| { + if let Some(I64(r)) = res { + let offset = r as u32; + let length = (r as u64 >> 32) as usize; + memory.get(offset, length).map_err(|_| ErrorKind::Runtime.into()).map(Some) + } else { + Ok(None) + } + } + ) + } + + /// Call a given method in the given wasm-module runtime. + fn call_in_wasm_module_with_custom_signature< + E: Externalities, + F: FnOnce(&mut FnMut(&[u8]) -> Result) -> Result>, + FR: FnOnce(Option, &MemoryRef) -> Result>, + R, + >( + &self, + ext: &mut E, + module_instance: &ModuleRef, + method: &str, + create_parameters: F, + filter_result: FR, + ) -> Result { // extract a reference to a linear memory, optional reference to a table // and then initialize FunctionExecutor. let memory = Self::get_mem_instance(module_instance)?; @@ -689,26 +758,22 @@ impl WasmExecutor { let low = memory.lowest_used(); let used_mem = memory.used_size(); let mut fec = FunctionExecutor::new(memory.clone(), table, ext)?; - let size = data.len() as u32; - let offset = fec.heap.allocate(size).map_err(|_| ErrorKind::Runtime)?; - memory.set(offset, &data)?; + let parameters = create_parameters(&mut |data: &[u8]| { + let offset = fec.heap.allocate(data.len() as u32).map_err(|_| ErrorKind::Runtime)?; + memory.set(offset, &data)?; + Ok(offset) + })?; let result = module_instance.invoke_export( method, - &[ - I32(offset as i32), - I32(size as i32) - ], + ¶meters, &mut fec ); let result = match result { - Ok(Some(I64(r))) => { - let offset = r as u32; - let length = (r >> 32) as u32 as usize; - memory.get(offset, length) - .map_err(|_| ErrorKind::Runtime.into()) + Ok(val) => match filter_result(val, &memory)? { + Some(val) => Ok(val), + None => Err(ErrorKind::InvalidReturn.into()), }, - Ok(_) => Err(ErrorKind::InvalidReturn.into()), Err(e) => { trace!(target: "wasm-executor", "Failed to execute code with {} pages", memory.current_size().0); Err(e.into()) @@ -738,7 +803,7 @@ impl WasmExecutor { module, &ImportsBuilder::new() .with_resolver("env", FunctionExecutor::::resolver()) - )?; + )?; // extract a reference to a linear memory, optional reference to a table // and then initialize FunctionExecutor. @@ -759,7 +824,9 @@ impl WasmExecutor { #[cfg(test)] mod tests { use super::*; + use parity_codec::Encode; + use state_machine::TestExternalities; use hex_literal::{hex, hex_impl}; use primitives::map; @@ -875,7 +942,7 @@ mod tests { fn ed25519_verify_should_work() { let mut ext = TestExternalities::::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let key = ed25519::Pair::from_seed(&blake2_256(b"test")); + let key = ed25519::Pair::from_seed(blake2_256(b"test")); let sig = key.sign(b"all ok!"); let mut calldata = vec![]; calldata.extend_from_slice(key.public().as_ref()); @@ -901,7 +968,7 @@ mod tests { fn sr25519_verify_should_work() { let mut ext = TestExternalities::::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let key = sr25519::Pair::from_seed(&blake2_256(b"test")); + let key = sr25519::Pair::from_seed(blake2_256(b"test")); let sig = key.sign(b"all ok!"); let mut calldata = vec![]; calldata.extend_from_slice(key.public().as_ref()); diff --git a/core/executor/src/wasm_utils.rs b/core/executor/src/wasm_utils.rs index 310240651481dee41489670c89c43fdbf85b315c..4ad9541dbd0d99baa3831c86b4f92c641bb933df 100644 --- a/core/executor/src/wasm_utils.rs +++ b/core/executor/src/wasm_utils.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/executor/wasm/Cargo.lock b/core/executor/wasm/Cargo.lock index 27c80a723e87954785d80eb5f0dbae28ff7006f2..d7ff3a8d2350ae1d7e7cdfb5e49951cf2c30b84b 100644 --- a/core/executor/wasm/Cargo.lock +++ b/core/executor/wasm/Cargo.lock @@ -28,12 +28,12 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -44,7 +44,7 @@ name = "impl-codec" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -54,7 +54,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "parity-codec" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -150,8 +150,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "sr-io" version = "0.1.0" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -161,7 +161,7 @@ dependencies = [ name = "sr-sandbox" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -184,12 +184,11 @@ name = "substrate-primitives" version = "0.1.0" dependencies = [ "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", ] @@ -231,11 +230,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" -"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" -"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07463834729d0ce8d475e7dd6d302e407093ad9a9c02d77eb07fb74b5373829d" +"checksum hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1224388a21c88a80ae7087a2a245ca6d80acc97a9186b75789fb3eeefd0609af" "checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67a4d27831e31e27f1454d6e3d3bb34bcac6bf7ad7032eed0ad0070dc8cf55c1" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" "checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" "checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" "checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" diff --git a/core/finality-grandpa/Cargo.toml b/core/finality-grandpa/Cargo.toml index c84e798fe739206a0775bc1d5896c7a49cb21569..070b073b99774ab0c4755e5c98de6890c5f23586 100644 --- a/core/finality-grandpa/Cargo.toml +++ b/core/finality-grandpa/Cargo.toml @@ -11,7 +11,7 @@ log = "0.4" parking_lot = "0.7.1" tokio = "0.1.7" rand = "0.6" -parity-codec = { version = "3.1", features = ["derive"] } +parity-codec = { version = "3.2", features = ["derive"] } runtime_primitives = { package = "sr-primitives", path = "../sr-primitives" } consensus_common = { package = "substrate-consensus-common", path = "../consensus/common" } substrate-primitives = { path = "../primitives" } diff --git a/core/finality-grandpa/primitives/Cargo.toml b/core/finality-grandpa/primitives/Cargo.toml index 3891db8f018a0b9915a51f17cc8a362c240fe539..a0bd36eb9a43df5e292a0f4bf42dba177cfa3580 100644 --- a/core/finality-grandpa/primitives/Cargo.toml +++ b/core/finality-grandpa/primitives/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] client = { package = "substrate-client", path = "../../client", default-features = false } substrate-primitives = { path = "../../primitives", default-features = false } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } sr-primitives = { path = "../../sr-primitives", default-features = false } rstd = { package = "sr-std", path = "../../sr-std", default-features = false } diff --git a/core/finality-grandpa/primitives/src/lib.rs b/core/finality-grandpa/primitives/src/lib.rs index 1069647f69ca07a487b67fd76a9f94bb68706919..7016a708bd62b8c0f1bc05726d193dd2dc986d1e 100644 --- a/core/finality-grandpa/primitives/src/lib.rs +++ b/core/finality-grandpa/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,17 +23,19 @@ extern crate alloc; use parity_codec::{Encode, Decode}; -use substrate_primitives::Ed25519AuthorityId; +use substrate_primitives::ed25519; use sr_primitives::traits::{DigestFor, NumberFor}; use client::decl_runtime_apis; use rstd::vec::Vec; +use ed25519::Public as AuthorityId; + /// A scheduled change of authority set. #[cfg_attr(feature = "std", derive(Debug, PartialEq))] #[derive(Clone, Encode, Decode)] pub struct ScheduledChange { /// The new authorities after the change, along with their respective weights. - pub next_authorities: Vec<(Ed25519AuthorityId, u64)>, + pub next_authorities: Vec<(AuthorityId, u64)>, /// The number of blocks to delay. pub delay: N, } @@ -56,8 +58,8 @@ decl_runtime_apis! { /// This should be implemented on the runtime side. /// /// This is primarily used for negotiating authority-set changes for the - /// gadget. GRANDPA uses a signalling model of changing authority sets: - /// changes should be signalled with a delay of N blocks, and then automatically + /// gadget. GRANDPA uses a signaling model of changing authority sets: + /// changes should be signaled with a delay of N blocks, and then automatically /// applied in the runtime after those N blocks have passed. /// /// The consensus protocol will coordinate the handoff externally. @@ -81,7 +83,7 @@ decl_runtime_apis! { /// Check a digest for forced changes. /// Return `None` if there are no forced changes. Otherwise, return a /// tuple containing the pending change and the median last finalized - /// block number at the time the change was signalled. + /// block number at the time the change was signaled. /// /// Added in version 2. /// @@ -106,6 +108,6 @@ decl_runtime_apis! { /// When called at block B, it will return the set of authorities that should be /// used to finalize descendants of this block (B+1, B+2, ...). The block B itself /// is finalized by the authorities from block B-1. - fn grandpa_authorities() -> Vec<(Ed25519AuthorityId, u64)>; + fn grandpa_authorities() -> Vec<(AuthorityId, u64)>; } } diff --git a/core/finality-grandpa/src/authorities.rs b/core/finality-grandpa/src/authorities.rs index bb4992ef1d74ecbb2f4640fdff0dda71050cd620..ffded9a1ab3555eb124911e8f67a48f224ce2054 100644 --- a/core/finality-grandpa/src/authorities.rs +++ b/core/finality-grandpa/src/authorities.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,16 +18,19 @@ use fork_tree::ForkTree; use parking_lot::RwLock; -use substrate_primitives::Ed25519AuthorityId; +use substrate_primitives::ed25519; use grandpa::VoterSet; use parity_codec::{Encode, Decode}; use log::{debug, info}; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; use std::cmp::Ord; use std::fmt::Debug; use std::ops::Add; use std::sync::Arc; +use ed25519::Public as AuthorityId; + /// A shared authority set. pub(crate) struct SharedAuthoritySet { inner: Arc>>, @@ -61,7 +64,7 @@ where N: Add + Ord + Clone + Debug, } /// Get the current authorities and their weights (for the current set ID). - pub(crate) fn current_authorities(&self) -> VoterSet { + pub(crate) fn current_authorities(&self) -> VoterSet { self.inner.read().current_authorities.iter().cloned().collect() } } @@ -85,7 +88,7 @@ pub(crate) struct Status { /// A set of authorities. #[derive(Debug, Clone, Encode, Decode, PartialEq)] pub(crate) struct AuthoritySet { - pub(crate) current_authorities: Vec<(Ed25519AuthorityId, u64)>, + pub(crate) current_authorities: Vec<(AuthorityId, u64)>, pub(crate) set_id: u64, // Tree of pending standard changes across forks. Standard changes are // enacted on finality and must be enacted (i.e. finalized) in-order across @@ -102,7 +105,7 @@ where H: PartialEq, N: Ord, { /// Get a genesis set with given authorities. - pub(crate) fn genesis(initial: Vec<(Ed25519AuthorityId, u64)>) -> Self { + pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self { AuthoritySet { current_authorities: initial, set_id: 0, @@ -112,7 +115,7 @@ where H: PartialEq, } /// Get the current set id and a reference to the current authority set. - pub(crate) fn current(&self) -> (u64, &[(Ed25519AuthorityId, u64)]) { + pub(crate) fn current(&self) -> (u64, &[(AuthorityId, u64)]) { (self.set_id, &self.current_authorities[..]) } } @@ -133,7 +136,7 @@ where let hash = pending.canon_hash.clone(); let number = pending.canon_height.clone(); - debug!(target: "afg", "Inserting potential standard set change signalled at block {:?} \ + debug!(target: "afg", "Inserting potential standard set change signaled at block {:?} \ (delayed by {:?} blocks).", (&number, &hash), pending.delay); @@ -254,11 +257,14 @@ where .take_while(|c| c.effective_number() <= best_number) // to prevent iterating too far .filter(|c| c.effective_number() == best_number) { - // check if the given best block is in the same branch as the block that signalled the change. + // check if the given best block is in the same branch as the block that signaled the change. if is_descendent_of(&change.canon_hash, &best_hash)? { // apply this change: make the set canonical info!(target: "finality", "Applying authority set change forced at block #{:?}", change.canon_height); + telemetry!(CONSENSUS_INFO; "afg.applying_forced_authority_set_change"; + "block" => ?change.canon_height + ); let median_last_finalized = match change.delay_kind { DelayKind::Best { ref median_last_finalized } => median_last_finalized.clone(), @@ -322,6 +328,9 @@ where if let Some(change) = change { info!(target: "finality", "Applying authority set change scheduled at block #{:?}", change.canon_height); + telemetry!(CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change"; + "block" => ?change.canon_height + ); self.current_authorities = change.next_authorities; self.set_id += 1; @@ -342,14 +351,18 @@ where /// authority set change (without triggering it), ensuring that if there are /// multiple changes in the same branch, finalizing this block won't /// finalize past multiple transitions (i.e. transitions must be finalized - /// in-order). The given function `is_descendent_of` should return `true` if - /// the second hash (target) is a descendent of the first hash (base). + /// in-order). Returns `Some(true)` if the block being finalized enacts a + /// change that can be immediately applied, `Some(false)` if the block being + /// finalized enacts a change but it cannot be applied yet since there are + /// other dependent changes, and `None` if no change is enacted. The given + /// function `is_descendent_of` should return `true` if the second hash + /// (target) is a descendent of the first hash (base). pub fn enacts_standard_change( &self, finalized_hash: H, finalized_number: N, is_descendent_of: &F, - ) -> Result> + ) -> Result, fork_tree::Error> where F: Fn(&H, &H) -> Result, E: std::error::Error, { @@ -368,7 +381,7 @@ pub(crate) enum DelayKind { /// Depth in finalized chain. Finalized, /// Depth in best chain. The median last finalized block is calculated at the time the - /// change was signalled. + /// change was signaled. Best { median_last_finalized: N }, } @@ -379,7 +392,7 @@ pub(crate) enum DelayKind { #[derive(Debug, Clone, Encode, PartialEq)] pub(crate) struct PendingChange { /// The new authorities and weights to apply. - pub(crate) next_authorities: Vec<(Ed25519AuthorityId, u64)>, + pub(crate) next_authorities: Vec<(AuthorityId, u64)>, /// How deep in the chain the announcing block must be /// before the change is applied. pub(crate) delay: N, @@ -509,8 +522,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; - let set_b = vec![([2; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_b = vec![(AuthorityId([2; 32]), 5)]; // two competing changes at the same height on different forks let change_a = PendingChange { @@ -537,7 +550,7 @@ mod tests { vec![&change_b, &change_a], ); - // finalizing "hash_c" won't enact the change signalled at "hash_a" but it will prune out "hash_b" + // finalizing "hash_c" won't enact the change signaled at "hash_a" but it will prune out "hash_b" let status = authorities.apply_standard_changes("hash_c", 11, &is_descendent_of(|base, hash| match (*base, *hash) { ("hash_a", "hash_c") => true, ("hash_b", "hash_c") => false, @@ -551,7 +564,7 @@ mod tests { vec![&change_a], ); - // finalizing "hash_d" will enact the change signalled at "hash_a" + // finalizing "hash_d" will enact the change signaled at "hash_a" let status = authorities.apply_standard_changes("hash_d", 15, &is_descendent_of(|base, hash| match (*base, *hash) { ("hash_a", "hash_d") => true, _ => unreachable!(), @@ -574,8 +587,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; - let set_c = vec![([2; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_c = vec![(AuthorityId([2; 32]), 5)]; // two competing changes at the same height on different forks let change_a = PendingChange { @@ -640,7 +653,7 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; let change_a = PendingChange { next_authorities: set_a.clone(), @@ -650,21 +663,51 @@ mod tests { delay_kind: DelayKind::Finalized, }; + let change_b = PendingChange { + next_authorities: set_a.clone(), + delay: 10, + canon_height: 20, + canon_hash: "hash_b", + delay_kind: DelayKind::Finalized, + }; + authorities.add_pending_change(change_a.clone(), &static_is_descendent_of(false)).unwrap(); + authorities.add_pending_change(change_b.clone(), &static_is_descendent_of(true)).unwrap(); let is_descendent_of = is_descendent_of(|base, hash| match (*base, *hash) { - ("hash_a", "hash_b") => true, + ("hash_a", "hash_d") => true, + ("hash_a", "hash_e") => true, + ("hash_b", "hash_d") => true, + ("hash_b", "hash_e") => true, ("hash_a", "hash_c") => false, + ("hash_b", "hash_c") => false, _ => unreachable!(), }); // "hash_c" won't finalize the existing change since it isn't a descendent - assert!(!authorities.enacts_standard_change("hash_c", 15, &is_descendent_of).unwrap()); - // "hash_b" at depth 14 won't work either - assert!(!authorities.enacts_standard_change("hash_b", 14, &is_descendent_of).unwrap()); + assert_eq!( + authorities.enacts_standard_change("hash_c", 15, &is_descendent_of).unwrap(), + None, + ); + + // "hash_d" at depth 14 won't work either + assert_eq!( + authorities.enacts_standard_change("hash_d", 14, &is_descendent_of).unwrap(), + None, + ); // but it should work at depth 15 (change height + depth) - assert!(authorities.enacts_standard_change("hash_b", 15, &is_descendent_of).unwrap()); + assert_eq!( + authorities.enacts_standard_change("hash_d", 15, &is_descendent_of).unwrap(), + Some(true), + ); + + // finalizing "hash_e" at depth 20 will trigger change at "hash_b", but + // it can't be applied yet since "hash_a" must be applied first + assert_eq!( + authorities.enacts_standard_change("hash_e", 30, &is_descendent_of).unwrap(), + Some(false), + ); } #[test] @@ -676,8 +719,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; - let set_b = vec![([2; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_b = vec![(AuthorityId([2; 32]), 5)]; let change_a = PendingChange { next_authorities: set_a.clone(), @@ -700,7 +743,10 @@ mod tests { // there's an effective change triggered at block 15 but not a standard one. // so this should do nothing. - assert!(!authorities.enacts_standard_change("hash_c", 15, &static_is_descendent_of(true)).unwrap()); + assert_eq!( + authorities.enacts_standard_change("hash_c", 15, &static_is_descendent_of(true)).unwrap(), + None, + ); // throw a standard change into the mix to prove that it's discarded // for being on the same fork. diff --git a/core/finality-grandpa/src/aux_schema.rs b/core/finality-grandpa/src/aux_schema.rs index 930329344b8fb4a3413bed94116f887fcb10293f..cb41d481e3603b183205f7069308a334465b6cb1 100644 --- a/core/finality-grandpa/src/aux_schema.rs +++ b/core/finality-grandpa/src/aux_schema.rs @@ -16,20 +16,20 @@ //! Schema for stuff in the aux-db. +use std::fmt::Debug; +use std::sync::Arc; use parity_codec::{Encode, Decode}; use client::backend::AuxStore; use client::error::{Result as ClientResult, Error as ClientError, ErrorKind as ClientErrorKind}; use fork_tree::ForkTree; use grandpa::round::State as RoundState; -use substrate_primitives::Ed25519AuthorityId; use log::{info, warn}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind}; use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges}; use crate::NewAuthoritySet; -use std::fmt::Debug; -use std::sync::Arc; +use substrate_primitives::ed25519::Public as AuthorityId; const VERSION_KEY: &[u8] = b"grandpa_schema_version"; const SET_STATE_KEY: &[u8] = b"grandpa_completed_round"; @@ -39,7 +39,8 @@ const CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; const CURRENT_VERSION: u32 = 1; /// The voter set state. -#[derive(Clone, Encode, Decode)] +#[derive(Debug, Clone, Encode, Decode)] +#[cfg_attr(test, derive(PartialEq))] pub enum VoterSetState { /// The voter set state, currently paused. Paused(u64, RoundState), @@ -61,7 +62,7 @@ type V0VoterSetState = (u64, RoundState); #[derive(Debug, Clone, Encode, Decode, PartialEq)] struct V0PendingChange { - next_authorities: Vec<(Ed25519AuthorityId, u64)>, + next_authorities: Vec<(AuthorityId, u64)>, delay: N, canon_height: N, canon_hash: H, @@ -69,7 +70,7 @@ struct V0PendingChange { #[derive(Debug, Clone, Encode, Decode, PartialEq)] struct V0AuthoritySet { - current_authorities: Vec<(Ed25519AuthorityId, u64)>, + current_authorities: Vec<(AuthorityId, u64)>, set_id: u64, pending_changes: Vec>, } @@ -141,7 +142,7 @@ pub(crate) fn load_persistent( B: AuxStore, H: Debug + Decode + Encode + Clone + PartialEq, N: Debug + Decode + Encode + Clone + Ord, - G: FnOnce() -> ClientResult> + G: FnOnce() -> ClientResult> { let version: Option = load_decode(backend, VERSION_KEY)?; let consensus_changes = load_decode(backend, CONSENSUS_CHANGES_KEY)? @@ -160,7 +161,11 @@ pub(crate) fn load_persistent( backend.insert_aux(&[(AUTHORITY_SET_KEY, new_set.encode().as_slice())], &[])?; let set_state = match load_decode::<_, V0VoterSetState>(backend, SET_STATE_KEY)? { - Some((number, state)) => VoterSetState::Live(number, state), + Some((number, state)) => { + let set_state = VoterSetState::Live(number, state); + backend.insert_aux(&[(SET_STATE_KEY, set_state.encode().as_slice())], &[])?; + set_state + }, None => VoterSetState::Live(0, make_genesis_round()), }; @@ -273,3 +278,83 @@ pub(crate) fn load_authorities(backend: &B) load_decode::<_, AuthoritySet>(backend, AUTHORITY_SET_KEY) .expect("backend error") } + +#[cfg(test)] +mod test { + use substrate_primitives::H256; + use test_client; + use super::*; + + #[test] + fn load_decode_migrates_data_format() { + let client = test_client::new(); + + let authorities = vec![(AuthorityId::default(), 100)]; + let set_id = 3; + let round_number = 42; + let round_state = RoundState:: { + prevote_ghost: None, + finalized: None, + estimate: None, + completable: false, + }; + + { + let authority_set = V0AuthoritySet:: { + current_authorities: authorities.clone(), + pending_changes: Vec::new(), + set_id, + }; + + let voter_set_state = (round_number, round_state.clone()); + + client.insert_aux( + &[ + (AUTHORITY_SET_KEY, authority_set.encode().as_slice()), + (SET_STATE_KEY, voter_set_state.encode().as_slice()), + ], + &[], + ).unwrap(); + } + + assert_eq!( + load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), + None, + ); + + // should perform the migration + load_persistent( + &client, + H256::random(), + 0, + || unreachable!(), + ).unwrap(); + + assert_eq!( + load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), + Some(1), + ); + + let PersistentData { authority_set, set_state, .. } = load_persistent( + &client, + H256::random(), + 0, + || unreachable!(), + ).unwrap(); + + assert_eq!( + *authority_set.inner().read(), + AuthoritySet { + current_authorities: authorities, + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + set_id, + }, + ); + + assert_eq!( + set_state, + VoterSetState::Live(round_number, round_state), + ); + } +} diff --git a/core/finality-grandpa/src/communication.rs b/core/finality-grandpa/src/communication.rs index 4f6024fb95b3dcb175f593974f2a963da2c650a2..f498b51460ace8cb46e6276a178e40262680896c 100644 --- a/core/finality-grandpa/src/communication.rs +++ b/core/finality-grandpa/src/communication.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,15 +21,18 @@ use std::collections::HashMap; use std::sync::Arc; use grandpa::VoterSet; +use grandpa::Message::{Prevote, Precommit}; use futures::prelude::*; use futures::sync::mpsc; use log::{debug, trace}; use parity_codec::{Encode, Decode}; -use substrate_primitives::{ed25519, Ed25519AuthorityId}; +use substrate_primitives::{ed25519, Pair}; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; use runtime_primitives::traits::Block as BlockT; use tokio::timer::Interval; use crate::{Error, Network, Message, SignedMessage, Commit, CompactCommit, GossipMessage, FullCommitMessage, VoteOrPrecommitMessage}; +use ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; fn localized_payload(round: u64, set_id: u64, message: &E) -> Vec { (message, round, set_id).encode() @@ -127,12 +130,12 @@ impl> Future for BroadcastWorker { if rebroadcast { let SetId(set_id) = self.set_id; if let Some((Round(c_round), ref c_commit)) = self.last_commit { - self.network.send_commit(c_round, set_id, c_commit.clone()); + self.network.send_commit(c_round, set_id, c_commit.clone(), true); } let Round(round) = self.round_messages.0; for message in self.round_messages.1.iter().cloned() { - self.network.send_message(round, set_id, message); + self.network.send_message(round, set_id, message, true); } for (&announce_hash, &Round(round)) in &self.announcements { @@ -140,6 +143,7 @@ impl> Future for BroadcastWorker { } } } + loop { match self.incoming_broadcast.poll().expect("UnboundedReceiver does not yield errors; qed") { Async::NotReady => return Ok(Async::NotReady), @@ -165,7 +169,7 @@ impl> Future for BroadcastWorker { } // always send out to network. - self.network.send_commit(round.0, self.set_id.0, commit); + self.network.send_commit(round.0, self.set_id.0, commit, false); } Broadcast::Message(round, set_id, message) => { if self.set_id == set_id { @@ -179,7 +183,7 @@ impl> Future for BroadcastWorker { } // always send out to network. - self.network.send_message(round.0, set_id.0, message); + self.network.send_message(round.0, set_id.0, message, false); } Broadcast::Announcement(round, set_id, hash) => { if self.set_id == set_id { @@ -212,7 +216,7 @@ impl> Network for BroadcastHandle { self.network.messages_for(round, set_id) } - fn send_message(&self, round: u64, set_id: u64, message: Vec) { + fn send_message(&self, round: u64, set_id: u64, message: Vec, _force: bool) { let _ = self.relay.unbounded_send(Broadcast::Message(Round(round), SetId(set_id), message)); } @@ -228,7 +232,7 @@ impl> Network for BroadcastHandle { self.network.commit_messages(set_id) } - fn send_commit(&self, round: u64, set_id: u64, message: Vec) { + fn send_commit(&self, round: u64, set_id: u64, message: Vec, _force: bool) { let _ = self.relay.unbounded_send(Broadcast::Commit(Round(round), SetId(set_id), message)); } @@ -242,14 +246,14 @@ impl> Network for BroadcastHandle { // check a message. pub(crate) fn check_message_sig( message: &Message, - id: &Ed25519AuthorityId, - signature: &ed25519::Signature, + id: &AuthorityId, + signature: &AuthoritySignature, round: u64, set_id: u64, ) -> Result<(), ()> { - let as_public = ed25519::Public::from_raw(id.0); + let as_public = AuthorityId::from_raw(id.0); let encoded_raw = localized_payload(round, set_id, message); - if ed25519::verify_strong(signature, &encoded_raw, as_public) { + if ed25519::Pair::verify(signature, &encoded_raw, as_public) { Ok(()) } else { debug!(target: "afg", "Bad signature on message from {:?}", id); @@ -261,7 +265,7 @@ pub(crate) fn check_message_sig( /// the output stream checks signatures also. pub(crate) fn checked_message_stream( inner: S, - voters: Arc>, + voters: Arc>, ) -> impl Stream,Error=Error> where S: Stream,Error=()> @@ -282,6 +286,24 @@ pub(crate) fn checked_message_stream( debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); return Ok(None); } + + match &msg.message.message { + Prevote(prevote) => { + telemetry!(CONSENSUS_INFO; "afg.received_prevote"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?prevote.target_number, + "target_hash" => ?prevote.target_hash, + ); + }, + Precommit(precommit) => { + telemetry!(CONSENSUS_INFO; "afg.received_precommit"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?precommit.target_number, + "target_hash" => ?precommit.target_hash, + ); + }, + }; + Ok(Some(msg.message)) } _ => { @@ -297,7 +319,7 @@ pub(crate) fn checked_message_stream( pub(crate) struct OutgoingMessages> { round: u64, set_id: u64, - locals: Option<(Arc, Ed25519AuthorityId)>, + locals: Option<(Arc, AuthorityId)>, sender: mpsc::UnboundedSender>, network: N, } @@ -309,7 +331,7 @@ impl> Sink for OutgoingMessages fn start_send(&mut self, msg: Message) -> StartSend, Error> { // when locals exist, sign messages on import - if let Some((ref pair, local_id)) = self.locals { + if let Some((ref pair, ref local_id)) = self.locals { let encoded = localized_payload(self.round, self.set_id, &msg); let signature = pair.sign(&encoded[..]); @@ -317,7 +339,7 @@ impl> Sink for OutgoingMessages let signed = SignedMessage:: { message: msg, signature, - id: local_id, + id: local_id.clone(), }; let message = GossipMessage::VoteOrPrecommit(VoteOrPrecommitMessage:: { @@ -329,7 +351,7 @@ impl> Sink for OutgoingMessages // announce our block hash to peers and propagate the // message. self.network.announce(self.round, self.set_id, target_hash); - self.network.send_message(self.round, self.set_id, message.encode()); + self.network.send_message(self.round, self.set_id, message.encode(), false); // forward the message to the inner sender. let _ = self.sender.unbounded_send(signed); @@ -361,7 +383,7 @@ pub(crate) fn outgoing_messages>( round: u64, set_id: u64, local_key: Option>, - voters: Arc>, + voters: Arc>, network: N, ) -> ( impl Stream,Error=Error>, @@ -369,7 +391,7 @@ pub(crate) fn outgoing_messages>( ) { let locals = local_key.and_then(|pair| { let public = pair.public(); - let id = Ed25519AuthorityId(public.0); + let id = AuthorityId(public.0); if voters.contains_key(&id) { Some((pair, id)) } else { @@ -395,7 +417,7 @@ pub(crate) fn outgoing_messages>( fn check_compact_commit( msg: CompactCommit, - voters: &VoterSet, + voters: &VoterSet, ) -> Option> { if msg.precommits.len() != msg.auth_data.len() || msg.precommits.is_empty() { debug!(target: "afg", "Skipping malformed compact commit"); @@ -417,7 +439,7 @@ fn check_compact_commit( /// messages. pub(crate) fn checked_commit_stream( inner: S, - voters: Arc>, + voters: Arc>, ) -> impl Stream),Error=Error> where S: Stream,Error=()> @@ -435,6 +457,15 @@ pub(crate) fn checked_commit_stream( match msg { GossipMessage::Commit(msg) => { let round = msg.round; + let precommits_signed_by: Vec = + msg.message.auth_data.iter().map(move |(_, a)| { + format!("{}", a) + }).collect(); + telemetry!(CONSENSUS_INFO; "afg.received_commit"; + "contains_precommits_signed_by" => ?precommits_signed_by, + "target_number" => ?msg.message.target_number, + "target_hash" => ?msg.message.target_hash, + ); check_compact_commit::(msg.message, &*voters).map(move |c| (round, c)) }, _ => { @@ -476,6 +507,9 @@ impl> Sink for CommitsOut { } let (round, commit) = input; + telemetry!(CONSENSUS_INFO; "afg.commit_issued"; + "target_number" => ?commit.target_number, "target_hash" => ?commit.target_hash, + ); let (precommits, auth_data) = commit.precommits.into_iter() .map(|signed| (signed.precommit, (signed.signature, signed.id))) .unzip(); @@ -493,7 +527,7 @@ impl> Sink for CommitsOut { message: compact_commit, }); - self.network.send_commit(round, self.set_id, Encode::encode(&message)); + self.network.send_commit(round, self.set_id, Encode::encode(&message), false); Ok(AsyncSink::Ready) } diff --git a/core/finality-grandpa/src/environment.rs b/core/finality-grandpa/src/environment.rs index 857d6eafd711326d7d7f8367b0e8decadb3a0fe6..587762b608e0eca3d00133daf707d7282c05de3b 100644 --- a/core/finality-grandpa/src/environment.rs +++ b/core/finality-grandpa/src/environment.rs @@ -33,7 +33,8 @@ use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ As, Block as BlockT, Header as HeaderT, NumberFor, One, Zero, }; -use substrate_primitives::{Blake2Hasher, ed25519,Ed25519AuthorityId, H256}; +use substrate_primitives::{Blake2Hasher, ed25519, H256, Pair}; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; use crate::{ Commit, Config, Error, Network, Precommit, Prevote, @@ -45,6 +46,8 @@ use crate::consensus_changes::SharedConsensusChanges; use crate::justification::GrandpaJustification; use crate::until_imported::UntilVoteTargetImported; +use ed25519::Public as AuthorityId; + /// Data about a completed round. pub(crate) type CompletedRound = (u64, RoundState); @@ -75,7 +78,7 @@ impl LastCompletedRound { /// The environment we run GRANDPA in. pub(crate) struct Environment, RA> { pub(crate) inner: Arc>, - pub(crate) voters: Arc>, + pub(crate) voters: Arc>, pub(crate) config: Config, pub(crate) authority_set: SharedAuthoritySet>, pub(crate) consensus_changes: SharedConsensusChanges>, @@ -122,7 +125,7 @@ impl, B, E, N, RA> grandpa::Chain Option<(Block::Hash, NumberFor)> { // NOTE: when we finalize an authority set change through the sync protocol the voter is - // signalled asynchronously. therefore the voter could still vote in the next round + // signaled asynchronously. therefore the voter could still vote in the next round // before activating the new set. the `authority_set` is updated immediately thus we // restrict the voter based on that. if self.set_id != self.authority_set.inner().read().current().0 { @@ -205,7 +208,7 @@ impl, N, RA> voter::Environment: BlockNumberOps, { type Timer = Box + Send>; - type Id = Ed25519AuthorityId; + type Id = AuthorityId; type Signature = ed25519::Signature; // regular round message streams @@ -467,6 +470,9 @@ pub(crate) fn finalize_block, E, RA>( warn!(target: "finality", "Error applying finality to block {:?}: {:?}", (hash, number), e); e })?; + telemetry!(CONSENSUS_INFO; "afg.finalized_blocks_up_to"; + "number" => ?number, "hash" => ?hash, + ); let new_authorities = if let Some((canon_hash, canon_number)) = status.new_set_block { // the authority set has changed. @@ -478,6 +484,11 @@ pub(crate) fn finalize_block, E, RA>( info!("Applying GRANDPA set change to new set {:?}", set_ref); } + telemetry!(CONSENSUS_INFO; "afg.generating_new_authority_set"; + "number" => ?canon_number, "hash" => ?canon_hash, + "authorities" => ?set_ref.to_vec(), + "set_id" => ?new_id, + ); Some(NewAuthoritySet { canon_hash, canon_number, diff --git a/core/finality-grandpa/src/finality_proof.rs b/core/finality-grandpa/src/finality_proof.rs index 14f011a10c315b949ae8a3bcf540758824a4cb10..2b34a094a06494cad6ff2c1d49f37a35bcf6afe6 100644 --- a/core/finality-grandpa/src/finality_proof.rs +++ b/core/finality-grandpa/src/finality_proof.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -42,7 +42,9 @@ use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ NumberFor, Block as BlockT, Header as HeaderT, One, }; -use substrate_primitives::{Ed25519AuthorityId, H256}; +use substrate_primitives::{ed25519, H256}; +use ed25519::Public as AuthorityId; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; use crate::justification::GrandpaJustification; @@ -169,14 +171,14 @@ fn do_check_finality_proof, C, J>( } } - // check that the last header in finalization path is the jsutification target block + // check that the last header in finalization path is the justification target block let just_block = proof.justification.target_block(); { let finalized_header = proof.finalization_path.last() .expect("checked above that proof.finalization_path is not empty; qed"); if *finalized_header.number() != just_block.0 || finalized_header.hash() != just_block.1 { return Err(ClientErrorKind::BadJustification( - "finality proof: target jsutification block is not a part of finalized path".into() + "finality proof: target justification block is not a part of finalized path".into() ).into()); } } @@ -189,12 +191,14 @@ fn do_check_finality_proof, C, J>( call_data: vec![], retry_count: None, })?; - let grandpa_authorities: Vec<(Ed25519AuthorityId, u64)> = Decode::decode(&mut &grandpa_authorities[..]) + let grandpa_authorities: Vec<(AuthorityId, u64)> = Decode::decode(&mut &grandpa_authorities[..]) .ok_or_else(|| ClientErrorKind::BadJustification("failed to decode GRANDPA authorities set proof".into()))?; // and now check justification proof.justification.verify(set_id, &grandpa_authorities.into_iter().collect())?; + telemetry!(CONSENSUS_INFO; "afg.finality_proof_ok"; + "set_id" => ?set_id, "finalized_header_hash" => ?block.1); Ok(proof.finalization_path) } @@ -222,7 +226,7 @@ trait ProvableJustification: Encode + Decode { fn target_block(&self) -> (Header::Number, Header::Hash); /// Verify justification with respect to authorities set and authorities set id. - fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()>; + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()>; } impl> ProvableJustification for GrandpaJustification @@ -233,7 +237,7 @@ impl> ProvableJustification for GrandpaJ (self.commit.target_number, self.commit.target_hash) } - fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { GrandpaJustification::verify(self, set_id, authorities) } } @@ -253,12 +257,12 @@ mod tests { impl ProvableJustification

for ValidFinalityProof { fn target_block(&self) -> (u64, H256) { (3, header(3).hash()) } - fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { assert_eq!(set_id, 1); assert_eq!(authorities, &vec![ - (Ed25519AuthorityId([1u8; 32]), 1), - (Ed25519AuthorityId([2u8; 32]), 2), - (Ed25519AuthorityId([3u8; 32]), 3), + (AuthorityId([1u8; 32]), 1), + (AuthorityId([2u8; 32]), 2), + (AuthorityId([3u8; 32]), 3), ].into_iter().collect()); Ok(()) } @@ -387,7 +391,7 @@ mod tests { impl ProvableJustification
for InvalidFinalityProof { fn target_block(&self) -> (u64, H256) { (3, header(3).hash()) } - fn verify(&self, _set_id: u64, _authorities: &VoterSet) -> ClientResult<()> { + fn verify(&self, _set_id: u64, _authorities: &VoterSet) -> ClientResult<()> { Err(ClientErrorKind::Backend("test error".into()).into()) } } @@ -415,9 +419,9 @@ mod tests { .unwrap().unwrap(); assert_eq!(do_check_finality_proof::( |_| Ok(vec![ - (Ed25519AuthorityId([1u8; 32]), 1u64), - (Ed25519AuthorityId([2u8; 32]), 2u64), - (Ed25519AuthorityId([3u8; 32]), 3u64), + (AuthorityId([1u8; 32]), 1u64), + (AuthorityId([2u8; 32]), 2u64), + (AuthorityId([3u8; 32]), 3u64), ].encode()), header(1), (2, header(2).hash()), diff --git a/core/finality-grandpa/src/import.rs b/core/finality-grandpa/src/import.rs index 3f4dbb3650a86eb027d472cfbe88ee851c3663d1..5fa20fc2f664518ecc8f23659ead9b361ca348a1 100644 --- a/core/finality-grandpa/src/import.rs +++ b/core/finality-grandpa/src/import.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use std::sync::Arc; +use std::{sync::Arc, collections::HashMap}; use log::{debug, trace, info}; use parity_codec::Encode; @@ -27,7 +27,7 @@ use client::backend::Backend; use client::runtime_api::ApiExt; use consensus_common::{ BlockImport, Error as ConsensusError, ErrorKind as ConsensusErrorKind, - ImportBlock, ImportResult, JustificationImport, + ImportBlock, ImportResult, JustificationImport, well_known_cache_keys, }; use fg_primitives::GrandpaApi; use runtime_primitives::Justification; @@ -36,7 +36,7 @@ use runtime_primitives::traits::{ Block as BlockT, DigestFor, DigestItemFor, DigestItem, Header as HeaderT, NumberFor, ProvideRuntimeApi, }; -use substrate_primitives::{H256, Ed25519AuthorityId, Blake2Hasher}; +use substrate_primitives::{H256, ed25519, Blake2Hasher}; use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange}; @@ -44,6 +44,8 @@ use crate::consensus_changes::SharedConsensusChanges; use crate::environment::{finalize_block, is_descendent_of}; use crate::justification::GrandpaJustification; +use ed25519::Public as AuthorityId; + /// A block-import handler for GRANDPA. /// /// This scans each imported block for signals of changing authority set. @@ -67,7 +69,7 @@ impl, RA, PRA> JustificationImport B: Backend + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, RA: Send + Sync, PRA: ProvideRuntimeApi, PRA::Api: GrandpaApi, @@ -114,7 +116,7 @@ impl, RA, PRA> JustificationImport } enum AppliedChanges { - Standard, + Standard(bool), // true if the change is ready to be applied (i.e. it's a root) Forced(NewAuthoritySet), None, } @@ -122,7 +124,7 @@ enum AppliedChanges { impl AppliedChanges { fn needs_justification(&self) -> bool { match *self { - AppliedChanges::Standard => true, + AppliedChanges::Standard(_) => true, AppliedChanges::Forced(_) | AppliedChanges::None => false, } } @@ -161,7 +163,7 @@ impl, RA, PRA> GrandpaBlockImport + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, RA: Send + Sync, PRA: ProvideRuntimeApi, PRA::Api: GrandpaApi, @@ -343,8 +345,8 @@ impl, RA, PRA> GrandpaBlockImport, RA, PRA> GrandpaBlockImport Some(new), - AppliedChanges::Standard => None, // the change isn't actually applied yet. + AppliedChanges::Standard(_) => None, // the change isn't actually applied yet. AppliedChanges::None => None, }; @@ -379,14 +381,14 @@ impl, RA, PRA> BlockImport B: Backend + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, RA: Send + Sync, PRA: ProvideRuntimeApi, PRA::Api: GrandpaApi, { type Error = ConsensusError; - fn import_block(&self, mut block: ImportBlock, new_authorities: Option>) + fn import_block(&self, mut block: ImportBlock, new_cache: HashMap>) -> Result { let hash = block.post_header().hash(); @@ -403,9 +405,9 @@ impl, RA, PRA> BlockImport let pending_changes = self.make_authorities_changes(&mut block, hash)?; // we don't want to finalize on `inner.import_block` - let justification = block.justification.take(); - let enacts_consensus_change = new_authorities.is_some(); - let import_result = self.inner.import_block(block, new_authorities); + let mut justification = block.justification.take(); + let enacts_consensus_change = !new_cache.is_empty(); + let import_result = self.inner.import_block(block, new_cache); let mut imported_aux = { match import_result { @@ -433,23 +435,34 @@ impl, RA, PRA> BlockImport } let needs_justification = applied_changes.needs_justification(); - if let AppliedChanges::Forced(new) = applied_changes { - // NOTE: when we do a force change we are "discrediting" the old set so we - // ignore any justifications from them. this block may contain a justification - // which should be checked and imported below against the new authority - // triggered by this forced change. the new grandpa voter will start at the - // last median finalized block (which is before the block that enacts the - // change), full nodes syncing the chain will not be able to successfully - // import justifications for those blocks since their local authority set view - // is still of the set before the forced change was enacted, still after #1867 - // they should import the block and discard the justification, and they will - // then request a justification from sync if it's necessary (which they should - // then be able to successfully validate). - let _ = self.send_voter_commands.unbounded_send(VoterCommand::ChangeAuthorities(new)); - - // we must clear all pending justifications requests, presumably they won't be - // finalized hence why this forced changes was triggered - imported_aux.clear_justification_requests = true; + + match applied_changes { + AppliedChanges::Forced(new) => { + // NOTE: when we do a force change we are "discrediting" the old set so we + // ignore any justifications from them. this block may contain a justification + // which should be checked and imported below against the new authority + // triggered by this forced change. the new grandpa voter will start at the + // last median finalized block (which is before the block that enacts the + // change), full nodes syncing the chain will not be able to successfully + // import justifications for those blocks since their local authority set view + // is still of the set before the forced change was enacted, still after #1867 + // they should import the block and discard the justification, and they will + // then request a justification from sync if it's necessary (which they should + // then be able to successfully validate). + let _ = self.send_voter_commands.unbounded_send(VoterCommand::ChangeAuthorities(new)); + + // we must clear all pending justifications requests, presumably they won't be + // finalized hence why this forced changes was triggered + imported_aux.clear_justification_requests = true; + }, + AppliedChanges::Standard(false) => { + // we can't apply this change yet since there are other dependent changes that we + // need to apply first, drop any justification that might have been provided with + // the block to make sure we request them from `sync` which will ensure they'll be + // applied in-order. + justification.take(); + }, + _ => {}, } if !needs_justification && !enacts_consensus_change { @@ -458,7 +471,12 @@ impl, RA, PRA> BlockImport match justification { Some(justification) => { - self.import_justification(hash, number, justification, needs_justification)?; + self.import_justification(hash, number, justification, needs_justification).unwrap_or_else(|err| { + debug!(target: "finality", "Imported block #{} that enacts authority set change with \ + invalid justification: {:?}, requesting justification from peers.", number, err); + imported_aux.bad_justification = true; + imported_aux.needs_justification = true; + }); }, None => { if needs_justification { @@ -552,7 +570,7 @@ impl, RA, PRA> GrandpaBlockImport { info!(target: "finality", "Imported justification for block #{} that triggers \ - command {}, signalling voter.", number, command); + command {}, signaling voter.", number, command); if let Err(e) = self.send_voter_commands.unbounded_send(command) { return Err(ConsensusErrorKind::ClientImport(e.to_string()).into()); diff --git a/core/finality-grandpa/src/justification.rs b/core/finality-grandpa/src/justification.rs index 52ce9006e19abda06c4c6f7c0eef50c3eca47e09..d837e6a30862ea36a7fef9a91a986ed3c0a5c98d 100644 --- a/core/finality-grandpa/src/justification.rs +++ b/core/finality-grandpa/src/justification.rs @@ -25,11 +25,13 @@ use grandpa::VoterSet; use grandpa::{Error as GrandpaError}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{NumberFor, Block as BlockT, Header as HeaderT}; -use substrate_primitives::{H256, Ed25519AuthorityId, Blake2Hasher}; +use substrate_primitives::{H256, ed25519, Blake2Hasher}; use crate::{Commit, Error}; use crate::communication; +use ed25519::Public as AuthorityId; + /// A GRANDPA justification for block finality, it includes a commit message and /// an ancestry proof including all headers routing all precommit target blocks /// to the commit target block. Due to the current voting strategy the precommit @@ -95,7 +97,7 @@ impl> GrandpaJustification { pub(crate) fn decode_and_verify( encoded: Vec, set_id: u64, - voters: &VoterSet, + voters: &VoterSet, ) -> Result, ClientError> where NumberFor: grandpa::BlockNumberOps, { @@ -106,7 +108,7 @@ impl> GrandpaJustification { } /// Validate the commit and the votes' ancestry proofs. - pub(crate) fn verify(&self, set_id: u64, voters: &VoterSet) -> Result<(), ClientError> + pub(crate) fn verify(&self, set_id: u64, voters: &VoterSet) -> Result<(), ClientError> where NumberFor: grandpa::BlockNumberOps, { diff --git a/core/finality-grandpa/src/lib.rs b/core/finality-grandpa/src/lib.rs index a6b3df13fc565995fa86081b564f874d74327a8a..daf37357a0868e81a341b6c23e55f0e838e5e964 100644 --- a/core/finality-grandpa/src/lib.rs +++ b/core/finality-grandpa/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -68,8 +68,8 @@ use runtime_primitives::traits::{ use fg_primitives::GrandpaApi; use inherents::InherentDataProviders; use runtime_primitives::generic::BlockId; -use substrate_primitives::{ed25519, H256, Ed25519AuthorityId, Blake2Hasher}; -use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN}; +use substrate_primitives::{ed25519, H256, Blake2Hasher, Pair}; +use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; use srml_finality_tracker; @@ -106,10 +106,12 @@ pub use finality_proof::{prove_finality, check_finality_proof}; use import::GrandpaBlockImport; use until_imported::UntilCommitBlocksImported; +use ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; + #[cfg(test)] mod tests; -const GRANDPA_ENGINE_ID: network::ConsensusEngineId = [b'a', b'f', b'g', b'1']; +const GRANDPA_ENGINE_ID: runtime_primitives::ConsensusEngineId = [b'a', b'f', b'g', b'1']; const MESSAGE_ROUND_TOLERANCE: u64 = 2; /// A GRANDPA message for a substrate chain. @@ -118,8 +120,8 @@ pub type Message = grandpa::Message<::Hash, NumberFor = grandpa::SignedMessage< ::Hash, NumberFor, - ed25519::Signature, - Ed25519AuthorityId, + AuthoritySignature, + AuthorityId, >; /// Grandpa gossip message type. @@ -148,15 +150,15 @@ pub type Precommit = grandpa::Precommit<::Hash, NumberFo pub type Commit = grandpa::Commit< ::Hash, NumberFor, - ed25519::Signature, - Ed25519AuthorityId + AuthoritySignature, + AuthorityId >; /// A compact commit message for this chain's block type. pub type CompactCommit = grandpa::CompactCommit< ::Hash, NumberFor, - ed25519::Signature, - Ed25519AuthorityId + AuthoritySignature, + AuthorityId >; /// Network level commit message with topic information. @@ -281,6 +283,7 @@ impl TopicTracker { ); return true; } + false } } @@ -356,6 +359,7 @@ impl GossipValidator { -> network_gossip::ValidationResult { use grandpa::Message as GrandpaMessage; + if self.is_expired(full.round, full.set_id) { return network_gossip::ValidationResult::Expired; } @@ -386,6 +390,18 @@ impl GossipValidator { } let topic = commit_topic::(full.set_id); + + let precommits_signed_by: Vec = full.message.auth_data.iter().map(move |(_, a)| { + format!("{}", a) + }).collect(); + + telemetry!(CONSENSUS_INFO; "afg.received_commit_msg"; + "contains_precommits_signed_by" => ?precommits_signed_by, + "round" => ?full.round, + "set_id" => ?full.set_id, + "topic" => ?topic, + "block_hash" => ?full.message, + ); network_gossip::ValidationResult::Valid(topic) } } @@ -429,7 +445,7 @@ pub trait Network: Clone { fn messages_for(&self, round: u64, set_id: u64) -> Self::In; /// Send a message at a specific round out. - fn send_message(&self, round: u64, set_id: u64, message: Vec); + fn send_message(&self, round: u64, set_id: u64, message: Vec, force: bool); /// Clean up messages for a round. fn drop_round_messages(&self, round: u64, set_id: u64); @@ -442,7 +458,7 @@ pub trait Network: Clone { fn commit_messages(&self, set_id: u64) -> Self::In; /// Send message over the commit channel. - fn send_commit(&self, round: u64, set_id: u64, message: Vec); + fn send_commit(&self, round: u64, set_id: u64, message: Vec, force: bool); /// Inform peers that a block with given hash should be downloaded. fn announce(&self, round: u64, set_id: u64, block: Block::Hash); @@ -495,9 +511,9 @@ impl,> Network) { + fn send_message(&self, round: u64, set_id: u64, message: Vec, force: bool) { let topic = message_topic::(round, set_id); - self.service.gossip_consensus_message(topic, GRANDPA_ENGINE_ID, message); + self.service.gossip_consensus_message(topic, GRANDPA_ENGINE_ID, message, force); } fn drop_round_messages(&self, round: u64, set_id: u64) { @@ -520,9 +536,9 @@ impl,> Network) { + fn send_commit(&self, _round: u64, set_id: u64, message: Vec, force: bool) { let topic = commit_topic::(set_id); - self.service.gossip_consensus_message(topic, GRANDPA_ENGINE_ID, message); + self.service.gossip_consensus_message(topic, GRANDPA_ENGINE_ID, message, force); } fn announce(&self, round: u64, _set_id: u64, block: B::Hash) { @@ -560,7 +576,7 @@ pub(crate) struct NewAuthoritySet { pub(crate) canon_number: N, pub(crate) canon_hash: H, pub(crate) set_id: u64, - pub(crate) authorities: Vec<(Ed25519AuthorityId, u64)>, + pub(crate) authorities: Vec<(AuthorityId, u64)>, } /// Commands issued to the voter. @@ -684,16 +700,16 @@ pub fn block_import, RA, PRA>( fn committer_communication, B, E, N, RA>( local_key: Option>, set_id: u64, - voters: &Arc>, + voters: &Arc>, client: &Arc>, network: &N, ) -> ( impl Stream< - Item = (u64, ::grandpa::CompactCommit, ed25519::Signature, Ed25519AuthorityId>), + Item = (u64, ::grandpa::CompactCommit, AuthoritySignature, AuthorityId>), Error = CommandOrError>, >, impl Sink< - SinkItem = (u64, ::grandpa::Commit, ed25519::Signature, Ed25519AuthorityId>), + SinkItem = (u64, ::grandpa::Commit, AuthoritySignature, AuthorityId>), SinkError = CommandOrError>, >, ) where @@ -702,7 +718,7 @@ fn committer_communication, B, E, N, RA>( N: Network, RA: Send + Sync, NumberFor: BlockNumberOps, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, { // verification stream let commit_in = crate::communication::checked_commit_stream::( @@ -748,7 +764,13 @@ fn register_finality_tracker_inherent_data_provider Err(std::borrow::Cow::Owned(e.to_string())), - Ok(info) => Ok(info.finalized_number), + Ok(info) => { + telemetry!(CONSENSUS_INFO; "afg.finalized"; + "finalized_number" => ?info.finalized_number, + "finalized_hash" => ?info.finalized_hash, + ); + Ok(info.finalized_number) + }, } })) .map_err(|err| consensus_common::ErrorKind::InherentData(err.into()).into()) @@ -773,7 +795,7 @@ pub fn run_grandpa, N, RA>( N::In: Send + 'static, NumberFor: BlockNumberOps, DigestFor: Encode, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, RA: Send + Sync + 'static, { use futures::future::{self, Loop as FutureLoop}; @@ -860,6 +882,16 @@ pub fn run_grandpa, N, RA>( let handle_voter_command = move |command: VoterCommand<_, _>, voter_commands_rx| { match command { VoterCommand::ChangeAuthorities(new) => { + let voters: Vec = new.authorities.iter().map(move |(a, _)| { + format!("{}", a) + }).collect(); + telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities"; + "number" => ?new.canon_number, + "hash" => ?new.canon_hash, + "voters" => ?voters, + "set_id" => ?new.set_id, + ); + // start the new authority set using the block where the // set changed (not where the signal happened!) as the base. let genesis_state = RoundState::genesis((new.canon_hash, new.canon_number)); diff --git a/core/finality-grandpa/src/service_integration.rs b/core/finality-grandpa/src/service_integration.rs index 1986c5c0a491d4e2818e72bfc3ee84a9cd7a9fa3..3eee1dd9408d490f7275532fff3a8ea27ac7b73d 100644 --- a/core/finality-grandpa/src/service_integration.rs +++ b/core/finality-grandpa/src/service_integration.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/finality-grandpa/src/tests.rs b/core/finality-grandpa/src/tests.rs index 7fba9b654cbdd2c1569a78ce0164f3d9e2fb3000..f0d5894bb6d6a075955f4fc4e489d2bd4c057ec6 100644 --- a/core/finality-grandpa/src/tests.rs +++ b/core/finality-grandpa/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,7 +22,7 @@ use network::test::{PassThroughVerifier}; use network::config::{ProtocolConfig, Roles}; use parking_lot::Mutex; use tokio::runtime::current_thread; -use keyring::Keyring; +use keyring::AuthorityKeyring; use client::{ BlockchainEvents, error::Result, blockchain::Backend as BlockchainBackend, @@ -35,8 +35,7 @@ use std::collections::{HashMap, HashSet}; use std::result; use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi}; use runtime_primitives::generic::BlockId; -use runtime_primitives::ExecutionContext; -use substrate_primitives::NativeOrEncoded; +use substrate_primitives::{NativeOrEncoded, ExecutionContext}; use authorities::AuthoritySet; use consensus_changes::ConsensusChanges; @@ -193,9 +192,10 @@ impl Network for MessageRouting { Box::new(messages) } - fn send_message(&self, round: u64, set_id: u64, message: Vec) { + fn send_message(&self, round: u64, set_id: u64, message: Vec, force: bool) { let inner = self.inner.lock(); - inner.peer(self.peer_id).gossip_message(make_topic(round, set_id), GRANDPA_ENGINE_ID, message); + inner.peer(self.peer_id) + .gossip_message(make_topic(round, set_id), GRANDPA_ENGINE_ID, message, force); } fn drop_round_messages(&self, round: u64, set_id: u64) { @@ -214,7 +214,7 @@ impl Network for MessageRouting { self.validator.note_set(set_id); let inner = self.inner.lock(); let peer = inner.peer(self.peer_id); - let messages = peer.consensus_gossip_messages_for( + let messages = peer.consensus_gossip_messages_for( GRANDPA_ENGINE_ID, make_commit_topic(set_id), ); @@ -226,9 +226,10 @@ impl Network for MessageRouting { Box::new(messages) } - fn send_commit(&self, _round: u64, set_id: u64, message: Vec) { + fn send_commit(&self, _round: u64, set_id: u64, message: Vec, force: bool) { let inner = self.inner.lock(); - inner.peer(self.peer_id).gossip_message(make_commit_topic(set_id), GRANDPA_ENGINE_ID, message); + inner.peer(self.peer_id) + .gossip_message(make_commit_topic(set_id), GRANDPA_ENGINE_ID, message, force); } fn announce(&self, _round: u64, _set_id: u64, _block: H256) { @@ -238,13 +239,13 @@ impl Network for MessageRouting { #[derive(Default, Clone)] struct TestApi { - genesis_authorities: Vec<(Ed25519AuthorityId, u64)>, + genesis_authorities: Vec<(AuthorityId, u64)>, scheduled_changes: Arc>>>, forced_changes: Arc)>>>, } impl TestApi { - fn new(genesis_authorities: Vec<(Ed25519AuthorityId, u64)>) -> Self { + fn new(genesis_authorities: Vec<(AuthorityId, u64)>) -> Self { TestApi { genesis_authorities, scheduled_changes: Arc::new(Mutex::new(HashMap::new())), @@ -276,16 +277,6 @@ impl Core for RuntimeApi { unimplemented!("Not required for testing!") } - fn authorities_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<()>, - _: Vec, - ) -> Result>> { - unimplemented!("Not required for testing!") - } - fn execute_block_runtime_api_impl( &self, _: &BlockId, @@ -296,7 +287,7 @@ impl Core for RuntimeApi { unimplemented!("Not required for testing!") } - fn initialise_block_runtime_api_impl( + fn initialize_block_runtime_api_impl( &self, _: &BlockId, _: ExecutionContext, @@ -327,7 +318,7 @@ impl GrandpaApi for RuntimeApi { _: ExecutionContext, _: Option<()>, _: Vec, - ) -> Result>> { + ) -> Result>> { if at == &BlockId::Number(0) { Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) } else { @@ -374,9 +365,9 @@ impl GrandpaApi for RuntimeApi { const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500); const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50); -fn make_ids(keys: &[Keyring]) -> Vec<(Ed25519AuthorityId, u64)> { +fn make_ids(keys: &[AuthorityKeyring]) -> Vec<(AuthorityId, u64)> { keys.iter() - .map(|key| Ed25519AuthorityId(key.to_raw_public())) + .map(|key| AuthorityId(key.to_raw_public())) .map(|id| (id, 1)) .collect() } @@ -386,7 +377,7 @@ fn make_ids(keys: &[Keyring]) -> Vec<(Ed25519AuthorityId, u64)> { fn run_to_completion_with( blocks: u64, net: Arc>, - peers: &[Keyring], + peers: &[AuthorityKeyring], before_waiting: F, ) -> u64 { use parking_lot::RwLock; @@ -462,14 +453,14 @@ fn run_to_completion_with( highest_finalized } -fn run_to_completion(blocks: u64, net: Arc>, peers: &[Keyring]) -> u64 { +fn run_to_completion(blocks: u64, net: Arc>, peers: &[AuthorityKeyring]) -> u64 { run_to_completion_with(blocks, net, peers, || {}) } #[test] fn finalize_3_voters_no_observers() { let _ = env_logger::try_init(); - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers); let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); @@ -491,7 +482,7 @@ fn finalize_3_voters_no_observers() { #[test] fn finalize_3_voters_1_observer() { - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers); let mut net = GrandpaTestNet::new(TestApi::new(voters), 4); @@ -554,24 +545,24 @@ fn finalize_3_voters_1_observer() { fn transition_3_voters_twice_1_observer() { let _ = env_logger::try_init(); let peers_a = &[ - Keyring::Alice, - Keyring::Bob, - Keyring::Charlie, + AuthorityKeyring::Alice, + AuthorityKeyring::Bob, + AuthorityKeyring::Charlie, ]; let peers_b = &[ - Keyring::Dave, - Keyring::Eve, - Keyring::Ferdie, + AuthorityKeyring::Dave, + AuthorityKeyring::Eve, + AuthorityKeyring::Ferdie, ]; let peers_c = &[ - Keyring::Alice, - Keyring::Eve, - Keyring::Two, + AuthorityKeyring::Alice, + AuthorityKeyring::Eve, + AuthorityKeyring::Two, ]; - let observer = &[Keyring::One]; + let observer = &[AuthorityKeyring::One]; let genesis_voters = make_ids(peers_a); @@ -719,11 +710,11 @@ fn transition_3_voters_twice_1_observer() { #[test] fn justification_is_emitted_when_consensus_data_changes() { - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3); // import block#1 WITH consensus data change - let new_authorities = vec![Ed25519AuthorityId::from([42; 32])]; + let new_authorities = vec![AuthorityId::from_raw([42; 32])]; net.peer(0).push_authorities_change_block(new_authorities); net.sync(); let net = Arc::new(Mutex::new(net)); @@ -736,7 +727,7 @@ fn justification_is_emitted_when_consensus_data_changes() { #[test] fn justification_is_generated_periodically() { - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers); let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); @@ -775,8 +766,8 @@ fn consensus_changes_works() { #[test] fn sync_justifications_on_change_blocks() { - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; - let peers_b = &[Keyring::Alice, Keyring::Bob]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob]; let voters = make_ids(peers_b); // 4 peers, 3 of them are authorities and participate in grandpa @@ -825,13 +816,13 @@ fn sync_justifications_on_change_blocks() { fn finalizes_multiple_pending_changes_in_order() { let _ = env_logger::try_init(); - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; - let peers_b = &[Keyring::Dave, Keyring::Eve, Keyring::Ferdie]; - let peers_c = &[Keyring::Dave, Keyring::Alice, Keyring::Bob]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Dave, AuthorityKeyring::Eve, AuthorityKeyring::Ferdie]; + let peers_c = &[AuthorityKeyring::Dave, AuthorityKeyring::Alice, AuthorityKeyring::Bob]; let all_peers = &[ - Keyring::Alice, Keyring::Bob, Keyring::Charlie, - Keyring::Dave, Keyring::Eve, Keyring::Ferdie, + AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie, + AuthorityKeyring::Dave, AuthorityKeyring::Eve, AuthorityKeyring::Ferdie, ]; let genesis_voters = make_ids(peers_a); @@ -883,7 +874,7 @@ fn finalizes_multiple_pending_changes_in_order() { #[test] fn doesnt_vote_on_the_tip_of_the_chain() { - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers_a); let api = TestApi::new(voters); let mut net = GrandpaTestNet::new(api, 3); @@ -907,8 +898,8 @@ fn doesnt_vote_on_the_tip_of_the_chain() { #[test] fn force_change_to_new_set() { // two of these guys are offline. - let genesis_authorities = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie, Keyring::One, Keyring::Two]; - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let genesis_authorities = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie, AuthorityKeyring::One, AuthorityKeyring::Two]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let api = TestApi::new(make_ids(genesis_authorities)); let voters = make_ids(peers_a); @@ -960,8 +951,8 @@ fn force_change_to_new_set() { #[test] fn allows_reimporting_change_blocks() { - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; - let peers_b = &[Keyring::Alice, Keyring::Bob]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob]; let voters = make_ids(peers_a); let api = TestApi::new(voters); let net = GrandpaTestNet::new(api.clone(), 3); @@ -991,12 +982,55 @@ fn allows_reimporting_change_blocks() { }; assert_eq!( - block_import.import_block(block(), None).unwrap(), - ImportResult::Imported(ImportedAux { needs_justification: true, clear_justification_requests: false }), + block_import.import_block(block(), HashMap::new()).unwrap(), + ImportResult::Imported(ImportedAux { needs_justification: true, clear_justification_requests: false, bad_justification: false }), + ); + + assert_eq!( + block_import.import_block(block(), HashMap::new()).unwrap(), + ImportResult::AlreadyInChain + ); +} + +#[test] +fn test_bad_justification() { + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob]; + let voters = make_ids(peers_a); + let api = TestApi::new(voters); + let net = GrandpaTestNet::new(api.clone(), 3); + + let client = net.peer(0).client().clone(); + let (block_import, ..) = net.make_block_import(client.clone()); + + let builder = client.new_block_at(&BlockId::Number(0)).unwrap(); + let block = builder.bake().unwrap(); + api.scheduled_changes.lock().insert(*block.header.parent_hash(), ScheduledChange { + next_authorities: make_ids(peers_b), + delay: 0, + }); + + let block = || { + let block = block.clone(); + ImportBlock { + origin: BlockOrigin::File, + header: block.header, + justification: Some(Vec::new()), + post_digests: Vec::new(), + body: Some(block.extrinsics), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + } + }; + + assert_eq!( + block_import.import_block(block(), HashMap::new()).unwrap(), + ImportResult::Imported(ImportedAux { needs_justification: true, clear_justification_requests: false, bad_justification: true }), ); assert_eq!( - block_import.import_block(block(), None).unwrap(), + block_import.import_block(block(), HashMap::new()).unwrap(), ImportResult::AlreadyInChain ); } diff --git a/core/finality-grandpa/src/until_imported.rs b/core/finality-grandpa/src/until_imported.rs index 3d68e8cd848166c2db17bf7185648fbbb0e2dcd1..4b867c18c8e2bea8f0ca2e02db34a2fd5eaf75a2 100644 --- a/core/finality-grandpa/src/until_imported.rs +++ b/core/finality-grandpa/src/until_imported.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -28,7 +28,7 @@ use futures::prelude::*; use futures::stream::Fuse; use parking_lot::Mutex; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use substrate_primitives::Ed25519AuthorityId; +use substrate_primitives::ed25519::Public as AuthorityId; use tokio::timer::Interval; use std::collections::{HashMap, VecDeque}; @@ -199,7 +199,7 @@ impl Stream for UntilImported } } -fn warn_authority_wrong_target(hash: H, id: Ed25519AuthorityId) { +fn warn_authority_wrong_target(hash: H, id: AuthorityId) { warn!( target: "afg", "Authority {:?} signed GRANDPA message with \ diff --git a/core/inherents/Cargo.toml b/core/inherents/Cargo.toml index 2ea3c69a76a3ee9fa9b13a44eb166b7fbae3dfbc..d3292095cc5f405a388ab1aab179cf8057030057 100644 --- a/core/inherents/Cargo.toml +++ b/core/inherents/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] parking_lot = { version = "0.7", optional = true } rstd = { package = "sr-std", path = "../sr-std", default-features = false } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } [features] diff --git a/core/inherents/src/lib.rs b/core/inherents/src/lib.rs index 4f9c8b8006e4bd739c2599706490e81f397b2deb..7d2324bc933cdaeb5ab6d0b3f6a8d7579ec385b4 100644 --- a/core/inherents/src/lib.rs +++ b/core/inherents/src/lib.rs @@ -31,6 +31,7 @@ //! information on how that is done. #![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] use parity_codec as codec; use codec::{Encode, Decode}; @@ -43,6 +44,9 @@ use parking_lot::RwLock; #[cfg(feature = "std")] use std::{sync::Arc, format}; +#[cfg(feature = "std")] +pub mod pool; + pub use runtime_primitives::RuntimeString; /// An identifier for an inherent. @@ -399,7 +403,7 @@ pub trait ProvideInherent { fn create_inherent(data: &InherentData) -> Option; /// Check the given inherent if it is valid. - /// Checking the inherent is optional and can be ommitted. + /// Checking the inherent is optional and can be omitted. fn check_inherent(_: &Self::Call, _: &InherentData) -> Result<(), Self::Error> { Ok(()) } diff --git a/core/inherents/src/pool.rs b/core/inherents/src/pool.rs new file mode 100644 index 0000000000000000000000000000000000000000..2c7e953696a55ab9d134615a2371bbc48f902628 --- /dev/null +++ b/core/inherents/src/pool.rs @@ -0,0 +1,75 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Inherents Pool + +use std::{fmt, mem, vec}; +use parking_lot::Mutex; + +/// Inherents Pool +/// +/// The pool is responsible to collect inherents asynchronously generated +/// by some other parts of the code and make them ready for the next block production. +pub struct InherentsPool { + data: Mutex>, +} + +impl Default for InherentsPool { + fn default() -> Self { + InherentsPool { + data: Default::default(), + } + } +} + +impl fmt::Debug for InherentsPool { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut builder = fmt.debug_struct("InherentsPool"); + if let Some(data) = self.data.try_lock() { + builder.field("data", &*data); + } + builder.finish() + } +} + +impl InherentsPool { + /// Add inherent extrinsic to the pool. + /// + /// This inherent will be appended to the next produced block. + pub fn add(&self, extrinsic: T) { + self.data.lock().push(extrinsic); + } + + /// Drain all currently queued inherents. + pub fn drain(&self) -> Vec { + mem::replace(&mut *self.data.lock(), vec![]) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_drain_inherents_to_given_data() { + let pool = InherentsPool::default(); + pool.add(5); + pool.add(7); + + assert_eq!(pool.drain(), vec![5, 7]); + assert_eq!(pool.drain(), vec![]); + } +} diff --git a/core/keyring/Cargo.toml b/core/keyring/Cargo.toml index e3203742473e4a3c2cf66d8ccbcd00d88f00d1dc..db480744b74faa0fc306095a8a0d0223900d25a1 100644 --- a/core/keyring/Cargo.toml +++ b/core/keyring/Cargo.toml @@ -8,3 +8,5 @@ edition = "2018" substrate-primitives = { path = "../primitives" } hex-literal = { version = "0.1.0" } lazy_static = { version = "1.0" } +strum = "0.14.0" +strum_macros = "0.14.0" diff --git a/core/keyring/src/ed25519.rs b/core/keyring/src/ed25519.rs index 267da3995cdaf2263328e249681ee11feeb8502c..f36d8fd4853e97b7ac541f7acb1acf5fcc6adca6 100644 --- a/core/keyring/src/ed25519.rs +++ b/core/keyring/src/ed25519.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,15 +16,13 @@ //! Support code for the runtime. A set of test accounts. -use std::collections::HashMap; -use std::ops::Deref; +use std::{collections::HashMap, ops::Deref}; use lazy_static::lazy_static; -use hex_literal::{hex, hex_impl}; -use substrate_primitives::ed25519::{Pair, Public, Signature}; +use substrate_primitives::{ed25519::{Pair, Public, Signature}, Pair as PairT, H256}; pub use substrate_primitives::ed25519; /// Set of test accounts. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum_macros::Display, strum_macros::EnumIter)] pub enum Keyring { Alice, Bob, @@ -37,7 +35,7 @@ pub enum Keyring { } impl Keyring { - pub fn from_public(who: Public) -> Option { + pub fn from_public(who: &Public) -> Option { [ Keyring::Alice, Keyring::Bob, @@ -49,17 +47,25 @@ impl Keyring { Keyring::Two, ].iter() .map(|i| *i) - .find(|&k| Public::from(k) == who) + .find(|&k| &Public::from(k) == who) } pub fn from_raw_public(who: [u8; 32]) -> Option { - Self::from_public(Public::from_raw(who)) + Self::from_public(&Public::from_raw(who)) } pub fn to_raw_public(self) -> [u8; 32] { *Public::from(self).as_array_ref() } + pub fn from_h256_public(who: H256) -> Option { + Self::from_public(&Public::from_raw(who.into())) + } + + pub fn to_h256_public(self) -> H256 { + Public::from(self).as_array_ref().into() + } + pub fn to_raw_public_vec(self) -> Vec { Public::from(self).to_raw_vec() } @@ -69,16 +75,13 @@ impl Keyring { } pub fn pair(self) -> Pair { - match self { - Keyring::Alice => Pair::from_seed(b"Alice "), - Keyring::Bob => Pair::from_seed(b"Bob "), - Keyring::Charlie => Pair::from_seed(b"Charlie "), - Keyring::Dave => Pair::from_seed(b"Dave "), - Keyring::Eve => Pair::from_seed(b"Eve "), - Keyring::Ferdie => Pair::from_seed(b"Ferdie "), - Keyring::One => Pair::from_seed(b"12345678901234567890123456789012"), - Keyring::Two => Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")), - } + Pair::from_string(&format!("//{}", <&'static str>::from(self)), None) + .expect("static values are known good; qed") + } + + /// Returns an interator over all test accounts. + pub fn iter() -> impl Iterator { + ::iter() } } @@ -91,24 +94,15 @@ impl From for &'static str { Keyring::Dave => "Dave", Keyring::Eve => "Eve", Keyring::Ferdie => "Ferdie", - Keyring::One => "one", - Keyring::Two => "two", + Keyring::One => "One", + Keyring::Two => "Two", } } } lazy_static! { static ref PRIVATE_KEYS: HashMap = { - [ - Keyring::Alice, - Keyring::Bob, - Keyring::Charlie, - Keyring::Dave, - Keyring::Eve, - Keyring::Ferdie, - Keyring::One, - Keyring::Two, - ].iter().map(|&i| (i, i.pair())).collect() + Keyring::iter().map(|i| (i, i.pair())).collect() }; static ref PUBLIC_KEYS: HashMap = { @@ -134,6 +128,12 @@ impl From for [u8; 32] { } } +impl From for H256 { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref().into() + } +} + impl From for &'static [u8; 32] { fn from(k: Keyring) -> Self { (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() @@ -162,12 +162,12 @@ impl Deref for Keyring { #[cfg(test)] mod tests { use super::*; - use ed25519::Verifiable; + use substrate_primitives::{ed25519::Pair, Pair as PairT}; #[test] fn should_work() { - assert!(Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Bob!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Bob)); + assert!(Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Bob!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Bob)); } } diff --git a/core/keyring/src/lib.rs b/core/keyring/src/lib.rs index aa271d81891ba744c3119e86197f645bdfa0e907..5cf38401d0823f84a80054e9ccb9eb2d9bb8eba0 100644 --- a/core/keyring/src/lib.rs +++ b/core/keyring/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,7 +22,15 @@ pub mod sr25519; /// Test account crypto for ed25519. pub mod ed25519; -/// The Ed25519 keyring. -/// -/// This is deprecated: use `ed25519::Keyring` instead. -pub use ed25519::Keyring; +/// Convenience export: Sr25519's Keyring is exposed as `AccountKeyring`, +/// since it tends to be used for accounts. +pub use sr25519::Keyring as AccountKeyring; + +/// Convenience export: Ed25519's Keyring is exposed as `AuthorityKeyring`, +/// since it tends to be used for authorities (session keys &c.). +pub use ed25519::Keyring as AuthorityKeyring; + +pub mod test { + /// The keyring for use with accounts when using the test runtime. + pub use super::ed25519::Keyring as AccountKeyring; +} diff --git a/core/keyring/src/sr25519.rs b/core/keyring/src/sr25519.rs index 0142ab56f2232c6b2b34d68f04d8dc30d579f7a9..1d3342d86d1c4bc34fbda9c00802915b5a45eedf 100644 --- a/core/keyring/src/sr25519.rs +++ b/core/keyring/src/sr25519.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,8 +19,7 @@ use std::collections::HashMap; use std::ops::Deref; use lazy_static::lazy_static; -use hex_literal::{hex, hex_impl}; -use substrate_primitives::sr25519::{Pair, Public, Signature}; +use substrate_primitives::{sr25519::{Pair, Public, Signature}, Pair as PairT, H256}; pub use substrate_primitives::sr25519; /// Set of test accounts. @@ -37,7 +36,7 @@ pub enum Keyring { } impl Keyring { - pub fn from_public(who: Public) -> Option { + pub fn from_public(who: &Public) -> Option { [ Keyring::Alice, Keyring::Bob, @@ -49,17 +48,25 @@ impl Keyring { Keyring::Two, ].iter() .map(|i| *i) - .find(|&k| Public::from(k) == who) + .find(|&k| &Public::from(k) == who) } pub fn from_raw_public(who: [u8; 32]) -> Option { - Self::from_public(Public::from_raw(who)) + Self::from_public(&Public::from_raw(who)) } pub fn to_raw_public(self) -> [u8; 32] { *Public::from(self).as_array_ref() } + pub fn from_h256_public(who: H256) -> Option { + Self::from_public(&Public::from_raw(who.into())) + } + + pub fn to_h256_public(self) -> H256 { + Public::from(self).as_array_ref().into() + } + pub fn to_raw_public_vec(self) -> Vec { Public::from(self).to_raw_vec() } @@ -69,16 +76,8 @@ impl Keyring { } pub fn pair(self) -> Pair { - match self { - Keyring::Alice => Pair::from_seed(b"Alice "), - Keyring::Bob => Pair::from_seed(b"Bob "), - Keyring::Charlie => Pair::from_seed(b"Charlie "), - Keyring::Dave => Pair::from_seed(b"Dave "), - Keyring::Eve => Pair::from_seed(b"Eve "), - Keyring::Ferdie => Pair::from_seed(b"Ferdie "), - Keyring::One => Pair::from_seed(b"12345678901234567890123456789012"), - Keyring::Two => Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")), - } + Pair::from_string(&format!("//{}", <&'static str>::from(self)), None) + .expect("static values are known good; qed") } } @@ -91,8 +90,8 @@ impl From for &'static str { Keyring::Dave => "Dave", Keyring::Eve => "Eve", Keyring::Ferdie => "Ferdie", - Keyring::One => "one", - Keyring::Two => "two", + Keyring::One => "One", + Keyring::Two => "Two", } } } @@ -134,6 +133,12 @@ impl From for [u8; 32] { } } +impl From for H256 { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref().into() + } +} + impl From for &'static [u8; 32] { fn from(k: Keyring) -> Self { (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() @@ -162,12 +167,12 @@ impl Deref for Keyring { #[cfg(test)] mod tests { use super::*; - use sr25519::Verifiable; + use substrate_primitives::{sr25519::Pair, Pair as PairT}; #[test] fn should_work() { - assert!(Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Bob!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Bob)); + assert!(Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Bob!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Bob)); } } diff --git a/core/keystore/src/lib.rs b/core/keystore/src/lib.rs index 98bddb70742a89bca439be7a4243f3737985a8d7..59c1a65cfb1cd14317ab08dc41bfa5aec0ee300d 100644 --- a/core/keystore/src/lib.rs +++ b/core/keystore/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,13 +24,11 @@ use std::collections::HashMap; use std::path::PathBuf; use std::fs::{self, File}; use std::io::{self, Write}; -use std::num::NonZeroU32; -use serde_derive::{Serialize, Deserialize}; -use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, +use error_chain::{bail, error_chain, error_chain_processing, impl_error_chain_processed, impl_extract_backtrace, impl_error_chain_kind}; -use substrate_primitives::{hashing::blake2_256, ed25519::{Pair, Public, PKCS_LEN}}; +use substrate_primitives::{ed25519::{Pair, Public}, Pair as PairT}; pub use crypto::KEY_ITERATIONS; @@ -45,99 +43,21 @@ error_chain! { description("Invalid password"), display("Invalid password"), } - InvalidPKCS8 { - description("Invalid PKCS#8 data"), - display("Invalid PKCS#8 data"), + InvalidPhrase { + description("Invalid recovery phrase (BIP39) data"), + display("Invalid recovery phrase (BIP39) data"), } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct InvalidPassword; - -#[derive(Serialize, Deserialize)] -struct EncryptedKey { - mac: [u8; 32], - salt: [u8; 32], - ciphertext: Vec, // FIXME: switch to fixed-size when serde supports - iv: [u8; 16], - iterations: NonZeroU32, -} - -impl EncryptedKey { - fn encrypt(plain: &[u8; PKCS_LEN], password: &str, iterations: NonZeroU32) -> Self { - use rand::{Rng, rngs::OsRng}; - - let mut rng = OsRng::new().expect("OS Randomness available on all supported platforms; qed"); - - let salt: [u8; 32] = rng.gen(); - let iv: [u8; 16] = rng.gen(); - - // two parts of derived key - // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] - let (derived_left_bits, derived_right_bits) = crypto::derive_key_iterations(password.as_bytes(), &salt, iterations); - - // preallocated (on-stack in case of `Secret`) buffer to hold cipher - // length = length(plain) as we are using CTR-approach - let mut ciphertext = vec![0; PKCS_LEN]; - - // aes-128-ctr with initial vector of iv - crypto::aes::encrypt_128_ctr(&derived_left_bits, &iv, plain, &mut *ciphertext) - .expect("input lengths of key and iv are both 16; qed"); - - // Blake2_256(DK[16..31] ++ ), where DK[16..31] - derived_right_bits - let mac = blake2_256(&crypto::derive_mac(&derived_right_bits, &*ciphertext)); - - EncryptedKey { - salt, - iv, - mac, - iterations, - ciphertext, - } - } - - fn decrypt(&self, password: &str) -> Result<[u8; PKCS_LEN]> { - let (derived_left_bits, derived_right_bits) = - crypto::derive_key_iterations(password.as_bytes(), &self.salt, self.iterations); - - let mac = blake2_256(&crypto::derive_mac(&derived_right_bits, &self.ciphertext)); - - if subtle::ConstantTimeEq::ct_eq(&mac[..], &self.mac[..]).unwrap_u8() != 1 { - return Err(ErrorKind::InvalidPassword.into()); + InvalidSeed { + description("Invalid seed"), + display("Invalid seed"), } - - let mut plain = [0; PKCS_LEN]; - crypto::aes::decrypt_128_ctr(&derived_left_bits, &self.iv, &self.ciphertext, &mut plain[..]) - .expect("input lengths of key and iv are both 16; qed"); - Ok(plain) } } -type Seed = [u8; 32]; - /// Key store. pub struct Store { path: PathBuf, - additional: HashMap, -} - -pub fn pad_seed(seed: &str) -> Seed { - let mut s: [u8; 32] = [' ' as u8; 32]; - - let was_hex = if seed.len() == 66 && &seed[0..2] == "0x" { - if let Ok(d) = hex::decode(&seed[2..]) { - s.copy_from_slice(&d); - true - } else { false } - } else { false }; - - if !was_hex { - let len = ::std::cmp::min(32, seed.len()); - &mut s[..len].copy_from_slice(&seed.as_bytes()[..len]); - } - - s + additional: HashMap, } impl Store { @@ -149,44 +69,36 @@ impl Store { /// Generate a new key, placing it into the store. pub fn generate(&self, password: &str) -> Result { - let (pair, pkcs_bytes) = Pair::generate_with_pkcs8(); - let key_file = EncryptedKey::encrypt( - &pkcs_bytes, - password, - NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") - ); - + let (pair, phrase) = Pair::generate_with_phrase(Some(password)); let mut file = File::create(self.key_file_path(&pair.public()))?; - ::serde_json::to_writer(&file, &key_file)?; - + ::serde_json::to_writer(&file, &phrase)?; file.flush()?; - Ok(pair) } /// Create a new key from seed. Do not place it into the store. - /// Only the first 32 bytes of the sead are used. This is meant to be used for testing only. - // FIXME: remove this - https://github.com/paritytech/substrate/issues/1063 pub fn generate_from_seed(&mut self, seed: &str) -> Result { - let padded_seed = pad_seed(seed); - let pair = Pair::from_seed(&padded_seed); - self.additional.insert(pair.public(), padded_seed); + let pair = Pair::from_string(seed, None) + .map_err(|_| Error::from(ErrorKind::InvalidSeed))?; + self.additional.insert(pair.public(), pair.clone()); Ok(pair) } /// Load a key file with given public key. pub fn load(&self, public: &Public, password: &str) -> Result { - if let Some(ref seed) = self.additional.get(public) { - let pair = Pair::from_seed(seed); - return Ok(pair); + if let Some(pair) = self.additional.get(public) { + return Ok(pair.clone()); } let path = self.key_file_path(public); let file = File::open(path)?; - let encrypted_key: EncryptedKey = ::serde_json::from_reader(&file)?; - let pkcs_bytes = encrypted_key.decrypt(password)?; - - Pair::from_pkcs8(&pkcs_bytes[..]).map_err(|_| ErrorKind::InvalidPKCS8.into()) + let phrase: String = ::serde_json::from_reader(&file)?; + let pair = Pair::from_phrase(&phrase, Some(password)) + .map_err(|_| Error::from(ErrorKind::InvalidPhrase))?; + if &pair.public() != public { + bail!(ErrorKind::InvalidPassword); + } + Ok(pair) } /// Get public keys of all stored keys. @@ -227,42 +139,6 @@ mod tests { use super::*; use tempdir::TempDir; - #[test] - fn encrypt_and_decrypt() { - let plain = [1; PKCS_LEN]; - let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED")); - - let decrypted_key = encrypted_key.decrypt("thepassword").unwrap(); - - assert_eq!(&plain[..], &decrypted_key[..]); - } - - #[test] - fn decrypt_wrong_password_fails() { - let plain = [1; PKCS_LEN]; - let encrypted_key = EncryptedKey::encrypt( - &plain, - "thepassword", - NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") - ); - - assert!(encrypted_key.decrypt("thepassword2").is_err()); - } - - #[test] - fn decrypt_wrong_iterations_fails() { - let plain = [1; PKCS_LEN]; - let mut encrypted_key = EncryptedKey::encrypt( - &plain, - "thepassword", - NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") - ); - - encrypted_key.iterations = NonZeroU32::new(encrypted_key.iterations.get() - 64).unwrap(); - - assert!(encrypted_key.decrypt("thepassword").is_err()); - } - #[test] fn basic_store() { let temp_dir = TempDir::new("keystore").unwrap(); @@ -285,16 +161,7 @@ mod tests { let temp_dir = TempDir::new("keystore").unwrap(); let mut store = Store::open(temp_dir.path().to_owned()).unwrap(); - let pair = store.generate_from_seed("0x1").unwrap(); - assert_eq!("5GqhgbUd2S9uc5Tm7hWhw29Tw2jBnuHshmTV1fDF4V1w3G2z", pair.public().to_ss58check()); - let pair = store.generate_from_seed("0x3d97c819d68f9bafa7d6e79cb991eebcd77d966c5334c0b94d9e1fa7ad0869dc").unwrap(); assert_eq!("5DKUrgFqCPV8iAXx9sjy1nyBygQCeiUYRFWurZGhnrn3HBL8", pair.public().to_ss58check()); - - let pair = store.generate_from_seed("12345678901234567890123456789022").unwrap(); - assert_eq!("5DscZvfjnM5im7oKRXXP9xtCG1SEwfMb8J5eGLmw5EHhoHR3", pair.public().to_ss58check()); - - let pair = store.generate_from_seed("1").unwrap(); - assert_eq!("5DYnksEZFc7kgtfyNM1xK2eBtW142gZ3Ho3NQubrF2S6B2fq", pair.public().to_ss58check()); } } diff --git a/core/network-libp2p/Cargo.toml b/core/network-libp2p/Cargo.toml index ab784ac9783fc8bdd2bad8d52203c5a9c252304c..689a1b4a6aa117c74216277eb5de81f31fc41a82 100644 --- a/core/network-libp2p/Cargo.toml +++ b/core/network-libp2p/Cargo.toml @@ -13,7 +13,7 @@ bytes = "0.4" error-chain = { version = "0.12", default-features = false } fnv = "1.0" futures = "0.1" -libp2p = { version = "0.4.0", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] } +libp2p = { version = "0.6.0", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] } parking_lot = "0.7.1" lazy_static = "1.2" log = "0.4" @@ -22,8 +22,13 @@ serde = "1.0.70" serde_derive = "1.0.70" serde_json = "1.0.24" smallvec = "0.6" +substrate-peerset = { path = "../peerset" } tokio = "0.1" tokio-io = "0.1" tokio-timer = "0.2" unsigned-varint = { version = "0.2.1", features = ["codec"] } void = "1.0" + +[dev-dependencies] +tempdir = "0.3" + diff --git a/core/network-libp2p/src/behaviour.rs b/core/network-libp2p/src/behaviour.rs index ba79e0ef3207bde049f185cb4f582fc4c7f61218..f93665ce765ce8d8cf0cc4b34c210fbe3774514f 100644 --- a/core/network-libp2p/src/behaviour.rs +++ b/core/network-libp2p/src/behaviour.rs @@ -14,18 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::custom_proto::{CustomProtos, CustomProtosOut, RegisteredProtocols}; -use crate::{NetworkConfiguration, ProtocolId}; +use crate::custom_proto::{CustomProto, CustomProtoOut, RegisteredProtocol}; use futures::prelude::*; use libp2p::NetworkBehaviour; use libp2p::core::{Multiaddr, PeerId, ProtocolsHandler, PublicKey}; use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction}; use libp2p::core::swarm::{NetworkBehaviourEventProcess, PollParameters}; +use libp2p::core::swarm::toggle::Toggle; use libp2p::identify::{Identify, IdentifyEvent, protocol::IdentifyInfo}; -use libp2p::kad::{Kademlia, KademliaOut, KadConnectionType}; +use libp2p::kad::{Kademlia, KademliaOut}; +use libp2p::mdns::{Mdns, MdnsEvent}; use libp2p::ping::{Ping, PingEvent}; use log::{debug, trace, warn}; -use std::{cmp, io, time::Duration, time::Instant}; +use std::{cmp, io, fmt, time::Duration, time::Instant}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_timer::Delay; use void; @@ -37,11 +38,13 @@ pub struct Behaviour { /// Periodically ping nodes, and close the connection if it's unresponsive. ping: Ping, /// Custom protocols (dot, bbq, sub, etc.). - custom_protocols: CustomProtos, + custom_protocols: CustomProto, /// Discovers nodes of the network. Defined below. discovery: DiscoveryBehaviour, /// Periodically identifies the remote and responds to incoming requests. identify: Identify, + /// Discovers nodes on the local network. + mdns: Toggle>, /// Queue of events to produce for the outside. #[behaviour(ignore)] @@ -50,98 +53,65 @@ pub struct Behaviour { impl Behaviour { /// Builds a new `Behaviour`. - // TODO: redundancy between config and local_public_key (https://github.com/libp2p/rust-libp2p/issues/745) - pub fn new(config: &NetworkConfiguration, local_public_key: PublicKey, protocols: RegisteredProtocols) -> Self { + pub fn new( + user_agent: String, + local_public_key: PublicKey, + protocol: RegisteredProtocol, + known_addresses: Vec<(PeerId, Multiaddr)>, + peerset: substrate_peerset::PeersetMut, + enable_mdns: bool, + ) -> Self { let identify = { let proto_version = "/substrate/1.0".to_string(); - let user_agent = format!("{} ({})", config.client_version, config.node_name); Identify::new(proto_version, user_agent, local_public_key.clone()) }; - let local_peer_id = local_public_key.into_peer_id(); - let custom_protocols = CustomProtos::new(config, &local_peer_id, protocols); + let custom_protocols = CustomProto::new(protocol, peerset); + + let mut kademlia = Kademlia::new(local_public_key.into_peer_id()); + for (peer_id, addr) in &known_addresses { + kademlia.add_connected_address(peer_id, addr.clone()); + } Behaviour { ping: Ping::new(), custom_protocols, - discovery: DiscoveryBehaviour::new(local_peer_id), + discovery: DiscoveryBehaviour { + user_defined: known_addresses, + kademlia, + next_kad_random_query: Delay::new(Instant::now()), + duration_to_next_kad: Duration::from_secs(1), + }, identify, + mdns: if enable_mdns { + match Mdns::new() { + Ok(mdns) => Some(mdns).into(), + Err(err) => { + warn!(target: "sub-libp2p", "Failed to initialize mDNS: {:?}", err); + None.into() + } + } + } else { + None.into() + }, events: Vec::new(), } } - /// Sends a message to a peer using the given custom protocol. + /// Sends a message to a peer. /// /// Has no effect if the custom protocol is not open with the given peer. /// /// Also note that even we have a valid open substream, it may in fact be already closed /// without us knowing, in which case the packet will not be received. #[inline] - pub fn send_custom_message(&mut self, target: &PeerId, protocol_id: ProtocolId, data: TMessage) { - self.custom_protocols.send_packet(target, protocol_id, data) - } - - /// Returns the number of peers in the topology. - pub fn num_topology_peers(&self) -> usize { - self.custom_protocols.num_topology_peers() - } - - /// Flushes the topology to the disk. - pub fn flush_topology(&mut self) -> Result<(), io::Error> { - self.custom_protocols.flush_topology() - } - - /// Perform a cleanup pass, removing all obsolete addresses and peers. - /// - /// This should be done from time to time. - pub fn cleanup(&mut self) { - self.custom_protocols.cleanup(); - } - - /// Returns the list of reserved nodes. - pub fn reserved_peers(&self) -> impl Iterator { - self.custom_protocols.reserved_peers() - } - - /// Try to add a reserved peer. - pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) { - self.custom_protocols.add_reserved_peer(peer_id, addr) - } - - /// Try to remove a reserved peer. - /// - /// If we are in reserved mode and we were connected to a node with this peer ID, then this - /// method will disconnect it and return its index. - pub fn remove_reserved_peer(&mut self, peer_id: PeerId) { - self.custom_protocols.remove_reserved_peer(peer_id) - } - - /// Returns true if we only accept reserved nodes. - pub fn is_reserved_only(&self) -> bool { - self.custom_protocols.is_reserved_only() - } - - /// Start accepting all peers again if we weren't. - pub fn accept_unreserved_peers(&mut self) { - self.custom_protocols.accept_unreserved_peers() - } - - /// Start refusing non-reserved nodes. Returns the list of nodes that have been disconnected. - pub fn deny_unreserved_peers(&mut self) { - self.custom_protocols.deny_unreserved_peers() - } - - /// Disconnects a peer and bans it for a little while. - /// - /// Same as `drop_node`, except that the same peer will not be able to reconnect later. - #[inline] - pub fn ban_node(&mut self, peer_id: PeerId) { - self.custom_protocols.ban_peer(peer_id) + pub fn send_custom_message(&mut self, target: &PeerId, data: TMessage) { + self.custom_protocols.send_packet(target, data) } - /// Returns a list of all the peers that are banned, and until when. - pub fn banned_nodes(&self) -> impl Iterator { - self.custom_protocols.banned_peers() + /// Returns the list of nodes that we know exist in the network. + pub fn known_peers(&self) -> impl Iterator { + self.discovery.kademlia.kbuckets_entries() } /// Returns true if we try to open protocols with the given peer. @@ -149,9 +119,16 @@ impl Behaviour { self.custom_protocols.is_enabled(peer_id) } - /// Returns the list of protocols we have open with the given peer. - pub fn open_protocols<'a>(&'a self, peer_id: &'a PeerId) -> impl Iterator + 'a { - self.custom_protocols.open_protocols(peer_id) + /// Returns true if we have an open protocol with the given peer. + pub fn is_open(&self, peer_id: &PeerId) -> bool { + self.custom_protocols.is_open(peer_id) + } + + /// Adds a hard-coded address for the given peer, that never expires. + pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) { + if self.discovery.user_defined.iter().all(|(p, a)| *p != peer_id && *a != addr) { + self.discovery.user_defined.push((peer_id, addr)); + } } /// Disconnects the custom protocols from a peer. @@ -168,14 +145,9 @@ impl Behaviour { self.custom_protocols.disconnect_peer(peer_id) } - /// Returns the list of peers in the topology. - pub fn known_peers(&self) -> impl Iterator { - self.custom_protocols.known_peers() - } - - /// Returns a list of addresses known for this peer, and their reputation score. - pub fn known_addresses(&mut self, peer_id: &PeerId) -> impl Iterator { - self.custom_protocols.known_addresses(peer_id) + /// Returns the state of the peerset manager, for debugging purposes. + pub fn peerset_debug_info(&self) -> serde_json::Value { + self.custom_protocols.peerset_debug_info() } } @@ -184,8 +156,6 @@ impl Behaviour { pub enum BehaviourOut { /// Opened a custom protocol with the remote. CustomProtocolOpen { - /// Identifier of the protocol. - protocol_id: ProtocolId, /// Version of the protocol that has been opened. version: u8, /// Id of the node we have opened a connection with. @@ -198,8 +168,6 @@ pub enum BehaviourOut { CustomProtocolClosed { /// Id of the peer we were connected to. peer_id: PeerId, - /// Identifier of the protocol. - protocol_id: ProtocolId, /// Reason why the substream closed. If `Ok`, then it's a graceful exit (EOF). result: io::Result<()>, }, @@ -208,8 +176,6 @@ pub enum BehaviourOut { CustomMessage { /// Id of the peer the message came from. peer_id: PeerId, - /// Protocol which generated the message. - protocol_id: ProtocolId, /// Message that has been received. message: TMessage, }, @@ -218,8 +184,6 @@ pub enum BehaviourOut { Clogged { /// Id of the peer the message came from. peer_id: PeerId, - /// Protocol which generated the message. - protocol_id: ProtocolId, /// Copy of the messages that are within the buffer, for further diagnostic. messages: Vec, }, @@ -241,20 +205,20 @@ pub enum BehaviourOut { }, } -impl From> for BehaviourOut { - fn from(other: CustomProtosOut) -> BehaviourOut { +impl From> for BehaviourOut { + fn from(other: CustomProtoOut) -> BehaviourOut { match other { - CustomProtosOut::CustomProtocolOpen { protocol_id, version, peer_id, endpoint } => { - BehaviourOut::CustomProtocolOpen { protocol_id, version, peer_id, endpoint } + CustomProtoOut::CustomProtocolOpen { version, peer_id, endpoint } => { + BehaviourOut::CustomProtocolOpen { version, peer_id, endpoint } } - CustomProtosOut::CustomProtocolClosed { protocol_id, peer_id, result } => { - BehaviourOut::CustomProtocolClosed { protocol_id, peer_id, result } + CustomProtoOut::CustomProtocolClosed { peer_id, result } => { + BehaviourOut::CustomProtocolClosed { peer_id, result } } - CustomProtosOut::CustomMessage { protocol_id, peer_id, message } => { - BehaviourOut::CustomMessage { protocol_id, peer_id, message } + CustomProtoOut::CustomMessage { peer_id, message } => { + BehaviourOut::CustomMessage { peer_id, message } } - CustomProtosOut::Clogged { protocol_id, peer_id, messages } => { - BehaviourOut::Clogged { protocol_id, peer_id, messages } + CustomProtoOut::Clogged { peer_id, messages } => { + BehaviourOut::Clogged { peer_id, messages } } } } @@ -266,8 +230,8 @@ impl NetworkBehaviourEventProcess for Behaviou } } -impl NetworkBehaviourEventProcess> for Behaviour { - fn inject_event(&mut self, event: CustomProtosOut) { +impl NetworkBehaviourEventProcess> for Behaviour { + fn inject_event(&mut self, event: CustomProtoOut) { self.events.push(event.into()); } } @@ -291,10 +255,7 @@ impl NetworkBehaviourEventProcess for Behav for addr in &info.listen_addrs { self.discovery.kademlia.add_connected_address(&peer_id, addr.clone()); } - self.custom_protocols.add_discovered_addrs( - &peer_id, - info.listen_addrs.iter().map(|addr| (addr.clone(), true)) - ); + self.custom_protocols.add_discovered_node(&peer_id); self.events.push(BehaviourOut::Identified { peer_id, info }); } IdentifyEvent::Error { .. } => {} @@ -309,17 +270,16 @@ impl NetworkBehaviourEventProcess for Behav impl NetworkBehaviourEventProcess for Behaviour { fn inject_event(&mut self, out: KademliaOut) { match out { - KademliaOut::Discovered { peer_id, addresses, ty } => { - self.custom_protocols.add_discovered_addrs( - &peer_id, - addresses.into_iter().map(|addr| (addr, ty == KadConnectionType::Connected)) - ); + KademliaOut::Discovered { .. } => {} + KademliaOut::KBucketAdded { peer_id, .. } => { + self.custom_protocols.add_discovered_node(&peer_id); } KademliaOut::FindNodeResult { key, closer_peers } => { - trace!(target: "sub-libp2p", "Kademlia query for {:?} yielded {:?} results", + trace!(target: "sub-libp2p", "Libp2p => Query for {:?} yielded {:?} results", key, closer_peers.len()); if closer_peers.is_empty() { - warn!(target: "sub-libp2p", "Kademlia random query has yielded empty results"); + warn!(target: "sub-libp2p", "Libp2p => Random Kademlia query has yielded empty \ + results"); } } // We never start any GET_PROVIDERS query. @@ -339,6 +299,19 @@ impl NetworkBehaviourEventProcess for Behaviour } } +impl NetworkBehaviourEventProcess for Behaviour { + fn inject_event(&mut self, event: MdnsEvent) { + match event { + MdnsEvent::Discovered(list) => { + for (peer_id, _) in list { + self.custom_protocols.add_discovered_node(&peer_id); + } + }, + MdnsEvent::Expired(_) => {} + } + } +} + impl Behaviour { fn poll(&mut self) -> Async>> { if !self.events.is_empty() { @@ -351,6 +324,9 @@ impl Behaviour { /// Implementation of `NetworkBehaviour` that discovers the nodes on the network. pub struct DiscoveryBehaviour { + /// User-defined list of nodes and their addresses. Typically includes bootstrap nodes and + /// reserved nodes. + user_defined: Vec<(PeerId, Multiaddr)>, /// Kademlia requests and answers. kademlia: Kademlia, /// Stream that fires when we need to perform the next random Kademlia query. @@ -359,16 +335,6 @@ pub struct DiscoveryBehaviour { duration_to_next_kad: Duration, } -impl DiscoveryBehaviour { - fn new(local_peer_id: PeerId) -> Self { - DiscoveryBehaviour { - kademlia: Kademlia::without_init(local_peer_id), - next_kad_random_query: Delay::new(Instant::now()), - duration_to_next_kad: Duration::from_secs(1), - } - } -} - impl NetworkBehaviour for DiscoveryBehaviour where TSubstream: AsyncRead + AsyncWrite, @@ -381,7 +347,21 @@ where } fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { - self.kademlia.addresses_of_peer(peer_id) + let mut list = self.user_defined.iter() + .filter_map(|(p, a)| if p == peer_id { Some(a.clone()) } else { None }) + .collect::>(); + list.extend(self.kademlia.addresses_of_peer(peer_id)); + trace!(target: "sub-libp2p", "Addresses of {:?} are {:?}", peer_id, list); + if list.is_empty() { + if self.kademlia.kbuckets_entries().any(|p| p == peer_id) { + debug!(target: "sub-libp2p", "Requested dialing to {:?} (peer in k-buckets), \ + and no address was found", peer_id); + } else { + debug!(target: "sub-libp2p", "Requested dialing to {:?} (peer not in k-buckets), \ + and no address was found", peer_id); + } + } + list } fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { @@ -425,8 +405,8 @@ where Ok(Async::NotReady) => break, Ok(Async::Ready(_)) => { let random_peer_id = PeerId::random(); - debug!(target: "sub-libp2p", "Starting random Kademlia request for {:?}", - random_peer_id); + debug!(target: "sub-libp2p", "Libp2p <= Starting random Kademlia request for \ + {:?}", random_peer_id); self.kademlia.find_node(random_peer_id); // Reset the `Delay` to the next random. @@ -435,7 +415,7 @@ where Duration::from_secs(60)); }, Err(err) => { - warn!(target: "sub-libp2p", "Kad query timer errored: {:?}", err); + warn!(target: "sub-libp2p", "Kademlia query timer errored: {:?}", err); break } } @@ -445,3 +425,26 @@ where } } +/// The severity of misbehaviour of a peer that is reported. +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Severity { + /// Peer is timing out. Could be bad connectivity of overload of work on either of our sides. + Timeout, + /// Peer has been notably useless. E.g. unable to answer a request that we might reasonably consider + /// it could answer. + Useless(String), + /// Peer has behaved in an invalid manner. This doesn't necessarily need to be Byzantine, but peer + /// must have taken concrete action in order to behave in such a way which is wantanly invalid. + Bad(String), +} + +impl fmt::Display for Severity { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self { + Severity::Timeout => write!(fmt, "Timeout"), + Severity::Useless(r) => write!(fmt, "Useless ({})", r), + Severity::Bad(r) => write!(fmt, "Bad ({})", r), + } + } +} + diff --git a/core/network-libp2p/src/config.rs b/core/network-libp2p/src/config.rs new file mode 100644 index 0000000000000000000000000000000000000000..74f928000547967c88e30ce53cf0335a5c40d33c --- /dev/null +++ b/core/network-libp2p/src/config.rs @@ -0,0 +1,290 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Libp2p network configuration. + +use libp2p::identity::{Keypair, secp256k1, ed25519}; +use libp2p::{Multiaddr, multiaddr::Protocol}; +use std::error::Error; +use std::{io::{self, Write}, iter, fs, net::Ipv4Addr, path::{Path, PathBuf}}; + +/// Network service configuration. +#[derive(Clone)] +pub struct NetworkConfiguration { + /// Directory path to store general network configuration. None means nothing will be saved. + pub config_path: Option, + /// Directory path to store network-specific configuration. None means nothing will be saved. + pub net_config_path: Option, + /// Multiaddresses to listen for incoming connections. + pub listen_addresses: Vec, + /// Multiaddresses to advertise. Detected automatically if empty. + pub public_addresses: Vec, + /// List of initial node addresses + pub boot_nodes: Vec, + /// The node key configuration, which determines the node's network identity keypair. + pub node_key: NodeKeyConfig, + /// Maximum allowed number of incoming connections. + pub in_peers: u32, + /// Number of outgoing connections we're trying to maintain. + pub out_peers: u32, + /// List of reserved node addresses. + pub reserved_nodes: Vec, + /// The non-reserved peer mode. + pub non_reserved_mode: NonReservedPeerMode, + /// Client identifier. Sent over the wire for debugging purposes. + pub client_version: String, + /// Name of the node. Sent over the wire for debugging purposes. + pub node_name: String, + /// If true, the network will use mDNS to discover other libp2p nodes on the local network + /// and connect to them if they support the same chain. + pub enable_mdns: bool, +} + +impl Default for NetworkConfiguration { + fn default() -> Self { + NetworkConfiguration { + config_path: None, + net_config_path: None, + listen_addresses: Vec::new(), + public_addresses: Vec::new(), + boot_nodes: Vec::new(), + node_key: NodeKeyConfig::Secp256k1(Secret::New), + in_peers: 25, + out_peers: 75, + reserved_nodes: Vec::new(), + non_reserved_mode: NonReservedPeerMode::Accept, + client_version: "unknown".into(), + node_name: "unknown".into(), + enable_mdns: false, + } + } +} + +impl NetworkConfiguration { + /// Create a new instance of default settings. + pub fn new() -> Self { + Self::default() + } + + /// Create new default configuration for localhost-only connection with random port (useful for testing) + pub fn new_local() -> NetworkConfiguration { + let mut config = NetworkConfiguration::new(); + config.listen_addresses = vec![ + iter::once(Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) + .chain(iter::once(Protocol::Tcp(0))) + .collect() + ]; + config + } +} + +/// The policy for connections to non-reserved peers. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum NonReservedPeerMode { + /// Accept them. This is the default. + Accept, + /// Deny them. + Deny, +} + +impl NonReservedPeerMode { + /// Attempt to parse the peer mode from a string. + pub fn parse(s: &str) -> Option { + match s { + "accept" => Some(NonReservedPeerMode::Accept), + "deny" => Some(NonReservedPeerMode::Deny), + _ => None, + } + } +} + +/// The configuration of a node's secret key, describing the type of key +/// and how it is obtained. A node's identity keypair is the result of +/// the evaluation of the node key configuration. +#[derive(Clone)] +pub enum NodeKeyConfig { + /// A Secp256k1 secret key configuration. + Secp256k1(Secret), + /// A Ed25519 secret key configuration. + Ed25519(Secret) +} + +/// The options for obtaining a Secp256k1 secret key. +pub type Secp256k1Secret = Secret; + +/// The options for obtaining a Ed25519 secret key. +pub type Ed25519Secret = Secret; + +/// The configuration options for obtaining a secret key `K`. +#[derive(Clone)] +pub enum Secret { + /// Use the given secret key `K`. + Input(K), + /// Read the secret key from a file. If the file does not exist, + /// it is created with a newly generated secret key `K`. The format + /// of the file is determined by `K`: + /// + /// * `secp256k1::SecretKey`: An unencoded 32 bytes Secp256k1 secret key. + /// * `ed25519::SecretKey`: An unencoded 32 bytes Ed25519 secret key. + File(PathBuf), + /// Always generate a new secret key `K`. + New +} + +impl NodeKeyConfig { + /// Evaluate a `NodeKeyConfig` to obtain an identity `Keypair`: + /// + /// * If the secret is configured as input, the corresponding keypair is returned. + /// + /// * If the secret is configured as a file, it is read from that file, if it exists. + /// Otherwise a new secret is generated and stored. In either case, the + /// keypair obtained from the secret is returned. + /// + /// * If the secret is configured to be new, it is generated and the corresponding + /// keypair is returned. + pub fn into_keypair(self) -> io::Result { + use NodeKeyConfig::*; + match self { + Secp256k1(Secret::New) => + Ok(Keypair::generate_secp256k1()), + + Secp256k1(Secret::Input(k)) => + Ok(Keypair::Secp256k1(k.into())), + + Secp256k1(Secret::File(f)) => + get_secret(f, + |mut b| secp256k1::SecretKey::from_bytes(&mut b), + secp256k1::SecretKey::generate) + .map(secp256k1::Keypair::from) + .map(Keypair::Secp256k1), + + Ed25519(Secret::New) => + Ok(Keypair::generate_ed25519()), + + Ed25519(Secret::Input(k)) => + Ok(Keypair::Ed25519(k.into())), + + Ed25519(Secret::File(f)) => + get_secret(f, + |mut b| ed25519::SecretKey::from_bytes(&mut b), + ed25519::SecretKey::generate) + .map(ed25519::Keypair::from) + .map(Keypair::Ed25519), + } + } +} + +/// Load a secret key from a file, if it exists, or generate a +/// new secret key and write it to that file. In either case, +/// the secret key is returned. +fn get_secret(file: P, parse: F, generate: G) -> io::Result +where + P: AsRef, + F: for<'r> FnOnce(&'r mut [u8]) -> Result, + G: FnOnce() -> K, + E: Error + Send + Sync + 'static, + K: AsRef<[u8]> +{ + std::fs::read(&file) + .and_then(|mut sk_bytes| + parse(&mut sk_bytes) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))) + .or_else(|e| { + if e.kind() == io::ErrorKind::NotFound { + file.as_ref().parent().map_or(Ok(()), fs::create_dir_all)?; + let sk = generate(); + write_secret_file(file, sk.as_ref())?; + Ok(sk) + } else { + Err(e) + } + }) +} + +/// Write secret bytes to a file. +fn write_secret_file

(path: P, sk_bytes: &[u8]) -> io::Result<()> +where + P: AsRef +{ + let mut file = open_secret_file(&path)?; + file.write_all(sk_bytes) +} + +/// Opens a file containing a secret key in write mode. +#[cfg(unix)] +fn open_secret_file

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

(path: P) -> Result +where + P: AsRef +{ + fs::OpenOptions::new() + .write(true) + .create_new(true) + .open(path) +} + +#[cfg(test)] +mod tests { + use super::*; + use tempdir::TempDir; + + fn secret_bytes(kp: &Keypair) -> Vec { + match kp { + Keypair::Ed25519(p) => p.secret().as_ref().iter().cloned().collect(), + Keypair::Secp256k1(p) => p.secret().as_ref().iter().cloned().collect(), + _ => panic!("Unexpected keypair.") + } + } + + #[test] + fn test_secret_file() { + let tmp = TempDir::new("x").unwrap(); + std::fs::remove_dir(tmp.path()).unwrap(); // should be recreated + let file = tmp.path().join("x").to_path_buf(); + let kp1 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap(); + let kp2 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap(); + assert!(file.is_file() && secret_bytes(&kp1) == secret_bytes(&kp2)) + } + + #[test] + fn test_secret_input() { + let sk = secp256k1::SecretKey::generate(); + let kp1 = NodeKeyConfig::Secp256k1(Secret::Input(sk.clone())).into_keypair().unwrap(); + let kp2 = NodeKeyConfig::Secp256k1(Secret::Input(sk)).into_keypair().unwrap(); + assert!(secret_bytes(&kp1) == secret_bytes(&kp2)); + } + + #[test] + fn test_secret_new() { + let kp1 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap(); + let kp2 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap(); + assert!(secret_bytes(&kp1) != secret_bytes(&kp2)); + } +} + diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs index 70787d89e1ef85ba18b65e855dce7956ff7d7589..eb60bb9ba4df9ae384959067f1335913ed3c4beb 100644 --- a/core/network-libp2p/src/custom_proto/behaviour.rs +++ b/core/network-libp2p/src/custom_proto/behaviour.rs @@ -14,81 +14,129 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::custom_proto::handler::{CustomProtosHandler, CustomProtosHandlerOut, CustomProtosHandlerIn}; -use crate::custom_proto::topology::NetTopology; -use crate::custom_proto::upgrade::{CustomMessage, RegisteredProtocols}; -use crate::{NetworkConfiguration, NonReservedPeerMode, ProtocolId}; -use crate::parse_str_addr; -use fnv::{FnvHashMap, FnvHashSet}; +use crate::custom_proto::handler::{CustomProtoHandlerProto, CustomProtoHandlerOut, CustomProtoHandlerIn}; +use crate::custom_proto::upgrade::{CustomMessage, RegisteredProtocol}; +use fnv::FnvHashMap; use futures::prelude::*; use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use libp2p::core::{protocols_handler::ProtocolsHandler, Endpoint, Multiaddr, PeerId}; -use log::{debug, trace, warn}; +use libp2p::core::{Multiaddr, PeerId}; +use log::{debug, error, trace, warn}; use smallvec::SmallVec; -use std::{cmp, error, io, marker::PhantomData, path::Path, time::Duration, time::Instant}; +use std::{collections::hash_map::Entry, cmp, error, io, marker::PhantomData, mem, time::Duration, time::Instant}; use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_timer::Delay; - -// File where the network topology is stored. -const NODES_FILE: &str = "nodes.json"; -// Duration during which a peer is disabled. -const PEER_DISABLE_DURATION: Duration = Duration::from_secs(5 * 60); /// Network behaviour that handles opening substreams for custom protocols with other nodes. -pub struct CustomProtos { +pub struct CustomProto { /// List of protocols to open with peers. Never modified. - registered_protocols: RegisteredProtocols, + protocol: RegisteredProtocol, - /// Topology of the network. - topology: NetTopology, + /// Receiver for instructions about who to connect to or disconnect from. + peerset: substrate_peerset::PeersetMut, - /// List of custom protocols that we have open with remotes. - open_protocols: Vec<(PeerId, ProtocolId)>, + /// List of peers in our state. + peers: FnvHashMap, - /// List of peer handlers that were enabled, and whether we're dialing or listening. - /// - /// Note that it is possible for a peer to be in the shutdown process, in which case it will - /// not be in this list but will be present in `open_protocols`. - /// It is also possible that we have *just* enabled a peer, in which case it will be in this - /// list but not in `open_protocols`. - enabled_peers: FnvHashMap, + /// List of incoming messages we have sent to the peer set manager and that are waiting for an + /// answer. + incoming: SmallVec<[IncomingPeer; 6]>, - /// Maximum number of incoming non-reserved connections, taken from the config. Never modified. - max_incoming_connections: usize, + /// We generate indices to identify incoming connections. This is the next value for the index + /// to use when a connection is incoming. + next_incoming_index: substrate_peerset::IncomingIndex, - /// Maximum number of outgoing non-reserved connections, taken from the config. Never modified. - max_outgoing_connections: usize, + /// Events to produce from `poll()`. + events: SmallVec<[NetworkBehaviourAction, CustomProtoOut>; 4]>, - /// If true, only reserved peers can connect. - reserved_only: bool, + /// Marker to pin the generics. + marker: PhantomData, +} - /// List of the IDs of the peers we are connected to. - connected_peers: FnvHashSet, +/// State of a peer we're connected to. +#[derive(Debug)] +enum PeerState { + /// State is poisoned. This is a temporary state for a peer and we should always switch back + /// to it later. If it is found in the wild, that means there was either a panic or a bug in + /// the state machine code. + Poisoned, + + /// The peer misbehaved. If the PSM wants us to connect to this node, we will add an artificial + /// delay to the connection. + Banned { + /// Until when the node is banned. + until: Instant, + }, - /// List of the IDs of the reserved peers. We always try to maintain a connection these peers. - reserved_peers: FnvHashSet, + /// The peerset requested that we connect to this peer. We are not connected to this node. + PendingRequest { + /// When to actually start dialing. + timer: tokio_timer::Delay, + }, - /// List of the IDs of peers that are forbidden, and the moment their ban expires. - banned_peers: Vec<(PeerId, Instant)>, + /// The peerset requested that we connect to this peer. We are currently dialing this peer. + Requested, + + /// We are connected to this peer but the peerset refused it. This peer can still perform + /// Kademlia queries and such, but should get disconnected in a few seconds. + Disabled { + /// How we are connected to this peer. + connected_point: ConnectedPoint, + /// If true, we still have a custom protocol open with it. It will likely get closed in + /// a short amount of time, but we need to keep the information in order to not have a + /// state mismatch. + open: bool, + /// If `Some`, the node is banned until the given `Instant`. + banned_until: Option, + }, - /// When this delay expires, we need to synchronize our active connectons with the - /// network topology. - next_connect_to_nodes: Delay, + /// We are connected to this peer but we are not opening any Substrate substream. The handler + /// will be enabled when `timer` fires. This peer can still perform Kademlia queries and such, + /// but should get disconnected in a few seconds. + DisabledPendingEnable { + /// How we are connected to this peer. + connected_point: ConnectedPoint, + /// If true, we still have a custom protocol open with it. It will likely get closed in + /// a short amount of time, but we need to keep the information in order to not have a + /// state mismatch. + open: bool, + /// When to enable this remote. + timer: tokio_timer::Delay, + }, - /// Events to produce from `poll()`. - events: SmallVec<[NetworkBehaviourAction, CustomProtosOut>; 4]>, + /// We are connected to this peer and the peerset has accepted it. The handler is in the + /// enabled state. + Enabled { + /// How we are connected to this peer. + connected_point: ConnectedPoint, + /// If true, we have a custom protocol open with this peer. + open: bool, + }, - /// Marker to pin the generics. - marker: PhantomData, + /// We are connected to this peer, and we sent an incoming message to the peerset. The handler + /// is in initialization mode. We are waiting for the Accept or Reject from the peerset. There + /// is a corresponding entry in `incoming`. + Incoming { + /// How we are connected to this peer. + connected_point: ConnectedPoint, + }, +} + +/// State of an "incoming" message sent to the peer set manager. +#[derive(Debug)] +struct IncomingPeer { + /// Id of the node that is concerned. + peer_id: PeerId, + /// If true, this "incoming" still corresponds to an actual connection. If false, then the + /// connection corresponding to it has been closed or replaced already. + alive: bool, + /// Id that the we sent to the peerset. + incoming_id: substrate_peerset::IncomingIndex, } -/// Event that can be emitted by the `CustomProtos`. +/// Event that can be emitted by the `CustomProto`. #[derive(Debug)] -pub enum CustomProtosOut { +pub enum CustomProtoOut { /// Opened a custom protocol with the remote. CustomProtocolOpen { - /// Identifier of the protocol. - protocol_id: ProtocolId, /// Version of the protocol that has been opened. version: u8, /// Id of the node we have opened a connection with. @@ -101,8 +149,6 @@ pub enum CustomProtosOut { CustomProtocolClosed { /// Id of the peer we were connected to. peer_id: PeerId, - /// Identifier of the protocol. - protocol_id: ProtocolId, /// Reason why the substream closed. If `Ok`, then it's a graceful exit (EOF). result: io::Result<()>, }, @@ -111,8 +157,6 @@ pub enum CustomProtosOut { CustomMessage { /// Id of the peer the message came from. peer_id: PeerId, - /// Protocol which generated the message. - protocol_id: ProtocolId, /// Message that has been received. message: TMessage, }, @@ -122,539 +166,747 @@ pub enum CustomProtosOut { Clogged { /// Id of the peer which is clogged. peer_id: PeerId, - /// Protocol which has a problem. - protocol_id: ProtocolId, /// Copy of the messages that are within the buffer, for further diagnostic. messages: Vec, }, } -impl CustomProtos { +impl CustomProto { /// Creates a `CustomProtos`. - pub fn new(config: &NetworkConfiguration, local_peer_id: &PeerId, registered_protocols: RegisteredProtocols) -> Self { - // Initialize the topology of the network. - let mut topology = if let Some(ref path) = config.net_config_path { - let path = Path::new(path).join(NODES_FILE); - debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); - NetTopology::from_file(local_peer_id.clone(), path) - } else { - debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved"); - NetTopology::memory(local_peer_id.clone()) - }; - - // Add the bootstrap nodes to the topology. - for bootnode in config.boot_nodes.iter() { - if let Ok((peer_id, addr)) = parse_str_addr(bootnode) { - topology.add_bootstrap_addr(&peer_id, addr.clone()); - } - } - - let max_incoming_connections = config.in_peers as usize; - let max_outgoing_connections = config.out_peers as usize; - - // Expected maximum number of connections. - let connec_cap = max_incoming_connections - .saturating_add(max_outgoing_connections) - .saturating_add(4); // We add an arbitrary number for reserved peers slots - - // Expected maximum number of substreams. - let open_protos_cap = connec_cap.saturating_mul(registered_protocols.len()); - - CustomProtos { - registered_protocols, - topology, - max_incoming_connections, - max_outgoing_connections, - reserved_only: config.non_reserved_mode == NonReservedPeerMode::Deny, - connected_peers: Default::default(), - reserved_peers: Default::default(), - banned_peers: Vec::new(), - open_protocols: Vec::with_capacity(open_protos_cap), - enabled_peers: FnvHashMap::with_capacity_and_hasher(connec_cap, Default::default()), - next_connect_to_nodes: Delay::new(Instant::now()), + pub fn new( + protocol: RegisteredProtocol, + peerset: substrate_peerset::PeersetMut, + ) -> Self { + CustomProto { + protocol, + peerset, + peers: FnvHashMap::default(), + incoming: SmallVec::new(), + next_incoming_index: substrate_peerset::IncomingIndex(0), events: SmallVec::new(), marker: PhantomData, } } - /// Returns the list of reserved nodes. - pub fn reserved_peers(&self) -> impl Iterator { - self.reserved_peers.iter() - } - - /// Adds a reserved peer. - pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) { - self.topology.add_bootstrap_addr(&peer_id, addr); - self.reserved_peers.insert(peer_id); - - // Trigger a `connect_to_nodes` round. - self.next_connect_to_nodes = Delay::new(Instant::now()); - } - - /// Removes a reserved peer. - /// - /// If we are in reserved mode and we were connected to a node with this peer ID, then this - /// method will disconnect it and return its index. - pub fn remove_reserved_peer(&mut self, peer_id: PeerId) { - self.reserved_peers.remove(&peer_id); - } - - /// Returns true if we only accept reserved nodes. - pub fn is_reserved_only(&self) -> bool { - self.reserved_only - } - - /// Start accepting all peers again if we weren't. - pub fn accept_unreserved_peers(&mut self) { - if !self.reserved_only { - return - } - - self.reserved_only = false; - // Trigger a `connect_to_nodes` round. - self.next_connect_to_nodes = Delay::new(Instant::now()); + /// Disconnects the given peer if we are connected to it. + pub fn disconnect_peer(&mut self, peer_id: &PeerId) { + debug!(target: "sub-libp2p", "Disconnecting {:?} by request from the external API", peer_id); + self.disconnect_peer_inner(peer_id, None); } - /// Start refusing non-reserved nodes. - pub fn deny_unreserved_peers(&mut self) { - if self.reserved_only { + /// Inner implementation of `disconnect_peer`. If `ban` is `Some`, we ban the node for the + /// specific duration. + fn disconnect_peer_inner(&mut self, peer_id: &PeerId, ban: Option) { + let mut entry = if let Entry::Occupied(entry) = self.peers.entry(peer_id.clone()) { + entry + } else { return - } - - self.reserved_only = true; - - // Disconnecting nodes that are connected to us and that aren't reserved - let reserved_peers = &mut self.reserved_peers; - let events = &mut self.events; - self.enabled_peers.retain(move |peer_id, _| { - if reserved_peers.contains(peer_id) { - return true - } - events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtosHandlerIn::Disable, - }); - false - }) - } - - /// Disconnects the given peer if we are connected to it. - pub fn disconnect_peer(&mut self, peer: &PeerId) { - if self.enabled_peers.remove(peer).is_some() { - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer.clone(), - event: CustomProtosHandlerIn::Disable, - }); - } - } + }; - /// Disconnects the given peer if we are connected to it and disables it for a little while. - pub fn ban_peer(&mut self, peer_id: PeerId) { - // Peer is already banned - if let Some(pos) = self.banned_peers.iter().position(|(p, _)| p == &peer_id) { - if self.banned_peers[pos].1 > Instant::now() { - return - } else { - self.banned_peers.remove(pos); - } - } + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + // We're not connected anyway. + st @ PeerState::Disabled { .. } => *entry.into_mut() = st, + st @ PeerState::Requested => *entry.into_mut() = st, + st @ PeerState::PendingRequest { .. } => *entry.into_mut() = st, + st @ PeerState::Banned { .. } => *entry.into_mut() = st, + + // DisabledPendingEnable => Disabled. + PeerState::DisabledPendingEnable { open, connected_point, timer } => { + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id); + let banned_until = Some(if let Some(ban) = ban { + cmp::max(timer.deadline(), Instant::now() + ban) + } else { + timer.deadline() + }); + *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until } + }, + + // Enabled => Disabled. + PeerState::Enabled { open, connected_point } => { + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtoHandlerIn::Disable, + }); + let banned_until = ban.map(|dur| Instant::now() + dur); + *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until } + }, + + // Incoming => Disabled. + PeerState::Incoming { connected_point, .. } => { + let inc = if let Some(inc) = self.incoming.iter_mut() + .find(|i| i.peer_id == *entry.key() && i.alive) { + inc + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in \ + incoming for incoming peer"); + return + }; - self.banned_peers.push((peer_id.clone(), Instant::now() + PEER_DISABLE_DURATION)); - if self.enabled_peers.remove(&peer_id).is_some() { - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id, - event: CustomProtosHandlerIn::Disable, - }); + inc.alive = false; + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtoHandlerIn::Disable, + }); + let banned_until = ban.map(|dur| Instant::now() + dur); + *entry.into_mut() = PeerState::Disabled { open: false, connected_point, banned_until } + }, + + PeerState::Poisoned => + error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), } } - /// Returns a list of all the peers that are banned, and until when. - pub fn banned_peers(&self) -> impl Iterator { - self.banned_peers.iter().map(|&(ref id, until)| (id, until)) - } - /// Returns true if we try to open protocols with the given peer. pub fn is_enabled(&self, peer_id: &PeerId) -> bool { - self.enabled_peers.contains_key(peer_id) + match self.peers.get(peer_id) { + None => false, + Some(PeerState::Disabled { .. }) => false, + Some(PeerState::DisabledPendingEnable { .. }) => false, + Some(PeerState::Enabled { .. }) => true, + Some(PeerState::Incoming { .. }) => false, + Some(PeerState::Requested) => false, + Some(PeerState::PendingRequest { .. }) => false, + Some(PeerState::Banned { .. }) => false, + Some(PeerState::Poisoned) => false, + } } - /// Returns the list of protocols we have open with the given peer. - pub fn open_protocols<'a>(&'a self, peer_id: &'a PeerId) -> impl Iterator + 'a { - self.open_protocols - .iter() - .filter(move |(p, _)| p == peer_id) - .map(|(_, proto)| *proto) + /// Returns true if we have opened a protocol with the given peer. + pub fn is_open(&self, peer_id: &PeerId) -> bool { + match self.peers.get(peer_id) { + None => false, + Some(PeerState::Disabled { open, .. }) => *open, + Some(PeerState::DisabledPendingEnable { open, .. }) => *open, + Some(PeerState::Enabled { open, .. }) => *open, + Some(PeerState::Incoming { .. }) => false, + Some(PeerState::Requested) => false, + Some(PeerState::PendingRequest { .. }) => false, + Some(PeerState::Banned { .. }) => false, + Some(PeerState::Poisoned) => false, + } } - /// Sends a message to a peer using the given custom protocol. + /// Sends a message to a peer. /// /// Has no effect if the custom protocol is not open with the given peer. /// /// Also note that even we have a valid open substream, it may in fact be already closed /// without us knowing, in which case the packet will not be received. - pub fn send_packet(&mut self, target: &PeerId, protocol_id: ProtocolId, message: TMessage) { + pub fn send_packet(&mut self, target: &PeerId, message: TMessage) { + if !self.is_open(target) { + return; + } + + trace!(target: "sub-libp2p", "Handler({:?}) <= Packet", target); self.events.push(NetworkBehaviourAction::SendEvent { peer_id: target.clone(), - event: CustomProtosHandlerIn::SendCustomMessage { - protocol: protocol_id, + event: CustomProtoHandlerIn::SendCustomMessage { message, } }); } - /// Indicates to the topology that we have discovered new addresses for a given node. - pub fn add_discovered_addrs( - &mut self, - peer_id: &PeerId, - addrs: I, - ) where I: Iterator { - if self.topology.add_discovered_addrs(peer_id, addrs) { - // Trigger a `connect_to_nodes` round. - self.next_connect_to_nodes = Delay::new(Instant::now()); - } + /// Indicates to the peerset that we have discovered new addresses for a given node. + pub fn add_discovered_node(&mut self, peer_id: &PeerId) { + debug!(target: "sub-libp2p", "PSM <= Discovered({:?})", peer_id); + self.peerset.discovered(peer_id.clone()) } - /// Returns the number of peers in the topology. - pub fn num_topology_peers(&self) -> usize { - self.topology.num_peers() + /// Returns the state of the peerset manager, for debugging purposes. + pub fn peerset_debug_info(&self) -> serde_json::Value { + self.peerset.debug_info() } - /// Flushes the topology to the disk. - pub fn flush_topology(&mut self) -> Result<(), io::Error> { - self.topology.flush_to_disk() - } + /// Function that is called when the peerset wants us to connect to a node. + fn peerset_report_connect(&mut self, peer_id: PeerId) { + let mut occ_entry = match self.peers.entry(peer_id) { + Entry::Occupied(entry) => entry, + Entry::Vacant(entry) => { + // If there's no entry in `self.peers`, start dialing. + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Starting to connect", entry.key()); + debug!(target: "sub-libp2p", "Libp2p <= Dial {:?}", entry.key()); + self.events.push(NetworkBehaviourAction::DialPeer { peer_id: entry.key().clone() }); + entry.insert(PeerState::Requested); + return; + } + }; - /// Perform a cleanup pass, removing all obsolete addresses and peers. - /// - /// This should be done from time to time. - pub fn cleanup(&mut self) { - self.topology.cleanup(); + match mem::replace(occ_entry.get_mut(), PeerState::Poisoned) { + PeerState::Banned { ref until } if *until > Instant::now() => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Will start to connect at \ + until {:?}", occ_entry.key(), until); + *occ_entry.into_mut() = PeerState::PendingRequest { + timer: tokio_timer::Delay::new(until.clone()), + }; + }, + + PeerState::Banned { .. } => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Starting to connect", occ_entry.key()); + debug!(target: "sub-libp2p", "Libp2p <= Dial {:?}", occ_entry.key()); + self.events.push(NetworkBehaviourAction::DialPeer { peer_id: occ_entry.key().clone() }); + *occ_entry.into_mut() = PeerState::Requested; + }, + + PeerState::Disabled { open, ref connected_point, banned_until: Some(ref banned) } + if *banned > Instant::now() => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Has idle connection through \ + {:?} but node is banned until {:?}", occ_entry.key(), connected_point, banned); + *occ_entry.into_mut() = PeerState::DisabledPendingEnable { + connected_point: connected_point.clone(), + open, + timer: tokio_timer::Delay::new(banned.clone()), + }; + }, + + PeerState::Disabled { open, connected_point, banned_until: _ } => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling previously-idle \ + connection through {:?}", occ_entry.key(), connected_point); + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: occ_entry.key().clone(), + event: CustomProtoHandlerIn::Enable(connected_point.clone().into()), + }); + *occ_entry.into_mut() = PeerState::Enabled { connected_point, open }; + }, + + PeerState::Incoming { connected_point, .. } => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling incoming \ + connection through {:?}", occ_entry.key(), connected_point); + if let Some(inc) = self.incoming.iter_mut() + .find(|i| i.peer_id == *occ_entry.key() && i.alive) { + inc.alive = false; + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in \ + incoming for incoming peer") + } + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: occ_entry.key().clone(), + event: CustomProtoHandlerIn::Enable(connected_point.clone().into()), + }); + *occ_entry.into_mut() = PeerState::Enabled { connected_point, open: false }; + }, + + st @ PeerState::Enabled { .. } => { + warn!(target: "sub-libp2p", "PSM => Connect({:?}): Already connected to this \ + peer", occ_entry.key()); + *occ_entry.into_mut() = st; + }, + st @ PeerState::DisabledPendingEnable { .. } => { + warn!(target: "sub-libp2p", "PSM => Connect({:?}): Already have an idle \ + connection to this peer and waiting to enable it", occ_entry.key()); + *occ_entry.into_mut() = st; + }, + st @ PeerState::Requested { .. } | st @ PeerState::PendingRequest { .. } => { + warn!(target: "sub-libp2p", "PSM => Connect({:?}): Received a previous \ + request for that peer", occ_entry.key()); + *occ_entry.into_mut() = st; + }, + + PeerState::Poisoned => + error!(target: "sub-libp2p", "State of {:?} is poisoned", occ_entry.key()), + } } - /// Returns the list of peers in the topology. - pub fn known_peers(&self) -> impl Iterator { - self.topology.known_peers() - } + /// Function that is called when the peerset wants us to disconnect from a node. + fn peerset_report_disconnect(&mut self, peer_id: PeerId) { + let mut entry = match self.peers.entry(peer_id) { + Entry::Occupied(entry) => entry, + Entry::Vacant(entry) => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Node already disabled", entry.key()); + return + } + }; - /// Returns a list of addresses known for this peer, and their reputation score. - pub fn known_addresses(&mut self, peer_id: &PeerId) -> impl Iterator { - self.topology.addresses_of_peer(peer_id, true) + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + st @ PeerState::Disabled { .. } | st @ PeerState::Banned { .. } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Node already disabled", entry.key()); + *entry.into_mut() = st; + }, + + PeerState::DisabledPendingEnable { open, connected_point, timer } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Interrupting pending \ + enable", entry.key()); + *entry.into_mut() = PeerState::Disabled { + open, + connected_point, + banned_until: Some(timer.deadline()), + }; + }, + + PeerState::Enabled { open, connected_point } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Disabling connection", entry.key()); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", entry.key()); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: entry.key().clone(), + event: CustomProtoHandlerIn::Disable, + }); + *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until: None } + }, + st @ PeerState::Incoming { .. } => { + error!(target: "sub-libp2p", "PSM => Drop({:?}): Was in incoming mode", + entry.key()); + *entry.into_mut() = st; + }, + PeerState::Requested => { + // We don't cancel dialing. Libp2p doesn't expose that on purpose, as other + // sub-systems (such as the discovery mechanism) may require dialing this node as + // well at the same time. + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Was not yet connected", entry.key()); + entry.remove(); + }, + PeerState::PendingRequest { timer } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Was not yet connected", entry.key()); + *entry.into_mut() = PeerState::Banned { until: timer.deadline() } + }, + + PeerState::Poisoned => + error!(target: "sub-libp2p", "State of {:?} is poisoned", entry.key()), + } } - /// Updates the attempted connections to nodes. - /// - /// Also updates `next_connect_to_nodes` with the earliest known moment when we need to - /// update connections again. - fn connect_to_nodes(&mut self, params: &mut PollParameters) { - // Make sure we are connected or connecting to all the reserved nodes. - for reserved in self.reserved_peers.iter() { - // TODO: don't generate an event if we're already in a pending connection (https://github.com/libp2p/rust-libp2p/issues/697) - if !self.enabled_peers.contains_key(&reserved) { - self.events.push(NetworkBehaviourAction::DialPeer { peer_id: reserved.clone() }); - } - } + /// Function that is called when the peerset wants us to accept an incoming node. + fn peerset_report_accept(&mut self, index: substrate_peerset::IncomingIndex) { + let incoming = if let Some(pos) = self.incoming.iter().position(|i| i.incoming_id == index) { + self.incoming.remove(pos) + } else { + error!(target: "sub-libp2p", "PSM => Accept({:?}): Invalid index", index); + return + }; - // We're done with reserved node; return early if there's nothing more to do. - if self.reserved_only { - // We set a timeout to 60 seconds for trying to connect again, however in practice - // a round will happen as soon as we fail to dial, disconnect from a node, allow - // unreserved nodes, and so on. - self.next_connect_to_nodes.reset(Instant::now() + Duration::from_secs(60)); + if !incoming.alive { + debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Obsolete incoming, + sending back dropped", index, incoming.peer_id); + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", incoming.peer_id); + self.peerset.dropped(&incoming.peer_id); return } - // Counter of number of connections to open, decreased when we open one. - let mut num_to_open = { - let num_outgoing_connections = self.enabled_peers - .iter() - .filter(|(_, endpoint)| endpoint.is_dialer()) - .filter(|(p, _)| !self.reserved_peers.contains(p)) - .count(); - self.max_outgoing_connections - num_outgoing_connections + let state = if let Some(state) = self.peers.get_mut(&incoming.peer_id) { + state + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in peers \ + corresponding to an alive incoming"); + return }; - trace!(target: "sub-libp2p", "Connect-to-nodes round; attempting to fill {:?} slots", - num_to_open); - - let local_peer_id = params.local_peer_id().clone(); - let (to_try, will_change) = self.topology.addrs_to_attempt(); - for (peer_id, _) in to_try { - if num_to_open == 0 { - break - } + let connected_point = if let PeerState::Incoming { connected_point } = state { + connected_point.clone() + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: entry in peers corresponding \ + to an alive incoming is not in incoming state"); + return + }; - if peer_id == &local_peer_id { - continue - } + debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Enabling connection \ + through {:?}", index, incoming.peer_id, connected_point); + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", incoming.peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: incoming.peer_id, + event: CustomProtoHandlerIn::Enable(connected_point.clone().into()), + }); - if self.connected_peers.contains(&peer_id) { - continue - } + *state = PeerState::Enabled { open: false, connected_point }; + } - if let Some((_, ban_end)) = self.banned_peers.iter().find(|(p, _)| p == peer_id) { - if *ban_end > Instant::now() { - continue - } - } + /// Function that is called when the peerset wants us to reject an incoming node. + fn peerset_report_reject(&mut self, index: substrate_peerset::IncomingIndex) { + let incoming = if let Some(pos) = self.incoming.iter().position(|i| i.incoming_id == index) { + self.incoming.remove(pos) + } else { + error!(target: "sub-libp2p", "PSM => Reject({:?}): Invalid index", index); + return + }; - num_to_open -= 1; - self.events.push(NetworkBehaviourAction::DialPeer { peer_id: peer_id.clone() }); + if !incoming.alive { + error!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Obsolete incoming, \ + ignoring", index, incoming.peer_id); + return } - // Next round is when we expect the topology will change. - self.next_connect_to_nodes.reset(cmp::min(will_change, Instant::now() + Duration::from_secs(60))); + let state = if let Some(state) = self.peers.get_mut(&incoming.peer_id) { + state + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in peers \ + corresponding to an alive incoming"); + return + }; + + let connected_point = if let PeerState::Incoming { connected_point } = state { + connected_point.clone() + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: entry in peers corresponding \ + to an alive incoming is not in incoming state"); + return + }; + + debug!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Rejecting connection through \ + {:?}", index, incoming.peer_id, connected_point); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", incoming.peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: incoming.peer_id, + event: CustomProtoHandlerIn::Disable, + }); + *state = PeerState::Disabled { open: false, connected_point, banned_until: None }; } } -impl NetworkBehaviour for CustomProtos +impl NetworkBehaviour for CustomProto where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage, { - type ProtocolsHandler = CustomProtosHandler; - type OutEvent = CustomProtosOut; + type ProtocolsHandler = CustomProtoHandlerProto; + type OutEvent = CustomProtoOut; fn new_handler(&mut self) -> Self::ProtocolsHandler { - CustomProtosHandler::new(self.registered_protocols.clone()) + CustomProtoHandlerProto::new(self.protocol.clone()) } - fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { - self.topology.addresses_of_peer(peer_id, false).map(|(a, _)| a.clone()).collect() + fn addresses_of_peer(&mut self, _: &PeerId) -> Vec { + Vec::new() } - fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { - // When a peer connects, its handler is initially in the disabled state. We make sure that - // the peer is allowed, and if so we put it in the enabled state. - - self.connected_peers.insert(peer_id.clone()); + fn inject_connected(&mut self, peer_id: PeerId, connected_point: ConnectedPoint) { + match (self.peers.entry(peer_id), connected_point) { + (Entry::Occupied(mut entry), connected_point) => { + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + PeerState::Requested | PeerState::PendingRequest { .. } | + PeerState::Banned { .. } => { + debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Connection \ + requested by PSM (through {:?})", entry.key(), connected_point); + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", entry.key()); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: entry.key().clone(), + event: CustomProtoHandlerIn::Enable(connected_point.clone().into()), + }); + *entry.into_mut() = PeerState::Enabled { open: false, connected_point }; + } + st @ _ => { + // This is a serious bug either in this state machine or in libp2p. + error!(target: "sub-libp2p", "Received inject_connected for \ + already-connected node; state is {:?}", st); + *entry.into_mut() = st; + return + } + } + } - let is_reserved = self.reserved_peers.contains(&peer_id); - if self.reserved_only && !is_reserved { - debug!(target: "sub-libp2p", "Ignoring {:?} because we're in reserved mode", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtosHandlerIn::Disable, - }); - return - } + (Entry::Vacant(entry), connected_point @ ConnectedPoint::Listener { .. }) => { + let incoming_id = self.next_incoming_index.clone(); + self.next_incoming_index.0 = match self.next_incoming_index.0.checked_add(1) { + Some(v) => v, + None => { + error!(target: "sub-libp2p", "Overflow in next_incoming_index"); + return + } + }; + debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Incoming connection", + entry.key()); + debug!(target: "sub-libp2p", "PSM <= Incoming({:?}, {:?}): Through {:?}", + incoming_id, entry.key(), connected_point); + self.peerset.incoming(entry.key().clone(), incoming_id); + self.incoming.push(IncomingPeer { + peer_id: entry.key().clone(), + alive: true, + incoming_id, + }); + entry.insert(PeerState::Incoming { connected_point }); + } - // Check whether peer is banned. - if !is_reserved { - if let Some((_, expire)) = self.banned_peers.iter().find(|(p, _)| p == &peer_id) { - if *expire >= Instant::now() { - debug!(target: "sub-libp2p", "Ignoring banned peer {:?}", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtosHandlerIn::Disable, - }); - return - } + (Entry::Vacant(entry), connected_point) => { + debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Requested by something \ + else than PSM, disabling", entry.key()); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", entry.key()); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: entry.key().clone(), + event: CustomProtoHandlerIn::Disable, + }); + entry.insert(PeerState::Disabled { open: false, connected_point, banned_until: None }); } } + } - // Check the limits on the ingoing and outgoing connections. - match endpoint { - ConnectedPoint::Dialer { .. } => { - let num_outgoing = self.enabled_peers.iter() - .filter(|(_, e)| e.is_dialer()) - .filter(|(p, _)| !self.reserved_peers.contains(p)) - .count(); - - debug_assert!(num_outgoing <= self.max_outgoing_connections); - if num_outgoing == self.max_outgoing_connections { - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtosHandlerIn::Disable, - }); - return + fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + match self.peers.remove(peer_id) { + None | Some(PeerState::Requested) | Some(PeerState::PendingRequest { .. }) | + Some(PeerState::Banned { .. }) => + // This is a serious bug either in this state machine or in libp2p. + error!(target: "sub-libp2p", "Received inject_disconnected for non-connected \ + node {:?}", peer_id), + + Some(PeerState::Disabled { open, banned_until, .. }) => { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \ + (through {:?})", peer_id, endpoint); + if let Some(until) = banned_until { + self.peers.insert(peer_id.clone(), PeerState::Banned { until }); } - } - ConnectedPoint::Listener { .. } => { - let num_ingoing = self.enabled_peers.iter() - .filter(|(_, e)| e.is_listener()) - .filter(|(p, _)| !self.reserved_peers.contains(p)) - .count(); - - debug_assert!(num_ingoing <= self.max_incoming_connections); - if num_ingoing == self.max_incoming_connections { - debug!(target: "sub-libp2p", "Ignoring incoming connection from {:?} because \ - we're full", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { + if open { + debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); + let event = CustomProtoOut::CustomProtocolClosed { peer_id: peer_id.clone(), - event: CustomProtosHandlerIn::Disable, - }); - return + result: Ok(()), + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); } } - } - // If everything is fine, enable the node. - debug_assert!(!self.enabled_peers.contains_key(&peer_id)); - // We ask the handler to actively open substreams only if we are the dialer; otherwise - // the two nodes will race to be the first to open the unique allowed substream. - if endpoint.is_dialer() { - trace!(target: "sub-libp2p", "Enabling custom protocols with {:?} (active)", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtosHandlerIn::Enable(Endpoint::Dialer), - }); - } else { - trace!(target: "sub-libp2p", "Enabling custom protocols with {:?} (passive)", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtosHandlerIn::Enable(Endpoint::Listener), - }); - } + Some(PeerState::DisabledPendingEnable { open, timer, .. }) => { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \ + (through {:?}) but pending enable", peer_id, endpoint); + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id); + self.peers.insert(peer_id.clone(), PeerState::Banned { until: timer.deadline() }); + if open { + debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); + let event = CustomProtoOut::CustomProtocolClosed { + peer_id: peer_id.clone(), + result: Ok(()), + }; - self.topology.set_connected(&peer_id, &endpoint); - self.enabled_peers.insert(peer_id, endpoint); - } + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + } - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { - let was_connected = self.connected_peers.remove(&peer_id); - debug_assert!(was_connected); + Some(PeerState::Enabled { open, .. }) => { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was enabled \ + (through {:?})", peer_id, endpoint); + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id); - self.topology.set_disconnected(peer_id, &endpoint); + if open { + debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); + let event = CustomProtoOut::CustomProtocolClosed { + peer_id: peer_id.clone(), + result: Ok(()), + }; - while let Some(pos) = self.open_protocols.iter().position(|(p, _)| p == peer_id) { - let (_, protocol_id) = self.open_protocols.remove(pos); + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + } - let event = CustomProtosOut::CustomProtocolClosed { - protocol_id, - peer_id: peer_id.clone(), - result: Ok(()), - }; + // In the incoming state, we don't report "Dropped". Instead we will just ignore the + // corresponding Accept/Reject. + Some(PeerState::Incoming { .. }) => { + if let Some(state) = self.incoming.iter_mut().find(|i| i.peer_id == *peer_id) { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was in incoming \ + mode (id {:?}, through {:?})", peer_id, state.incoming_id, endpoint); + state.alive = false; + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in incoming \ + corresponding to an incoming state in peers") + } + } - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + Some(PeerState::Poisoned) => + error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), } - - // Trigger a `connect_to_nodes` round. - self.next_connect_to_nodes = Delay::new(Instant::now()); - - self.enabled_peers.remove(peer_id); } - fn inject_dial_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn error::Error) { - if let Some(peer_id) = peer_id.as_ref() { - debug!(target: "sub-libp2p", "Failed to reach peer {:?} through {} => {:?}", peer_id, addr, error); - self.topology.set_unreachable(addr); + fn inject_addr_reach_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn error::Error) { + trace!(target: "sub-libp2p", "Libp2p => Reach failure for {:?} through {:?}: {:?}", peer_id, addr, error); + } - // Trigger a `connect_to_nodes` round. - self.next_connect_to_nodes = Delay::new(Instant::now()); + fn inject_dial_failure(&mut self, peer_id: &PeerId) { + if let Entry::Occupied(mut entry) = self.peers.entry(peer_id.clone()) { + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + // The node is not in our list. + st @ PeerState::Banned { .. } => { + trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); + *entry.into_mut() = st; + }, + + // "Basic" situation: we failed to reach a node that the peerset requested. + PeerState::Requested | PeerState::PendingRequest { .. } => { + debug!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); + *entry.into_mut() = PeerState::Banned { + until: Instant::now() + Duration::from_secs(5) + }; + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id) + }, + + // We can still get dial failures even if we are already connected to the node, + // as an extra diagnostic for an earlier attempt. + st @ PeerState::Disabled { .. } | st @ PeerState::Enabled { .. } | + st @ PeerState::DisabledPendingEnable { .. } | st @ PeerState::Incoming { .. } => { + debug!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); + *entry.into_mut() = st; + }, + + PeerState::Poisoned => + error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), + } } else { - // This code path is only reached if `peer_id` is None, which means that we dialed an - // address without knowing the `PeerId` to expect. We don't currently do that, except - // in one situation: for convenience, we accept bootstrap node addresses in the format - // `IP:PORT`. - // There is no reason this trigger a `connect_to_nodes` round in that situation. - debug!(target: "sub-libp2p", "Failed to reach {} => {:?}", addr, error); - self.topology.set_unreachable(addr); + // The node is not in our list. + trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); } } fn inject_node_event( &mut self, source: PeerId, - event: ::OutEvent, + event: CustomProtoHandlerOut, ) { match event { - CustomProtosHandlerOut::CustomProtocolClosed { protocol_id, result } => { - let pos = self.open_protocols.iter().position(|(s, p)| - s == &source && p == &protocol_id - ); - - if let Some(pos) = pos { - self.open_protocols.remove(pos); - } else { - debug_assert!(false, "Couldn't find protocol in open_protocols"); + CustomProtoHandlerOut::CustomProtocolClosed { result } => { + debug!(target: "sub-libp2p", "Handler({:?}) => Closed({:?})", source, result); + match self.peers.get_mut(&source) { + Some(PeerState::Enabled { ref mut open, .. }) if *open => + *open = false, + Some(PeerState::Disabled { ref mut open, .. }) if *open => + *open = false, + Some(PeerState::DisabledPendingEnable { ref mut open, .. }) if *open => + *open = false, + _ => error!(target: "sub-libp2p", "State mismatch in the custom protos handler"), } - let event = CustomProtosOut::CustomProtocolClosed { - protocol_id, + debug!(target: "sub-libp2p", "External API <= Closed({:?})", source); + let event = CustomProtoOut::CustomProtocolClosed { result, peer_id: source, }; self.events.push(NetworkBehaviourAction::GenerateEvent(event)); } - CustomProtosHandlerOut::CustomProtocolOpen { protocol_id, version } => { - debug_assert!(!self.open_protocols.iter().any(|(s, p)| - s == &source && p == &protocol_id - )); - self.open_protocols.push((source.clone(), protocol_id)); - - if let Some(address) = self.enabled_peers.get(&source) { - let event = CustomProtosOut::CustomProtocolOpen { - protocol_id, - version, - peer_id: source, - endpoint: address.clone() - }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } + CustomProtoHandlerOut::CustomProtocolOpen { version } => { + debug!(target: "sub-libp2p", "Handler({:?}) => Open: version {:?}", source, version); + let endpoint = match self.peers.get_mut(&source) { + Some(PeerState::Enabled { ref mut open, ref connected_point }) | + Some(PeerState::DisabledPendingEnable { ref mut open, ref connected_point, .. }) | + Some(PeerState::Disabled { ref mut open, ref connected_point, .. }) if !*open => { + *open = true; + connected_point.clone() + } + _ => { + error!(target: "sub-libp2p", "State mismatch in the custom protos handler"); + return + } + }; + + debug!(target: "sub-libp2p", "External API <= Open({:?})", source); + let event = CustomProtoOut::CustomProtocolOpen { + version, + peer_id: source, + endpoint, + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); } - CustomProtosHandlerOut::CustomMessage { protocol_id, message } => { - debug_assert!(self.open_protocols.iter().any(|(s, p)| - s == &source && p == &protocol_id - )); - let event = CustomProtosOut::CustomMessage { + + CustomProtoHandlerOut::CustomMessage { message } => { + debug_assert!(self.is_open(&source)); + trace!(target: "sub-libp2p", "Handler({:?}) => Message", source); + trace!(target: "sub-libp2p", "External API <= Message({:?})", source); + let event = CustomProtoOut::CustomMessage { peer_id: source, - protocol_id, message, }; self.events.push(NetworkBehaviourAction::GenerateEvent(event)); } - CustomProtosHandlerOut::Clogged { protocol_id, messages } => { - debug_assert!(self.open_protocols.iter().any(|(s, p)| - s == &source && p == &protocol_id - )); - warn!(target: "sub-libp2p", "Queue of packets to send to {:?} (protocol: {:?}) is \ - pretty large", source, protocol_id); - self.events.push(NetworkBehaviourAction::GenerateEvent(CustomProtosOut::Clogged { + + CustomProtoHandlerOut::Clogged { messages } => { + debug_assert!(self.is_open(&source)); + trace!(target: "sub-libp2p", "Handler({:?}) => Clogged", source); + trace!(target: "sub-libp2p", "External API <= Clogged({:?})", source); + warn!(target: "sub-libp2p", "Queue of packets to send to {:?} is \ + pretty large", source); + self.events.push(NetworkBehaviourAction::GenerateEvent(CustomProtoOut::Clogged { peer_id: source, - protocol_id, messages, })); } - CustomProtosHandlerOut::ProtocolError { protocol_id, error, is_severe } => { - if is_severe { - warn!(target: "sub-libp2p", "Network misbehaviour from {:?} with protocol \ - {:?}: {:?}", source, protocol_id, error); - self.ban_peer(source); - } else { - debug!(target: "sub-libp2p", "Network misbehaviour from {:?} with protocol \ - {:?}: {:?}", source, protocol_id, error); - } + + // Don't do anything for non-severe errors except report them. + CustomProtoHandlerOut::ProtocolError { is_severe, ref error } if !is_severe => { + debug!(target: "sub-libp2p", "Handler({:?}) => Benign protocol error: {:?}", + source, error) + } + + CustomProtoHandlerOut::ProtocolError { error, .. } => { + debug!(target: "sub-libp2p", "Handler({:?}) => Severe protocol error: {:?}", + source, error); + self.disconnect_peer_inner(&source, Some(Duration::from_secs(5))); } } } fn poll( &mut self, - params: &mut PollParameters, + _params: &mut PollParameters, ) -> Async< NetworkBehaviourAction< - ::InEvent, + CustomProtoHandlerIn, Self::OutEvent, >, > { + // Poll for instructions from the peerset. + // Note that the peerset is a *best effort* crate, and we have to use defensive programming. loop { - match self.next_connect_to_nodes.poll() { - Ok(Async::Ready(())) => self.connect_to_nodes(params), + match self.peerset.poll() { + Ok(Async::Ready(Some(substrate_peerset::Message::Accept(index)))) => { + self.peerset_report_accept(index); + } + Ok(Async::Ready(Some(substrate_peerset::Message::Reject(index)))) => { + self.peerset_report_reject(index); + } + Ok(Async::Ready(Some(substrate_peerset::Message::Connect(id)))) => { + self.peerset_report_connect(id); + } + Ok(Async::Ready(Some(substrate_peerset::Message::Drop(id)))) => { + self.peerset_report_disconnect(id); + } + Ok(Async::Ready(None)) => { + error!(target: "sub-libp2p", "Peerset receiver stream has returned None"); + break; + } Ok(Async::NotReady) => break, Err(err) => { - warn!(target: "sub-libp2p", "Connect-to-nodes timer errored: {:?}", err); + error!(target: "sub-libp2p", "Peerset receiver stream has errored: {:?}", err); break } } } - // Clean up `banned_peers` - self.banned_peers.retain(|(_, end)| *end > Instant::now()); - self.banned_peers.shrink_to_fit(); + for (peer_id, peer_state) in self.peers.iter_mut() { + match mem::replace(peer_state, PeerState::Poisoned) { + PeerState::PendingRequest { mut timer } => { + if let Ok(Async::NotReady) = timer.poll() { + *peer_state = PeerState::PendingRequest { timer }; + continue; + } + + debug!(target: "sub-libp2p", "Libp2p <= Dial {:?} now that ban has expired", peer_id); + self.events.push(NetworkBehaviourAction::DialPeer { peer_id: peer_id.clone() }); + *peer_state = PeerState::Requested; + } + + PeerState::DisabledPendingEnable { mut timer, connected_point, open } => { + if let Ok(Async::NotReady) = timer.poll() { + *peer_state = PeerState::DisabledPendingEnable { timer, connected_point, open }; + continue; + } + + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable now that ban has expired", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtoHandlerIn::Enable(connected_point.clone().into()), + }); + *peer_state = PeerState::Enabled { connected_point, open }; + } + + st @ _ => *peer_state = st, + } + } if !self.events.is_empty() { return Async::Ready(self.events.remove(0)) diff --git a/core/network-libp2p/src/custom_proto/handler.rs b/core/network-libp2p/src/custom_proto/handler.rs index d7b8da5f742fc425e1ef3569e8417c186b5f02ca..516130602e8b047bc8cd4c958cf6beb785fa5b1b 100644 --- a/core/network-libp2p/src/custom_proto/handler.rs +++ b/core/network-libp2p/src/custom_proto/handler.rs @@ -14,27 +14,29 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::ProtocolId; -use crate::custom_proto::upgrade::{CustomMessage, CustomMessageId, RegisteredProtocol, RegisteredProtocols}; +use crate::custom_proto::upgrade::{CustomMessage, CustomMessageId, RegisteredProtocol}; use crate::custom_proto::upgrade::{RegisteredProtocolEvent, RegisteredProtocolSubstream}; use futures::prelude::*; use libp2p::core::{ - Endpoint, ProtocolsHandler, ProtocolsHandlerEvent, + PeerId, Endpoint, ProtocolsHandler, ProtocolsHandlerEvent, + protocols_handler::IntoProtocolsHandler, protocols_handler::KeepAlive, protocols_handler::ProtocolsHandlerUpgrErr, upgrade::{InboundUpgrade, OutboundUpgrade} }; use log::{debug, error, warn}; use smallvec::{smallvec, SmallVec}; -use std::{error, fmt, io, mem, time::Duration, time::Instant}; +use std::{error, fmt, io, marker::PhantomData, mem, time::Duration, time::Instant}; use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_timer::Delay; use void::Void; -/// Implements the `ProtocolsHandler` trait of libp2p. +/// Implements the `IntoProtocolsHandler` trait of libp2p. /// -/// Every time a connection with a remote is established, an instance of this struct is created and -/// sent to a background task dedicated to this connection. It handles all communications that are -/// specific to Substrate. +/// Every time a connection with a remote starts, an instance of this struct is created and +/// sent to a background task dedicated to this connection. Once the connection is established, +/// it is turned into a `CustomProtoHandler`. It then handles all communications that are specific +/// to Substrate on that connection. /// /// Note that there can be multiple instance of this struct simultaneously for same peer. However /// if that happens, only one main instance can communicate with the outer layers of the code. @@ -62,39 +64,88 @@ use void::Void; /// happens on one substream, we consider that we are disconnected. Re-enabling is performed by /// opening an outbound substream. /// -pub struct CustomProtosHandler { - /// Fields individual to each protocol that we support. - protocols: SmallVec<[PerProtocol; 1]>, +pub struct CustomProtoHandlerProto { + /// Configuration for the protocol upgrade to negotiate. + protocol: RegisteredProtocol, + + /// Marker to pin the generic type. + marker: PhantomData, +} + +impl CustomProtoHandlerProto +where + TSubstream: AsyncRead + AsyncWrite, + TMessage: CustomMessage, +{ + /// Builds a new `CustomProtoHandlerProto`. + pub fn new(protocol: RegisteredProtocol) -> Self { + CustomProtoHandlerProto { + protocol, + marker: PhantomData, + } + } +} + +impl IntoProtocolsHandler for CustomProtoHandlerProto +where + TSubstream: AsyncRead + AsyncWrite, + TMessage: CustomMessage, +{ + type Handler = CustomProtoHandler; + + fn into_handler(self, remote_peer_id: &PeerId) -> Self::Handler { + CustomProtoHandler { + protocol: self.protocol, + remote_peer_id: remote_peer_id.clone(), + state: ProtocolState::Init { + substreams: SmallVec::new(), + init_deadline: Delay::new(Instant::now() + Duration::from_secs(5)) + }, + events_queue: SmallVec::new(), + warm_up_end: Instant::now() + Duration::from_secs(5), + } + } +} + +/// The actual handler once the connection has been established. +pub struct CustomProtoHandler { + /// Configuration for the protocol upgrade to negotiate. + protocol: RegisteredProtocol, + + /// State of the communications with the remote. + state: ProtocolState, + + /// Identifier of the node we're talking to. Used only for logging purposes and shouldn't have + /// any influence on the behaviour. + remote_peer_id: PeerId, /// Queue of events to send to the outside. /// /// This queue must only ever be modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent, ProtocolId, CustomProtosHandlerOut>; 16]>, + events_queue: SmallVec<[ProtocolsHandlerEvent, (), CustomProtoHandlerOut>; 16]>, /// We have a warm-up period after creating the handler during which we don't shut down the /// connection. warm_up_end: Instant, } -/// Fields individual to each protocol that we support. -struct PerProtocol { - /// Configuration for the protocol upgrade to negotiate. - protocol: RegisteredProtocol, - - /// State of the communications with the remote. - state: PerProtocolState, -} - -/// State of the handler for a specific protocol. -enum PerProtocolState { +/// State of the handler. +enum ProtocolState { /// Waiting for the behaviour to tell the handler whether it is enabled or disabled. - /// Contains a list of substreams opened by the remote but that haven't been processed yet. - Init(SmallVec<[RegisteredProtocolSubstream; 6]>), + Init { + /// List of substreams opened by the remote but that haven't been processed yet. + substreams: SmallVec<[RegisteredProtocolSubstream; 6]>, + /// Deadline after which the initialization is abnormally long. + init_deadline: Delay, + }, /// Handler is opening a substream in order to activate itself. /// If we are in this state, we haven't sent any `CustomProtocolOpen` yet. - Opening, + Opening { + /// Deadline after which the opening is abnormally long. + deadline: Delay, + }, /// Backwards-compatible mode. Contains the unique substream that is open. /// If we are in this state, we have sent a `CustomProtocolOpen` message to the outside. @@ -124,11 +175,6 @@ enum PerProtocolState { reenable: bool, }, - /// We are trying to shut down the connection and thus should refuse any incoming connection. - /// Contains substreams that are being closed. Once all the substreams are closed, we close - /// the connection. - ShuttingDown(SmallVec<[RegisteredProtocolSubstream; 6]>), - /// We sometimes temporarily switch to this state during processing. If we are in this state /// at the beginning of a method, that means something bad happend in the source code. Poisoned, @@ -157,290 +203,6 @@ struct PerProtocolNormalState { shutdown: SmallVec<[RegisteredProtocolSubstream; 4]>, } -impl PerProtocol -where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { - /// Enables the protocol. Returns an optional event to emit. - /// Must be passed the endpoint of the connection. - #[must_use] - fn enable(&mut self, endpoint: Endpoint) - -> Option, ProtocolId, CustomProtosHandlerOut>> { - - let return_value; - - self.state = match mem::replace(&mut self.state, PerProtocolState::Poisoned) { - PerProtocolState::Poisoned => { - error!(target: "sub-libp2p", "Handler is in poisoned state"); - return_value = None; - PerProtocolState::Poisoned - } - - PerProtocolState::Init(incoming) => { - if incoming.is_empty() { - if let Endpoint::Dialer = endpoint { - return_value = Some(ProtocolsHandlerEvent::OutboundSubstreamRequest { - upgrade: self.protocol.clone(), - info: self.protocol.id(), - }); - } else { - return_value = None; - } - PerProtocolState::Opening - - } else if incoming.iter().any(|s| s.is_multiplex()) { - let event = CustomProtosHandlerOut::CustomProtocolOpen { - protocol_id: self.protocol.id(), - version: incoming[0].protocol_version() - }; - return_value = Some(ProtocolsHandlerEvent::Custom(event)); - PerProtocolState::Normal(PerProtocolNormalState { - outgoing_substream: None, - incoming_substreams: incoming.into_iter().collect(), - pending_response: SmallVec::new(), - pending_send_back: SmallVec::new(), - pending_messages: SmallVec::new(), - shutdown: SmallVec::new(), - }) - - } else { - let event = CustomProtosHandlerOut::CustomProtocolOpen { - protocol_id: self.protocol.id(), - version: incoming[0].protocol_version() - }; - return_value = Some(ProtocolsHandlerEvent::Custom(event)); - PerProtocolState::BackCompat { - substream: incoming.into_iter().next() - .expect("We have a check above that incoming isn't empty; QED"), - shutdown: SmallVec::new() - } - } - } - - st @ PerProtocolState::Opening => { return_value = None; st } - st @ PerProtocolState::BackCompat { .. } => { return_value = None; st } - st @ PerProtocolState::Normal { .. } => { return_value = None; st } - PerProtocolState::Disabled { shutdown, .. } => { - return_value = None; - PerProtocolState::Disabled { shutdown, reenable: true } - } - PerProtocolState::ShuttingDown(list) => { - return_value = None; - PerProtocolState::ShuttingDown(list) - } - }; - - return_value - } - - /// Disables the protocol. Returns `true` if the protocol was closed, `false` if it was already - /// closed or not open yet. - fn disable(&mut self) -> bool { - let mut return_value = false; - - self.state = match mem::replace(&mut self.state, PerProtocolState::Poisoned) { - PerProtocolState::Poisoned => { - error!(target: "sub-libp2p", "Handler is in poisoned state"); - PerProtocolState::Poisoned - } - - PerProtocolState::Init(mut shutdown) => { - for s in &mut shutdown { - s.shutdown(); - } - PerProtocolState::Disabled { shutdown, reenable: false } - } - - PerProtocolState::Opening => { - PerProtocolState::Disabled { shutdown: SmallVec::new(), reenable: false } - } - - PerProtocolState::BackCompat { mut substream, mut shutdown } => { - substream.shutdown(); - shutdown.push(substream); - return_value = true; - PerProtocolState::Disabled { - shutdown: shutdown.into_iter().collect(), - reenable: false - } - } - - PerProtocolState::Normal(state) => { - let mut out: SmallVec<[_; 6]> = SmallVec::new(); - out.extend(state.outgoing_substream.into_iter()); - out.extend(state.incoming_substreams.into_iter()); - out.extend(state.pending_response.into_iter().map(|(_, s)| s)); - out.extend(state.pending_send_back.into_iter().map(|(_, s)| s)); - for s in &mut out { - s.shutdown(); - } - out.extend(state.shutdown.into_iter()); - return_value = true; - PerProtocolState::Disabled { shutdown: out, reenable: false } - } - - PerProtocolState::Disabled { shutdown, .. } => - PerProtocolState::Disabled { shutdown, reenable: false }, - PerProtocolState::ShuttingDown(list) => - PerProtocolState::ShuttingDown(list), - }; - - return_value - } - - /// Shuts down all the substream. Returns `true` if the protocol was closed, `false` if it was - /// already closed or not open yet. - fn shutdown(&mut self) -> bool { - let mut return_value = false; - self.state = match mem::replace(&mut self.state, PerProtocolState::Poisoned) { - PerProtocolState::Poisoned => { - error!(target: "sub-libp2p", "Handler is in poisoned state"); - PerProtocolState::Poisoned - } - - PerProtocolState::Init(mut list) => { - for s in &mut list { s.shutdown(); } - PerProtocolState::ShuttingDown(list) - } - - PerProtocolState::Opening => { - PerProtocolState::ShuttingDown(SmallVec::new()) - } - - PerProtocolState::BackCompat { mut substream, mut shutdown } => { - substream.shutdown(); - shutdown.push(substream); - return_value = true; - PerProtocolState::ShuttingDown(shutdown.into_iter().collect()) - } - - PerProtocolState::Normal(state) => { - let mut out: SmallVec<[_; 6]> = SmallVec::new(); - out.extend(state.outgoing_substream.into_iter()); - out.extend(state.incoming_substreams.into_iter()); - out.extend(state.pending_response.into_iter().map(|(_, s)| s)); - out.extend(state.pending_send_back.into_iter().map(|(_, s)| s)); - for s in &mut out { - s.shutdown(); - } - out.extend(state.shutdown.into_iter()); - return_value = true; - PerProtocolState::ShuttingDown(out) - } - - PerProtocolState::Disabled { shutdown, .. } => - PerProtocolState::ShuttingDown(shutdown), - PerProtocolState::ShuttingDown(list) => - PerProtocolState::ShuttingDown(list), - }; - return_value - } - - /// Polls the state for events. Optionally returns an event to produce. - #[must_use] - fn poll(&mut self) - -> Option, ProtocolId, CustomProtosHandlerOut>> { - - let return_value; - self.state = match mem::replace(&mut self.state, PerProtocolState::Poisoned) { - PerProtocolState::Poisoned => { - error!(target: "sub-libp2p", "Handler is in poisoned state; shutting down"); - return_value = Some(ProtocolsHandlerEvent::Shutdown); - PerProtocolState::Poisoned - } - - st @ PerProtocolState::Init(_) => { - return_value = None; - st - } - - st @ PerProtocolState::Opening { .. } => { - return_value = None; - st - } - - PerProtocolState::BackCompat { mut substream, shutdown } => { - match substream.poll() { - Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => { - let event = CustomProtosHandlerOut::CustomMessage { - protocol_id: substream.protocol_id(), - message - }; - return_value = Some(ProtocolsHandlerEvent::Custom(event)); - PerProtocolState::BackCompat { substream, shutdown } - }, - Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { messages }))) => { - let event = CustomProtosHandlerOut::Clogged { - protocol_id: substream.protocol_id(), - messages, - }; - return_value = Some(ProtocolsHandlerEvent::Custom(event)); - PerProtocolState::BackCompat { substream, shutdown } - } - Ok(Async::NotReady) => { - return_value = None; - PerProtocolState::BackCompat { substream, shutdown } - } - Ok(Async::Ready(None)) => { - let event = CustomProtosHandlerOut::CustomProtocolClosed { - protocol_id: substream.protocol_id(), - result: Ok(()) - }; - return_value = Some(ProtocolsHandlerEvent::Custom(event)); - PerProtocolState::Disabled { - shutdown: shutdown.into_iter().collect(), - reenable: false - } - } - Err(err) => { - let event = CustomProtosHandlerOut::CustomProtocolClosed { - protocol_id: substream.protocol_id(), - result: Err(err), - }; - return_value = Some(ProtocolsHandlerEvent::Custom(event)); - PerProtocolState::Disabled { - shutdown: shutdown.into_iter().collect(), - reenable: false - } - } - } - } - - PerProtocolState::Normal(mut norm_state) => { - if let Some(event) = norm_state.poll(self.protocol.id()) { - return_value = Some(ProtocolsHandlerEvent::Custom(event)); - } else { - return_value = None; - } - - PerProtocolState::Normal(norm_state) - } - - PerProtocolState::Disabled { mut shutdown, reenable } => { - shutdown_list(&mut shutdown); - // If `reenable` is `true`, that means we should open the substreams system again - // after all the substreams are closed. - if reenable && shutdown.is_empty() { - return_value = Some(ProtocolsHandlerEvent::OutboundSubstreamRequest { - upgrade: self.protocol.clone(), - info: self.protocol.id(), - }); - PerProtocolState::Opening - } else { - return_value = None; - PerProtocolState::Disabled { shutdown, reenable } - } - } - - PerProtocolState::ShuttingDown(mut list) => { - shutdown_list(&mut list); - return_value = None; - PerProtocolState::ShuttingDown(list) - } - }; - - return_value - } -} - impl PerProtocolNormalState where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { /// Polls for things that are new. Same API constraints as `Future::poll()`. @@ -449,22 +211,20 @@ where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { /// API note: Ideally we wouldn't need to be passed a `ProtocolId`, and we would return a /// different enum that doesn't contain any `protocol_id`, and the caller would inject /// the ID itself, but that's a ton of code for not much gain. - fn poll(&mut self, protocol_id: ProtocolId) -> Option> { + fn poll(&mut self) -> Option> { for n in (0..self.pending_response.len()).rev() { let (request_id, mut substream) = self.pending_response.swap_remove(n); match substream.poll() { Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => { if message.request_id() == CustomMessageId::Response(request_id) { - let event = CustomProtosHandlerOut::CustomMessage { - protocol_id: substream.protocol_id(), + let event = CustomProtoHandlerOut::CustomMessage { message }; self.shutdown.push(substream); return Some(event); } else { self.shutdown.push(substream); - let event = CustomProtosHandlerOut::ProtocolError { - protocol_id, + let event = CustomProtoHandlerOut::ProtocolError { is_severe: true, error: format!("Request ID doesn't match substream: expected {:?}, \ got {:?}", request_id, message.request_id()).into(), @@ -478,8 +238,7 @@ where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { self.pending_response.push((request_id, substream)), Ok(Async::Ready(None)) => { self.shutdown.push(substream); - let event = CustomProtosHandlerOut::ProtocolError { - protocol_id, + let event = CustomProtoHandlerOut::ProtocolError { is_severe: false, error: format!("Request ID {:?} didn't receive an answer", request_id).into(), }; @@ -487,8 +246,7 @@ where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { } Err(err) => { self.shutdown.push(substream); - let event = CustomProtosHandlerOut::ProtocolError { - protocol_id, + let event = CustomProtoHandlerOut::ProtocolError { is_severe: false, error: format!("Error while waiting for an answer for {:?}: {}", request_id, err).into(), @@ -502,26 +260,26 @@ where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { let mut substream = self.incoming_substreams.swap_remove(n); match substream.poll() { Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => { - let protocol_id = substream.protocol_id(); - if let CustomMessageId::Request(id) = message.request_id() { - self.pending_send_back.push((id, substream)); - return Some(CustomProtosHandlerOut::CustomMessage { - protocol_id, - message - }); - } else if let CustomMessageId::OneWay = message.request_id() { - self.shutdown.push(substream); - return Some(CustomProtosHandlerOut::CustomMessage { - protocol_id, - message - }); - } else { - self.shutdown.push(substream); - return Some(CustomProtosHandlerOut::ProtocolError { - protocol_id, - is_severe: true, - error: format!("Received response in new substream").into(), - }); + return match message.request_id() { + CustomMessageId::Request(id) => { + self.pending_send_back.push((id, substream)); + Some(CustomProtoHandlerOut::CustomMessage { + message + }) + } + CustomMessageId::OneWay => { + self.shutdown.push(substream); + Some(CustomProtoHandlerOut::CustomMessage { + message + }) + } + _ => { + self.shutdown.push(substream); + Some(CustomProtoHandlerOut::ProtocolError { + is_severe: true, + error: format!("Received response in new substream").into(), + }) + } } }, Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { .. }))) => @@ -531,8 +289,7 @@ where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { Ok(Async::Ready(None)) => {} Err(err) => { self.shutdown.push(substream); - return Some(CustomProtosHandlerOut::ProtocolError { - protocol_id, + return Some(CustomProtoHandlerOut::ProtocolError { is_severe: false, error: format!("Error in incoming substream: {}", err).into(), }); @@ -545,9 +302,9 @@ where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { } } -/// Event that can be received by a `CustomProtosHandler`. +/// Event that can be received by a `CustomProtoHandler`. #[derive(Debug)] -pub enum CustomProtosHandlerIn { +pub enum CustomProtoHandlerIn { /// The node should start using custom protocols. Contains whether we are the dialer or the /// listener of the connection. Enable(Endpoint), @@ -557,36 +314,28 @@ pub enum CustomProtosHandlerIn { /// Sends a message through a custom protocol substream. SendCustomMessage { - /// The protocol to use. - protocol: ProtocolId, /// The message to send. message: TMessage, }, } -/// Event that can be emitted by a `CustomProtosHandler`. +/// Event that can be emitted by a `CustomProtoHandler`. #[derive(Debug)] -pub enum CustomProtosHandlerOut { +pub enum CustomProtoHandlerOut { /// Opened a custom protocol with the remote. CustomProtocolOpen { - /// Identifier of the protocol. - protocol_id: ProtocolId, /// Version of the protocol that has been opened. version: u8, }, /// Closed a custom protocol with the remote. CustomProtocolClosed { - /// Identifier of the protocol. - protocol_id: ProtocolId, /// Reason why the substream closed. If `Ok`, then it's a graceful exit (EOF). result: io::Result<()>, }, /// Receives a message on a custom protocol substream. CustomMessage { - /// Protocol which generated the message. - protocol_id: ProtocolId, /// Message that has been received. message: TMessage, }, @@ -594,16 +343,12 @@ pub enum CustomProtosHandlerOut { /// A substream to the remote is clogged. The send buffer is very large, and we should print /// a diagnostic message and/or avoid sending more data. Clogged { - /// Protocol which is clogged. - protocol_id: ProtocolId, /// Copy of the messages that are within the buffer, for further diagnostic. messages: Vec, }, /// An error has happened on the protocol level with this node. ProtocolError { - /// Protocol for which the error happened. - protocol_id: ProtocolId, /// If true the error is severe, such as a protocol violation. is_severe: bool, /// The error that happened. @@ -611,45 +356,248 @@ pub enum CustomProtosHandlerOut { }, } -impl CustomProtosHandler +impl CustomProtoHandler where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage, { - /// Builds a new `CustomProtosHandler`. - pub fn new(protocols: RegisteredProtocols) -> Self { - CustomProtosHandler { - protocols: protocols.0.into_iter().map(|protocol| { - PerProtocol { - protocol, - state: PerProtocolState::Init(SmallVec::new()), + /// Enables the handler. + fn enable(&mut self, endpoint: Endpoint) { + self.state = match mem::replace(&mut self.state, ProtocolState::Poisoned) { + ProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler with {:?} is in poisoned state", + self.remote_peer_id); + ProtocolState::Poisoned + } + + ProtocolState::Init { substreams: incoming, .. } => { + if incoming.is_empty() { + if let Endpoint::Dialer = endpoint { + self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + upgrade: self.protocol.clone(), + info: (), + }); + } + ProtocolState::Opening { + deadline: Delay::new(Instant::now() + Duration::from_secs(60)) + } + + } else if incoming.iter().any(|s| s.is_multiplex()) { + let event = CustomProtoHandlerOut::CustomProtocolOpen { + version: incoming[0].protocol_version() + }; + self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::Normal(PerProtocolNormalState { + outgoing_substream: None, + incoming_substreams: incoming.into_iter().collect(), + pending_response: SmallVec::new(), + pending_send_back: SmallVec::new(), + pending_messages: SmallVec::new(), + shutdown: SmallVec::new(), + }) + + } else { + let event = CustomProtoHandlerOut::CustomProtocolOpen { + version: incoming[0].protocol_version() + }; + self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::BackCompat { + substream: incoming.into_iter().next() + .expect("We have a check above that incoming isn't empty; QED"), + shutdown: SmallVec::new() + } } - }).collect(), - events_queue: SmallVec::new(), - warm_up_end: Instant::now() + Duration::from_secs(5), - } - } + } - /// Enables the handler for all protocols. - fn enable(&mut self, endpoint: Endpoint) { - for protocol in &mut self.protocols { - if let Some(message) = protocol.enable(endpoint) { - self.events_queue.push(message); + st @ ProtocolState::Opening { .. } => st, + st @ ProtocolState::BackCompat { .. } => st, + st @ ProtocolState::Normal { .. } => st, + ProtocolState::Disabled { shutdown, .. } => { + ProtocolState::Disabled { shutdown, reenable: true } } } } - /// Disables the handler for all protocols. + /// Disables the handler. fn disable(&mut self) { - for protocol in &mut self.protocols { - if protocol.disable() { - let event = CustomProtosHandlerOut::CustomProtocolClosed { - protocol_id: protocol.protocol.id(), + self.state = match mem::replace(&mut self.state, ProtocolState::Poisoned) { + ProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler with {:?} is in poisoned state", + self.remote_peer_id); + ProtocolState::Poisoned + } + + ProtocolState::Init { substreams: mut shutdown, .. } => { + for s in &mut shutdown { + s.shutdown(); + } + ProtocolState::Disabled { shutdown, reenable: false } + } + + ProtocolState::Opening { .. } => { + ProtocolState::Disabled { shutdown: SmallVec::new(), reenable: false } + } + + ProtocolState::BackCompat { mut substream, mut shutdown } => { + substream.shutdown(); + shutdown.push(substream); + let event = CustomProtoHandlerOut::CustomProtocolClosed { + result: Ok(()) + }; + self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::Disabled { + shutdown: shutdown.into_iter().collect(), + reenable: false + } + } + + ProtocolState::Normal(state) => { + let mut out: SmallVec<[_; 6]> = SmallVec::new(); + out.extend(state.outgoing_substream.into_iter()); + out.extend(state.incoming_substreams.into_iter()); + out.extend(state.pending_response.into_iter().map(|(_, s)| s)); + out.extend(state.pending_send_back.into_iter().map(|(_, s)| s)); + for s in &mut out { + s.shutdown(); + } + out.extend(state.shutdown.into_iter()); + let event = CustomProtoHandlerOut::CustomProtocolClosed { result: Ok(()) }; self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::Disabled { shutdown: out, reenable: false } } - } + + ProtocolState::Disabled { shutdown, .. } => + ProtocolState::Disabled { shutdown, reenable: false }, + }; + } + + /// Polls the state for events. Optionally returns an event to produce. + #[must_use] + fn poll_state(&mut self) + -> Option, (), CustomProtoHandlerOut>> { + let return_value; + self.state = match mem::replace(&mut self.state, ProtocolState::Poisoned) { + ProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler with {:?} is in poisoned state", + self.remote_peer_id); + return_value = None; + ProtocolState::Poisoned + } + + ProtocolState::Init { substreams, mut init_deadline } => { + match init_deadline.poll() { + Ok(Async::Ready(())) => { + init_deadline.reset(Instant::now() + Duration::from_secs(60)); + error!(target: "sub-libp2p", "Handler initialization process is too long \ + with {:?}", self.remote_peer_id) + }, + Ok(Async::NotReady) => {} + Err(_) => error!(target: "sub-libp2p", "Tokio timer has errored") + } + + return_value = None; + ProtocolState::Init { substreams, init_deadline } + } + + ProtocolState::Opening { mut deadline } => { + match deadline.poll() { + Ok(Async::Ready(())) => { + deadline.reset(Instant::now() + Duration::from_secs(60)); + let event = CustomProtoHandlerOut::ProtocolError { + is_severe: false, + error: "Timeout when opening protocol".to_string().into(), + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::Opening { deadline } + }, + Ok(Async::NotReady) => { + return_value = None; + ProtocolState::Opening { deadline } + }, + Err(_) => { + error!(target: "sub-libp2p", "Tokio timer has errored"); + deadline.reset(Instant::now() + Duration::from_secs(60)); + return_value = None; + ProtocolState::Opening { deadline } + }, + } + } + + ProtocolState::BackCompat { mut substream, shutdown } => { + match substream.poll() { + Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => { + let event = CustomProtoHandlerOut::CustomMessage { + message + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::BackCompat { substream, shutdown } + }, + Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { messages }))) => { + let event = CustomProtoHandlerOut::Clogged { + messages, + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::BackCompat { substream, shutdown } + } + Ok(Async::NotReady) => { + return_value = None; + ProtocolState::BackCompat { substream, shutdown } + } + Ok(Async::Ready(None)) => { + let event = CustomProtoHandlerOut::CustomProtocolClosed { + result: Ok(()) + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::Disabled { + shutdown: shutdown.into_iter().collect(), + reenable: false + } + } + Err(err) => { + let event = CustomProtoHandlerOut::CustomProtocolClosed { + result: Err(err), + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + ProtocolState::Disabled { + shutdown: shutdown.into_iter().collect(), + reenable: false + } + } + } + } + + ProtocolState::Normal(mut norm_state) => { + if let Some(event) = norm_state.poll() { + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + } else { + return_value = None; + } + + ProtocolState::Normal(norm_state) + } + + ProtocolState::Disabled { mut shutdown, reenable } => { + shutdown_list(&mut shutdown); + // If `reenable` is `true`, that means we should open the substreams system again + // after all the substreams are closed. + if reenable && shutdown.is_empty() { + return_value = Some(ProtocolsHandlerEvent::OutboundSubstreamRequest { + upgrade: self.protocol.clone(), + info: (), + }); + ProtocolState::Opening { + deadline: Delay::new(Instant::now() + Duration::from_secs(60)) + } + } else { + return_value = None; + ProtocolState::Disabled { shutdown, reenable } + } + } + }; + + return_value } /// Called by `inject_fully_negotiated_inbound` and `inject_fully_negotiated_outbound`. @@ -657,39 +605,31 @@ where &mut self, mut substream: RegisteredProtocolSubstream ) { - let state = match self.protocols.iter_mut().find(|p| p.protocol.id() == substream.protocol_id()) { - Some(p) => &mut p.state, - None => { - error!(target: "sub-libp2p", "Found unknown protocol ID {:?}", - substream.protocol_id()); - return - }, - }; - - *state = match mem::replace(state, PerProtocolState::Poisoned) { - PerProtocolState::Poisoned => { - error!(target: "sub-libp2p", "Handler is in poisoned state"); - PerProtocolState::Poisoned + self.state = match mem::replace(&mut self.state, ProtocolState::Poisoned) { + ProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler with {:?} is in poisoned state", + self.remote_peer_id); + ProtocolState::Poisoned } - PerProtocolState::Init(mut incoming) => { + ProtocolState::Init { mut substreams, init_deadline } => { if substream.endpoint() == Endpoint::Dialer { - error!(target: "sub-libp2p", "Opened dialing substream before initialization"); + error!(target: "sub-libp2p", "Opened dialing substream with {:?} before \ + initialization", self.remote_peer_id); } - incoming.push(substream); - PerProtocolState::Init(incoming) + substreams.push(substream); + ProtocolState::Init { substreams, init_deadline } } - PerProtocolState::Opening => { - let event = CustomProtosHandlerOut::CustomProtocolOpen { - protocol_id: substream.protocol_id(), + ProtocolState::Opening { .. } => { + let event = CustomProtoHandlerOut::CustomProtocolOpen { version: substream.protocol_version() }; self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); match (substream.endpoint(), substream.is_multiplex()) { (Endpoint::Dialer, true) => { - PerProtocolState::Normal(PerProtocolNormalState { + ProtocolState::Normal(PerProtocolNormalState { outgoing_substream: Some(substream), incoming_substreams: SmallVec::new(), pending_response: SmallVec::new(), @@ -699,7 +639,7 @@ where }) }, (Endpoint::Listener, true) => { - PerProtocolState::Normal(PerProtocolNormalState { + ProtocolState::Normal(PerProtocolNormalState { outgoing_substream: None, incoming_substreams: smallvec![substream], pending_response: SmallVec::new(), @@ -709,7 +649,7 @@ where }) }, (_, false) => { - PerProtocolState::BackCompat { + ProtocolState::BackCompat { substream, shutdown: SmallVec::new() } @@ -717,15 +657,15 @@ where } } - PerProtocolState::BackCompat { substream: existing, mut shutdown } => { + ProtocolState::BackCompat { substream: existing, mut shutdown } => { warn!(target: "sub-libp2p", "Received extra substream after having already one \ - open in backwards-compatibility mode"); + open in backwards-compatibility mode with {:?}", self.remote_peer_id); substream.shutdown(); shutdown.push(substream); - PerProtocolState::BackCompat { substream: existing, shutdown } + ProtocolState::BackCompat { substream: existing, shutdown } } - PerProtocolState::Normal(mut state) => { + ProtocolState::Normal(mut state) => { if substream.endpoint() == Endpoint::Listener { state.incoming_substreams.push(substream); } else if !state.pending_messages.is_empty() { @@ -738,60 +678,45 @@ where state.shutdown.push(substream); } } else { - debug!(target: "sub-libp2p", "Opened spurious outbound substream"); + debug!(target: "sub-libp2p", "Opened spurious outbound substream with {:?}", + self.remote_peer_id); substream.shutdown(); state.shutdown.push(substream); } - PerProtocolState::Normal(state) + ProtocolState::Normal(state) } - PerProtocolState::Disabled { mut shutdown, .. } => { + ProtocolState::Disabled { mut shutdown, .. } => { substream.shutdown(); shutdown.push(substream); - PerProtocolState::Disabled { shutdown, reenable: false } - } - - PerProtocolState::ShuttingDown(mut list) => { - substream.shutdown(); - list.push(substream); - PerProtocolState::ShuttingDown(list) + ProtocolState::Disabled { shutdown, reenable: false } } }; } /// Sends a message to the remote. - fn send_message(&mut self, protocol: ProtocolId, message: TMessage) { - let (protocol, state) = match self.protocols.iter_mut().find(|p| p.protocol.id() == protocol) { - Some(p) => (&mut p.protocol, &mut p.state), - None => { - error!(target: "sub-libp2p", "Tried to send message over unknown protocol ID {:?}", - protocol); - return - }, - }; - - match *state { - PerProtocolState::BackCompat { ref mut substream, .. } => + fn send_message(&mut self, message: TMessage) { + match self.state { + ProtocolState::BackCompat { ref mut substream, .. } => substream.send_message(message), - PerProtocolState::Normal(ref mut state) => { + ProtocolState::Normal(ref mut state) => { if let CustomMessageId::Request(request_id) = message.request_id() { if let Some(mut outgoing_substream) = state.outgoing_substream.take() { outgoing_substream.send_message(message); state.pending_response.push((request_id, outgoing_substream)); } else { if state.pending_messages.len() >= 2048 { - let event = CustomProtosHandlerOut::Clogged { + let event = CustomProtoHandlerOut::Clogged { messages: Vec::new(), - protocol_id: protocol.id() }; self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); } state.pending_messages.push(message); self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { - upgrade: protocol.clone(), - info: protocol.id() + upgrade: self.protocol.clone(), + info: () }); } } else if let CustomMessageId::Response(request_id) = message.request_id() { @@ -801,45 +726,44 @@ where state.shutdown.push(substream); } else { warn!(target: "sub-libp2p", "Libp2p layer received response to a \ - non-existing request ID {:?}", request_id); + non-existing request ID {:?} with {:?}", request_id, self.remote_peer_id); } } else if let Some(mut outgoing_substream) = state.outgoing_substream.take() { outgoing_substream.send_message(message); state.shutdown.push(outgoing_substream); } else { if state.pending_messages.len() >= 2048 { - let event = CustomProtosHandlerOut::Clogged { + let event = CustomProtoHandlerOut::Clogged { messages: Vec::new(), - protocol_id: protocol.id() }; self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); } state.pending_messages.push(message); self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { - upgrade: protocol.clone(), - info: protocol.id() + upgrade: self.protocol.clone(), + info: () }); } } - _ => debug!(target: "sub-libp2p", "Tried to send message over closed protocol") + _ => debug!(target: "sub-libp2p", "Tried to send message over closed protocol \ + with {:?}", self.remote_peer_id) } } } -impl ProtocolsHandler for CustomProtosHandler +impl ProtocolsHandler for CustomProtoHandler where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage { - type InEvent = CustomProtosHandlerIn; - type OutEvent = CustomProtosHandlerOut; + type InEvent = CustomProtoHandlerIn; + type OutEvent = CustomProtoHandlerOut; type Substream = TSubstream; type Error = Void; - type InboundProtocol = RegisteredProtocols; + type InboundProtocol = RegisteredProtocol; type OutboundProtocol = RegisteredProtocol; - type OutboundOpenInfo = ProtocolId; + type OutboundOpenInfo = (); - #[inline] fn listen_protocol(&self) -> Self::InboundProtocol { - RegisteredProtocols(self.protocols.iter().map(|p| p.protocol.clone()).collect()) + self.protocol.clone() } fn inject_fully_negotiated_inbound( @@ -849,7 +773,6 @@ where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage { self.inject_fully_negotiated(proto); } - #[inline] fn inject_fully_negotiated_outbound( &mut self, proto: >::Output, @@ -858,34 +781,26 @@ where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage { self.inject_fully_negotiated(proto); } - fn inject_event(&mut self, message: CustomProtosHandlerIn) { + fn inject_event(&mut self, message: CustomProtoHandlerIn) { match message { - CustomProtosHandlerIn::Disable => self.disable(), - CustomProtosHandlerIn::Enable(endpoint) => self.enable(endpoint), - CustomProtosHandlerIn::SendCustomMessage { protocol, message } => - self.send_message(protocol, message), + CustomProtoHandlerIn::Disable => self.disable(), + CustomProtoHandlerIn::Enable(endpoint) => self.enable(endpoint), + CustomProtoHandlerIn::SendCustomMessage { message } => + self.send_message(message), } } #[inline] - fn inject_inbound_closed(&mut self) {} - - #[inline] - fn inject_dial_upgrade_error(&mut self, protocol_id: Self::OutboundOpenInfo, err: ProtocolsHandlerUpgrErr) { + fn inject_dial_upgrade_error(&mut self, _: (), err: ProtocolsHandlerUpgrErr) { let is_severe = match err { ProtocolsHandlerUpgrErr::Upgrade(_) => true, _ => false, }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(CustomProtosHandlerOut::ProtocolError { - protocol_id, + self.events_queue.push(ProtocolsHandlerEvent::Custom(CustomProtoHandlerOut::ProtocolError { is_severe, error: Box::new(err), })); - - // If we failed to open a substream, there is little chance that we manage to open any - // other substream ever again on this connection, and thus we disable the handler. - self.disable(); } fn connection_keep_alive(&self) -> KeepAlive { @@ -893,26 +808,19 @@ where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage { return KeepAlive::Until(self.warm_up_end) } - for protocol in self.protocols.iter() { - match protocol.state { - PerProtocolState::Disabled { .. } | PerProtocolState::ShuttingDown(_) | - PerProtocolState::Poisoned => return KeepAlive::Now, - _ => {} - } - } + let mut keep_forever = false; - KeepAlive::Forever - } + match self.state { + ProtocolState::Init { .. } | ProtocolState::Opening { .. } => {} + ProtocolState::BackCompat { .. } | ProtocolState::Normal { .. } => + keep_forever = true, + ProtocolState::Disabled { .. } | ProtocolState::Poisoned => return KeepAlive::Now, + } - fn shutdown(&mut self) { - for protocol in &mut self.protocols { - if protocol.shutdown() { - let event = CustomProtosHandlerOut::CustomProtocolClosed { - protocol_id: protocol.protocol.id(), - result: Ok(()) - }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); - } + if keep_forever { + KeepAlive::Forever + } else { + KeepAlive::Now } } @@ -929,32 +837,20 @@ where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage { } // Process all the substreams. - for protocol in self.protocols.iter_mut() { - if let Some(event) = protocol.poll() { - return Ok(Async::Ready(event)) - } - } - - // Shut down the node if everything is closed. - let can_shut_down = self.protocols.iter().all(|p| - match p.state { - PerProtocolState::ShuttingDown(ref list) if list.is_empty() => true, - _ => false - }); - if can_shut_down { - return Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown)) + if let Some(event) = self.poll_state() { + return Ok(Async::Ready(event)) } Ok(Async::NotReady) } } -impl fmt::Debug for CustomProtosHandler +impl fmt::Debug for CustomProtoHandler where TSubstream: AsyncRead + AsyncWrite, { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.debug_struct("CustomProtosHandler") + f.debug_struct("CustomProtoHandler") .finish() } } diff --git a/core/network-libp2p/src/custom_proto/mod.rs b/core/network-libp2p/src/custom_proto/mod.rs index 073ce8360aeea9137ec356108fea24f6a6b654c1..cf2bf57153cc3ec0dfec5ffa2df713907b071a55 100644 --- a/core/network-libp2p/src/custom_proto/mod.rs +++ b/core/network-libp2p/src/custom_proto/mod.rs @@ -14,10 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -pub use self::behaviour::{CustomProtos, CustomProtosOut}; -pub use self::upgrade::{CustomMessage, CustomMessageId, RegisteredProtocol, RegisteredProtocols}; +pub use self::behaviour::{CustomProto, CustomProtoOut}; +pub use self::upgrade::{CustomMessage, CustomMessageId, RegisteredProtocol}; mod behaviour; mod handler; -mod topology; mod upgrade; diff --git a/core/network-libp2p/src/custom_proto/topology.rs b/core/network-libp2p/src/custom_proto/topology.rs deleted file mode 100644 index 14792e2f57849b05e94aeeac66f89573559cd156..0000000000000000000000000000000000000000 --- a/core/network-libp2p/src/custom_proto/topology.rs +++ /dev/null @@ -1,725 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see .? - -use fnv::FnvHashMap; -use libp2p::{core::swarm::ConnectedPoint, Multiaddr, PeerId}; -use log::{debug, info, trace, warn}; -use serde_derive::{Serialize, Deserialize}; -use std::{cmp, fs}; -use std::io::{Read, Cursor, Error as IoError, ErrorKind as IoErrorKind, Write, BufReader, BufWriter}; -use std::path::{Path, PathBuf}; -use std::time::{Duration, Instant, SystemTime}; - -/// For each address we're connected to, a period of this duration increases the score by 1. -const CONNEC_DURATION_PER_SCORE: Duration = Duration::from_secs(10); -/// Maximum number of addresses for a given peer. If there are more than this number of addresses, -/// the ones with a lower score will be removed. -const MAX_ADDRESSES_PER_PEER: usize = 10; -/// Maximum value for the score. -const MAX_SCORE: u32 = 100; -/// When we successfully connect to a node, raises its score to the given minimum value. -const CONNECTED_MINIMUM_SCORE: u32 = 20; -/// Initial score that a node discovered through Kademlia receives, where we have a hint that the -/// node is reachable. -const DISCOVERY_INITIAL_SCORE_CONNECTABLE: u32 = 15; -/// Initial score that a node discovered through Kademlia receives, without any hint. -const DISCOVERY_INITIAL_SCORE: u32 = 10; -/// Score adjustement when we fail to connect to an address. -const SCORE_DIFF_ON_FAILED_TO_CONNECT: i32 = -1; -/// Default time-to-live for addresses discovered through Kademlia. -/// After this time has elapsed and no connection has succeeded, the address will be removed. -const KADEMLIA_DISCOVERY_EXPIRATION: Duration = Duration::from_secs(2 * 3600); -/// After a successful connection, the TTL is set to a minimum at this amount. -const EXPIRATION_PUSH_BACK_CONNEC: Duration = Duration::from_secs(2 * 3600); -/// Initial score that a bootstrap node receives when registered. -const BOOTSTRAP_NODE_SCORE: u32 = 100; -/// Time to live of a boostrap node. This only applies if you start the node later *without* -/// that bootstrap node configured anymore. -const BOOTSTRAP_NODE_EXPIRATION: Duration = Duration::from_secs(24 * 3600); -/// The first time we fail to connect to an address, wait this duration before trying again. -const FIRST_CONNECT_FAIL_BACKOFF: Duration = Duration::from_secs(2); -/// Every time we fail to connect to an address, multiply the backoff by this constant. -const FAIL_BACKOFF_MULTIPLIER: u32 = 2; -/// We need a maximum value for the backoff, overwise we risk an overflow. -const MAX_BACKOFF: Duration = Duration::from_secs(30 * 60); - -/// Stores information about the topology of the network. -#[derive(Debug)] -pub struct NetTopology { - /// The actual storage. Never contains a key for `local_peer_id`. - store: FnvHashMap, - /// Optional path to the file that caches the serialized version of `store`. - cache_path: Option, - /// PeerId of the local node. - local_peer_id: PeerId, -} - -impl NetTopology { - /// Initializes a new `NetTopology` that isn't tied to any file. - /// - /// `flush_to_disk()` will be a no-op. - #[inline] - pub fn memory(local_peer_id: PeerId) -> NetTopology { - NetTopology { - store: Default::default(), - cache_path: None, - local_peer_id, - } - } - - /// Builds a `NetTopology` that will use `path` as a cache. - /// - /// This function tries to load a known topology from the file. If the file doesn't exist - /// or contains garbage data, the execution still continues. - /// - /// Calling `flush_to_disk()` in the future writes to the given path. - pub fn from_file>(local_peer_id: PeerId, path: P) -> NetTopology { - let path = path.as_ref(); - debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); - let store = try_load(path, &local_peer_id); - NetTopology { - store, - cache_path: Some(path.to_owned()), - local_peer_id, - } - } - - /// Writes the topology into the path passed to `from_file`. - /// - /// No-op if the object was created with `memory()`. - pub fn flush_to_disk(&mut self) -> Result<(), IoError> { - let path = match self.cache_path { - Some(ref p) => p, - None => return Ok(()) - }; - - let file = fs::File::create(path)?; - // TODO: the capacity of the BufWriter is kind of arbitrary ; decide better - serialize(BufWriter::with_capacity(1024 * 1024, file), &mut self.store) - } - - /// Returns the number of peers in the topology, excluding the local peer. - #[inline] - pub fn num_peers(&self) -> usize { - self.store.len() - } - - /// Perform a cleanup pass, removing all obsolete addresses and peers. - /// - /// This should be done from time to time. - pub fn cleanup(&mut self) { - let now_systime = SystemTime::now(); - self.store.retain(|_, peer| { - let new_addrs = peer.addrs - .drain(..) - .filter(|a| a.expires > now_systime || a.is_connected()) - .collect(); - peer.addrs = new_addrs; - !peer.addrs.is_empty() - }); - } - - /// Returns a list of all the known addresses of peers, ordered by the - /// order in which we should attempt to connect to them. - /// - /// Because of expiration and back-off mechanisms, this list can grow - /// by itself over time. The `Instant` that is returned corresponds to - /// the earlier known time when a new entry will be added automatically to - /// the list. - pub fn addrs_to_attempt(&mut self) -> (impl Iterator, Instant) { - // TODO: optimize - let now = Instant::now(); - let now_systime = SystemTime::now(); - let mut instant = now + Duration::from_secs(3600); - let mut addrs_out = Vec::new(); - - let mut peer_addrs = Vec::new(); - - 'peer_loop: for (peer, info) in &mut self.store { - peer_addrs.clear(); - - for addr in &mut info.addrs { - let (score, is_connected) = addr.score_and_is_connected(); - if is_connected { - continue 'peer_loop - } - if score == 0 || addr.expires < now_systime { - continue - } - if addr.back_off_until > now { - instant = cmp::min(instant, addr.back_off_until); - continue - } - - peer_addrs.push(((peer, &addr.addr), score)); - } - - for val in peer_addrs.drain(..) { - addrs_out.push(val); - } - } - - addrs_out.sort_by(|a, b| b.1.cmp(&a.1)); - (addrs_out.into_iter().map(|a| a.0), instant) - } - - /// Adds an address corresponding to a boostrap node. - /// - /// We assume that the address is valid, so its score starts very high. - pub fn add_bootstrap_addr(&mut self, peer: &PeerId, addr: Multiaddr) { - if *peer == self.local_peer_id { - return - } - - let now_systime = SystemTime::now(); - let now = Instant::now(); - - let peer = peer_access(&mut self.store, peer); - - let mut found = false; - let new_addrs = peer.addrs - .drain(..) - .filter_map(|a| { - if a.expires < now_systime && !a.is_connected() { - return None - } - if a.addr == addr { - found = true; - } - Some(a) - }) - .collect(); - peer.addrs = new_addrs; - - if !found { - peer.addrs.push(Addr { - addr, - expires: now_systime + BOOTSTRAP_NODE_EXPIRATION, - back_off_until: now, - next_back_off: FIRST_CONNECT_FAIL_BACKOFF, - score: AddrScore { - connected_since: None, - score: BOOTSTRAP_NODE_SCORE, - latest_score_update: now, - }, - }); - } - } - - /// Indicates the topology that we have discovered new addresses for a given node. - /// - /// Returns `true` if the topology has changed in some way. Returns `false` if calling this - /// method was a no-op. - pub fn add_discovered_addrs( - &mut self, - peer_id: &PeerId, - addrs: I, - ) -> bool - where I: Iterator { - if *peer_id == self.local_peer_id { - return false - } - - let mut addrs: Vec<_> = addrs.collect(); - - if addrs.len() > 40 { - warn!(target: "sub-libp2p", "Attempt to add more than 40 addresses for {:?}", peer_id); - addrs.truncate(40); - } - - let now_systime = SystemTime::now(); - let now = Instant::now(); - - let peer = peer_access(&mut self.store, peer_id); - - let new_addrs = peer.addrs - .drain(..) - .filter(|a| { - if a.expires < now_systime && !a.is_connected() { - return false - } - addrs.retain(|(addr, _)| *addr != a.addr); - true - }) - .collect(); - peer.addrs = new_addrs; - - let mut anything_changed = false; - - if !addrs.is_empty() { - anything_changed = true; - trace!( - target: "sub-libp2p", - "Peer store: adding addresses {:?} for {:?}", - addrs, - peer_id, - ); - } - - 'addrs_inserter: for (addr, connectable) in addrs { - let initial_score = if connectable { - DISCOVERY_INITIAL_SCORE_CONNECTABLE - } else { - DISCOVERY_INITIAL_SCORE - }; - - // Enforce `MAX_ADDRESSES_PER_PEER` before inserting, or skip this entry. - while peer.addrs.len() >= MAX_ADDRESSES_PER_PEER { - let pos = peer.addrs.iter_mut().position(|addr| addr.score() <= initial_score); - if let Some(pos) = pos { - let _ = peer.addrs.remove(pos); - } else { - continue 'addrs_inserter; - } - } - - // `addrs` can contain duplicates, therefore we would insert the same address twice. - if peer.addrs.iter().any(|a| a.addr == addr) { - continue; - } - - peer.addrs.push(Addr { - addr, - expires: now_systime + KADEMLIA_DISCOVERY_EXPIRATION, - back_off_until: now, - next_back_off: FIRST_CONNECT_FAIL_BACKOFF, - score: AddrScore { - connected_since: None, - score: initial_score, - latest_score_update: now, - }, - }); - } - - anything_changed - } - - /// Returns the list of peers that are stored in the topology. - #[inline] - pub fn known_peers(&self) -> impl Iterator { - self.store.keys() - } - - /// Returns the addresses stored for a specific peer, and their reputation score. - /// - /// If `include_expired` is true, includes expired addresses that shouldn't be taken into - /// account when dialing. - #[inline] - pub fn addresses_of_peer(&mut self, peer: &PeerId, include_expired: bool) - -> impl Iterator { - let now_st = SystemTime::now(); - let now_is = Instant::now(); - - let mut list = self.store.get_mut(peer).into_iter().flat_map(|p| p.addrs.iter_mut()).filter_map(move |addr| { - let (score, connected) = addr.score_and_is_connected(); - if include_expired || (addr.expires >= now_st && score > 0 && addr.back_off_until < now_is) || connected { - Some((score, &addr.addr)) - } else { - None - } - }).collect::>(); - list.sort_by(|a, b| a.0.cmp(&b.0)); - // TODO: meh, optimize - list.into_iter().map(|(score, addr)| (addr, score)) - } - - /// Marks the given peer as connected through the given endpoint. - pub fn set_connected(&mut self, peer: &PeerId, endpoint: &ConnectedPoint) { - if *peer == self.local_peer_id { - return - } - - let addr = match endpoint { - ConnectedPoint::Dialer { address } => address, - ConnectedPoint::Listener { .. } => return - }; - - let now = Instant::now(); - - // Just making sure that we have an entry for this peer in `store`, but don't use it. - let _ = peer_access(&mut self.store, peer); - - for (peer_in_store, info_in_store) in self.store.iter_mut() { - if peer == peer_in_store { - if let Some(addr) = info_in_store.addrs.iter_mut().find(|a| &a.addr == addr) { - addr.connected_now(CONNECTED_MINIMUM_SCORE); - addr.back_off_until = now; - addr.next_back_off = FIRST_CONNECT_FAIL_BACKOFF; - continue - } - - info_in_store.addrs.push(Addr { - addr: addr.clone(), - expires: SystemTime::now() + EXPIRATION_PUSH_BACK_CONNEC, - back_off_until: now, - next_back_off: FIRST_CONNECT_FAIL_BACKOFF, - score: AddrScore { - connected_since: Some(now), - latest_score_update: now, - score: CONNECTED_MINIMUM_SCORE, - }, - }); - - } else { - // Set the score to 0 for any address that matches the one we connected to. - for addr_in_store in &mut info_in_store.addrs { - if &addr_in_store.addr == addr { - addr_in_store.adjust_score(-(MAX_SCORE as i32)); - } - } - } - } - } - - /// Marks the given peer as disconnected. The endpoint is the one we were connected to. - pub fn set_disconnected(&mut self, _: &PeerId, endpoint: &ConnectedPoint) { - let addr = match endpoint { - ConnectedPoint::Dialer { address } => address, - ConnectedPoint::Listener { .. } => return - }; - - // Note that we used to have different score values here in the past, but there really - // isn't much point in doing so in practice. - let score_diff = -3; - - for info in self.store.values_mut() { - for a in info.addrs.iter_mut() { - if &a.addr == addr { - a.disconnected_now(score_diff); - a.back_off_until = Instant::now() + a.next_back_off; - a.next_back_off = cmp::min(a.next_back_off * FAIL_BACKOFF_MULTIPLIER, MAX_BACKOFF); - let expires_push_back = SystemTime::now() + EXPIRATION_PUSH_BACK_CONNEC; - if a.expires < expires_push_back { - a.expires = expires_push_back; - } - return - } - } - } - } - - /// Indicates to the topology that we failed to reach a node when dialing the given address. - pub fn set_unreachable(&mut self, addr: &Multiaddr) { - for info in self.store.values_mut() { - for a in info.addrs.iter_mut() { - if &a.addr != addr { - continue - } - - // It is possible that we are connected to this address, and that the dial failure - // concerns another peer. - if a.is_connected() { - continue - } - - a.adjust_score(SCORE_DIFF_ON_FAILED_TO_CONNECT); - trace!(target: "sub-libp2p", "Back off for {} = {:?}", addr, a.next_back_off); - a.back_off_until = Instant::now() + a.next_back_off; - a.next_back_off = cmp::min(a.next_back_off * FAIL_BACKOFF_MULTIPLIER, MAX_BACKOFF); - } - } - } -} - -fn peer_access<'a>(store: &'a mut FnvHashMap, peer: &PeerId) -> &'a mut PeerInfo { - // TODO: should be optimizable if HashMap gets a better API - store.entry(peer.clone()).or_insert_with(Default::default) -} - -#[derive(Debug, Clone, Default)] -struct PeerInfo { - /// Addresses of that peer. - addrs: Vec, -} - -#[derive(Debug)] -struct Addr { - /// The multiaddress. - addr: Multiaddr, - /// When the address expires. - expires: SystemTime, - next_back_off: Duration, - /// Don't try to connect to this node until `Instant`. - back_off_until: Instant, - score: AddrScore, -} - -impl Clone for Addr { - fn clone(&self) -> Addr { - Addr { - addr: self.addr.clone(), - expires: self.expires, - next_back_off: self.next_back_off, - back_off_until: self.back_off_until, - score: self.score.clone(), - } - } -} - -#[derive(Debug, Clone)] -struct AddrScore { - /// If connected, contains the moment when we connected. `None` if we're not connected. - connected_since: Option, - /// Score of this address. Potentially needs to be updated based on `latest_score_update`. - score: u32, - /// When we last updated the score. - latest_score_update: Instant, -} - -impl Addr { - /// Sets the addr to connected. If the score is lower than the given value, raises it to this - /// value. - fn connected_now(&mut self, raise_to_min: u32) { - let now = Instant::now(); - Addr::flush(&mut self.score, now); - self.score.connected_since = Some(now); - if self.score.score < raise_to_min { - self.score.score = raise_to_min; - } - } - - /// Applies a modification to the score. - fn adjust_score(&mut self, score_diff: i32) { - Addr::flush(&mut self.score, Instant::now()); - if score_diff >= 0 { - self.score.score = cmp::min(MAX_SCORE, self.score.score + score_diff as u32); - } else { - self.score.score = self.score.score.saturating_sub(-score_diff as u32); - } - } - - /// Sets the addr to disconnected and applies a modification to the score. - fn disconnected_now(&mut self, score_diff: i32) { - Addr::flush(&mut self.score, Instant::now()); - self.score.connected_since = None; - if score_diff >= 0 { - self.score.score = cmp::min(MAX_SCORE, self.score.score + score_diff as u32); - } else { - self.score.score = self.score.score.saturating_sub(-score_diff as u32); - } - } - - /// Returns true if we are connected to this addr. - fn is_connected(&self) -> bool { - self.score.connected_since.is_some() - } - - /// Returns the score, and true if we are connected to this addr. - fn score_and_is_connected(&mut self) -> (u32, bool) { - Addr::flush(&mut self.score, Instant::now()); - let is_connected = self.score.connected_since.is_some(); - (self.score.score, is_connected) - } - - /// Updates `score` and `latest_score_update`, and returns the score. - fn score(&mut self) -> u32 { - Addr::flush(&mut self.score, Instant::now()); - self.score.score - } - - fn flush(score: &mut AddrScore, now: Instant) { - if let Some(connected_since) = score.connected_since { - let potential_score: u32 = div_dur_with_dur(now - connected_since, CONNEC_DURATION_PER_SCORE); - // We flush when we connect to an address. - debug_assert!(score.latest_score_update >= connected_since); - let effective_score: u32 = - div_dur_with_dur(score.latest_score_update - connected_since, CONNEC_DURATION_PER_SCORE); - let to_add = potential_score.saturating_sub(effective_score); - score.score = cmp::min(MAX_SCORE, score.score + to_add); - } - - score.latest_score_update = now; - } -} - -/// Divides a `Duration` with a `Duration`. This exists in the stdlib but isn't stable yet. -// TODO: remove this function once stable -fn div_dur_with_dur(a: Duration, b: Duration) -> u32 { - let a_ms = a.as_secs() * 1_000_000 + u64::from(a.subsec_micros()); - let b_ms = b.as_secs() * 1_000_000 + u64::from(b.subsec_micros()); - (a_ms / b_ms) as u32 -} - -/// Serialized version of a `PeerInfo`. Suitable for storage in the cache file. -#[derive(Debug, Clone, Serialize, Deserialize)] -struct SerializedPeerInfo { - addrs: Vec, -} - -/// Serialized version of an `Addr`. Suitable for storage in the cache file. -#[derive(Debug, Clone, Serialize, Deserialize)] -struct SerializedAddr { - addr: String, - expires: SystemTime, - score: u32, -} - -impl<'a> From<&'a mut Addr> for SerializedAddr { - fn from(addr: &'a mut Addr) -> SerializedAddr { - SerializedAddr { - addr: addr.addr.to_string(), - expires: addr.expires, - score: addr.score(), - } - } -} - -/// Attempts to load storage from a file. -/// Ignores any entry equal to `local_peer_id`. -/// Deletes the file and returns an empty map if the file doesn't exist, cannot be opened -/// or is corrupted. -fn try_load(path: impl AsRef, local_peer_id: &PeerId) -> FnvHashMap { - let path = path.as_ref(); - if !path.exists() { - debug!(target: "sub-libp2p", "Peer storage file {:?} doesn't exist", path); - return Default::default() - } - - let mut file = match fs::File::open(path) { - // TODO: the capacity of the BufReader is kind of arbitrary ; decide better - Ok(f) => BufReader::with_capacity(1024 * 1024, f), - Err(err) => { - warn!(target: "sub-libp2p", "Failed to open peer storage file: {:?}", err); - info!(target: "sub-libp2p", "Deleting peer storage file {:?}", path); - let _ = fs::remove_file(path); - return Default::default() - } - }; - - // We want to support empty files (and treat them as an empty recordset). Unfortunately - // `serde_json` will always produce an error if we do this ("unexpected EOF at line 0 - // column 0"). Therefore we start by reading one byte from the file in order to check - // for EOF. - - let mut first_byte = [0]; - let num_read = match file.read(&mut first_byte) { - Ok(f) => f, - Err(err) => { - // TODO: DRY - warn!(target: "sub-libp2p", "Failed to read peer storage file: {:?}", err); - info!(target: "sub-libp2p", "Deleting peer storage file {:?}", path); - let _ = fs::remove_file(path); - return Default::default() - } - }; - - if num_read == 0 { - // File is empty. - debug!(target: "sub-libp2p", "Peer storage file {:?} is empty", path); - Default::default() - - } else { - let data = Cursor::new(first_byte).chain(file); - match serde_json::from_reader::<_, serde_json::Value>(data) { - Ok(serde_json::Value::Null) => Default::default(), - Ok(serde_json::Value::Object(map)) => - deserialize_tolerant(map.into_iter(), local_peer_id), - Ok(_) | Err(_) => { - // The `Ok(_)` case means that the file doesn't contain a map. - let _ = fs::remove_file(path); - Default::default() - }, - } - } -} - -/// Attempts to turn a deserialized version of the storage into the final version. -/// -/// Skips entries that are invalid or equal to `local_peer_id`. -fn deserialize_tolerant( - iter: impl Iterator, - local_peer_id: &PeerId -) -> FnvHashMap { - let now = Instant::now(); - let now_systime = SystemTime::now(); - - let mut out = FnvHashMap::default(); - for (peer, info) in iter { - let peer: PeerId = match peer.parse() { - Ok(p) => p, - Err(_) => continue, - }; - - if &peer == local_peer_id { - continue - } - - let info: SerializedPeerInfo = match serde_json::from_value(info) { - Ok(i) => i, - Err(_) => continue, - }; - - let mut addrs = Vec::with_capacity(info.addrs.len()); - for addr in info.addrs { - let multiaddr = match addr.addr.parse() { - Ok(a) => a, - Err(_) => continue, - }; - - if addr.expires < now_systime { - continue - } - - addrs.push(Addr { - addr: multiaddr, - expires: addr.expires, - next_back_off: FIRST_CONNECT_FAIL_BACKOFF, - back_off_until: now, - score: AddrScore { - connected_since: None, - score: addr.score, - latest_score_update: now, - }, - }); - } - - if addrs.is_empty() { - continue - } - - out.insert(peer, PeerInfo { addrs }); - } - - out -} - -/// Attempts to turn a deserialized version of the storage into the final version. -/// -/// Skips entries that are invalid or expired. -fn serialize(out: W, map: &mut FnvHashMap) -> Result<(), IoError> { - let now = SystemTime::now(); - let array: FnvHashMap<_, _> = map.iter_mut().filter_map(|(peer, info)| { - if info.addrs.is_empty() { - return None - } - - let peer = peer.to_base58(); - let info = SerializedPeerInfo { - addrs: info.addrs.iter_mut() - .filter_map(|a| if a.expires > now || a.is_connected() { - Some(a.into()) - } else { - None - }) - .collect(), - }; - - Some((peer, info)) - }).collect(); - - serde_json::to_writer_pretty(out, &array) - .map_err(|err| IoError::new(IoErrorKind::Other, err)) -} diff --git a/core/network-libp2p/src/custom_proto/upgrade.rs b/core/network-libp2p/src/custom_proto/upgrade.rs index 292993957d5a417b656a52f9590143864ab2593d..fc9ed5bddb1b70d8149660b496b98abb4a4b2d5b 100644 --- a/core/network-libp2p/src/custom_proto/upgrade.rs +++ b/core/network-libp2p/src/custom_proto/upgrade.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ use crate::ProtocolId; use bytes::Bytes; -use libp2p::core::{Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName}; +use libp2p::core::{Negotiated, Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName}; use libp2p::tokio_codec::Framed; use log::warn; use std::{collections::VecDeque, io, iter, marker::PhantomData, vec::IntoIter as VecIntoIter}; @@ -92,7 +92,7 @@ pub struct RegisteredProtocolSubstream { /// If true, we should call `poll_complete` on the inner sink. requires_poll_complete: bool, /// The underlying substream. - inner: stream::Fuse>>>, + inner: stream::Fuse, UviBytes>>>, /// Id of the protocol. protocol_id: ProtocolId, /// Version of the protocol that was negotiated. @@ -385,10 +385,14 @@ where TSubstream: AsyncRead + AsyncWrite, fn upgrade_inbound( self, - socket: TSubstream, + socket: Negotiated, info: Self::Info, ) -> Self::Future { - let framed = Framed::new(socket, UviBytes::default()); + let framed = { + let mut codec = UviBytes::default(); + codec.set_max_len(16 * 1024 * 1024); // 16 MiB hard limit for packets. + Framed::new(socket, codec) + }; future::ok(RegisteredProtocolSubstream { is_closing: false, @@ -414,7 +418,7 @@ where TSubstream: AsyncRead + AsyncWrite, fn upgrade_outbound( self, - socket: TSubstream, + socket: Negotiated, info: Self::Info, ) -> Self::Future { let framed = Framed::new(socket, UviBytes::default()); @@ -433,99 +437,3 @@ where TSubstream: AsyncRead + AsyncWrite, }) } } - -// Connection upgrade for all the protocols contained in it. -pub struct RegisteredProtocols(pub Vec>); - -impl RegisteredProtocols { - /// Returns the number of protocols. - #[inline] - pub fn len(&self) -> usize { - self.0.len() - } -} - -impl Default for RegisteredProtocols { - fn default() -> Self { - RegisteredProtocols(Vec::new()) - } -} - -impl UpgradeInfo for RegisteredProtocols { - type Info = RegisteredProtocolsName; - type InfoIter = VecIntoIter; - - #[inline] - fn protocol_info(&self) -> Self::InfoIter { - // We concat the lists of `RegisteredProtocol::protocol_names` for - // each protocol. - self.0.iter().enumerate().flat_map(|(n, proto)| - UpgradeInfo::protocol_info(proto) - .map(move |inner| { - RegisteredProtocolsName { - inner, - index: n, - } - }) - ).collect::>().into_iter() - } -} - -impl Clone for RegisteredProtocols { - fn clone(&self) -> Self { - RegisteredProtocols(self.0.clone()) - } -} - -/// Implementation of `ProtocolName` for several custom protocols. -#[derive(Debug, Clone)] -pub struct RegisteredProtocolsName { - /// Inner registered protocol. - inner: RegisteredProtocolName, - /// Index of the protocol in the list of registered custom protocols. - index: usize, -} - -impl ProtocolName for RegisteredProtocolsName { - fn protocol_name(&self) -> &[u8] { - self.inner.protocol_name() - } -} - -impl InboundUpgrade for RegisteredProtocols -where TSubstream: AsyncRead + AsyncWrite, -{ - type Output = as InboundUpgrade>::Output; - type Future = as InboundUpgrade>::Future; - type Error = io::Error; - - #[inline] - fn upgrade_inbound( - self, - socket: TSubstream, - info: Self::Info, - ) -> Self::Future { - self.0.into_iter() - .nth(info.index) - .expect("invalid protocol index ; programmer logic error") - .upgrade_inbound(socket, info.inner) - } -} - -impl OutboundUpgrade for RegisteredProtocols -where TSubstream: AsyncRead + AsyncWrite, -{ - type Output = >::Output; - type Future = >::Future; - type Error = >::Error; - - #[inline] - fn upgrade_outbound( - self, - socket: TSubstream, - info: Self::Info, - ) -> Self::Future { - // Upgrades are symmetrical. - self.upgrade_inbound(socket, info) - } -} diff --git a/core/network-libp2p/src/error.rs b/core/network-libp2p/src/error.rs deleted file mode 100644 index 5466ce2a26966b9abba7abdd39735e229a38d1b3..0000000000000000000000000000000000000000 --- a/core/network-libp2p/src/error.rs +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use error_chain::*; -use std::{io, net, fmt}; - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum DisconnectReason { - DisconnectRequested, - TCPError, - BadProtocol, - UselessPeer, - TooManyPeers, - DuplicatePeer, - IncompatibleProtocol, - NullIdentity, - ClientQuit, - UnexpectedIdentity, - LocalIdentity, - PingTimeout, - Unknown, -} - -impl DisconnectReason { - pub fn from_u8(n: u8) -> DisconnectReason { - match n { - 0 => DisconnectReason::DisconnectRequested, - 1 => DisconnectReason::TCPError, - 2 => DisconnectReason::BadProtocol, - 3 => DisconnectReason::UselessPeer, - 4 => DisconnectReason::TooManyPeers, - 5 => DisconnectReason::DuplicatePeer, - 6 => DisconnectReason::IncompatibleProtocol, - 7 => DisconnectReason::NullIdentity, - 8 => DisconnectReason::ClientQuit, - 9 => DisconnectReason::UnexpectedIdentity, - 10 => DisconnectReason::LocalIdentity, - 11 => DisconnectReason::PingTimeout, - _ => DisconnectReason::Unknown, - } - } -} - -impl fmt::Display for DisconnectReason { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::DisconnectReason::*; - - let msg = match *self { - DisconnectRequested => "disconnect requested", - TCPError => "TCP error", - BadProtocol => "bad protocol", - UselessPeer => "useless peer", - TooManyPeers => "too many peers", - DuplicatePeer => "duplicate peer", - IncompatibleProtocol => "incompatible protocol", - NullIdentity => "null identity", - ClientQuit => "client quit", - UnexpectedIdentity => "unexpected identity", - LocalIdentity => "local identity", - PingTimeout => "ping timeout", - Unknown => "unknown", - }; - - f.write_str(msg) - } -} - -error_chain! { - errors { - #[doc = "Error concerning the network address parsing subsystem."] - AddressParse { - description("Failed to parse network address"), - display("Failed to parse network address"), - } - - #[doc = "Error concerning the network address resolution subsystem."] - AddressResolve(err: Option) { - description("Failed to resolve network address"), - display("Failed to resolve network address {}", err.as_ref().map_or("".to_string(), |e| e.to_string())), - } - - #[doc = "Authentication failure"] - Auth { - description("Authentication failure"), - display("Authentication failure"), - } - - #[doc = "Unrecognised protocol"] - BadProtocol { - description("Bad protocol"), - display("Bad protocol"), - } - - #[doc = "Expired message"] - Expired { - description("Expired message"), - display("Expired message"), - } - - #[doc = "Peer not found"] - PeerNotFound { - description("Peer not found"), - display("Peer not found"), - } - - #[doc = "Peer is disconnected"] - Disconnect(reason: DisconnectReason) { - description("Peer disconnected"), - display("Peer disconnected: {}", reason), - } - - #[doc = "Invalid node id"] - InvalidNodeId { - description("Invalid node id"), - display("Invalid node id"), - } - - #[doc = "Packet size is over the protocol limit"] - OversizedPacket { - description("Packet is too large"), - display("Packet is too large"), - } - - #[doc = "An unknown IO error occurred."] - Io(err: io::Error) { - description("IO Error"), - display("Unexpected IO error: {}", err), - } - } -} - -impl From for Error { - fn from(err: io::Error) -> Self { - Error::from_kind(ErrorKind::Io(err)) - } -} - -impl From for Error { - fn from(_err: net::AddrParseError) -> Self { ErrorKind::AddressParse.into() } -} - -#[test] -fn test_errors() { - assert_eq!(DisconnectReason::ClientQuit, DisconnectReason::from_u8(8)); - let mut r = DisconnectReason::DisconnectRequested; - for i in 0 .. 20 { - r = DisconnectReason::from_u8(i); - } - assert_eq!(DisconnectReason::Unknown, r); -} diff --git a/core/network-libp2p/src/lib.rs b/core/network-libp2p/src/lib.rs index 695de936271b95972741942be0718af1e633e6d5..5b73db636b0f4d9b54db3418eab58f5ec1aceae4 100644 --- a/core/network-libp2p/src/lib.rs +++ b/core/network-libp2p/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,36 +17,76 @@ //! Networking layer of Substrate. mod behaviour; +mod config; mod custom_proto; -mod error; -mod secret; mod service_task; -mod traits; mod transport; +pub use crate::behaviour::Severity; +pub use crate::config::*; pub use crate::custom_proto::{CustomMessage, CustomMessageId, RegisteredProtocol}; -pub use crate::error::{Error, ErrorKind, DisconnectReason}; -pub use crate::secret::obtain_private_key; +pub use crate::config::{NetworkConfiguration, NodeKeyConfig, Secret, NonReservedPeerMode}; pub use crate::service_task::{start_service, Service, ServiceEvent}; -pub use crate::traits::{NetworkConfiguration, NodeIndex, NodeId, NonReservedPeerMode}; -pub use crate::traits::{ProtocolId, Secret, Severity}; -pub use libp2p::{Multiaddr, multiaddr::Protocol, build_multiaddr, PeerId, core::PublicKey}; +pub use libp2p::{Multiaddr, multiaddr, build_multiaddr}; +pub use libp2p::{identity, PeerId, core::PublicKey}; use libp2p::core::nodes::ConnectedPoint; use serde_derive::Serialize; -use std::{collections::{HashMap, HashSet}, time::Duration}; +use std::{collections::{HashMap, HashSet}, error, fmt, time::Duration}; + +/// Protocol / handler id +pub type ProtocolId = [u8; 3]; /// Parses a string address and returns the component, if valid. -pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), Error> { - let mut addr: Multiaddr = addr_str.parse().map_err(|_| ErrorKind::AddressParse)?; +pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> { + let mut addr: Multiaddr = addr_str.parse()?; + let who = match addr.pop() { - Some(Protocol::P2p(key)) => - PeerId::from_multihash(key).map_err(|_| ErrorKind::AddressParse)?, - _ => return Err(ErrorKind::AddressParse.into()), + Some(multiaddr::Protocol::P2p(key)) => PeerId::from_multihash(key) + .map_err(|_| ParseErr::InvalidPeerId)?, + _ => return Err(ParseErr::PeerIdMissing), }; + Ok((who, addr)) } +/// Error that can be generated by `parse_str_addr`. +#[derive(Debug)] +pub enum ParseErr { + /// Error while parsing the multiaddress. + MultiaddrParse(multiaddr::Error), + /// Multihash of the peer ID is invalid. + InvalidPeerId, + /// The peer ID is missing from the address. + PeerIdMissing, +} + +impl fmt::Display for ParseErr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ParseErr::MultiaddrParse(err) => write!(f, "{}", err), + ParseErr::InvalidPeerId => write!(f, "Peer id at the end of the address is invalid"), + ParseErr::PeerIdMissing => write!(f, "Peer id is missing from the address"), + } + } +} + +impl error::Error for ParseErr { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + ParseErr::MultiaddrParse(err) => Some(err), + ParseErr::InvalidPeerId => None, + ParseErr::PeerIdMissing => None, + } + } +} + +impl From for ParseErr { + fn from(err: multiaddr::Error) -> ParseErr { + ParseErr::MultiaddrParse(err) + } +} + /// Returns general information about the networking. /// /// Meant for general diagnostic purposes. @@ -59,13 +99,8 @@ pub struct NetworkState { pub peer_id: String, /// List of addresses the node is currently listening on. pub listened_addresses: HashSet, - // TODO (https://github.com/libp2p/rust-libp2p/issues/978): external_addresses: Vec, - /// If true, we only accept reserved peers. - pub is_reserved_only: bool, - /// PeerIds of the nodes that are marked as reserved. - pub reserved_peers: HashSet, - /// PeerIds of the nodes that are banned, and how long in the seconds the ban remains. - pub banned_peers: HashMap, + /// List of addresses the node knows it can be reached as. + pub external_addresses: HashSet, /// List of node we're connected to. pub connected_peers: HashMap, /// List of node that we know of but that we're not connected to. @@ -74,6 +109,8 @@ pub struct NetworkState { pub average_download_per_sec: u64, /// Uploaded bytes per second averaged over the past few seconds. pub average_upload_per_sec: u64, + /// State of the peerset manager. + pub peerset: serde_json::Value, } #[derive(Debug, PartialEq, Serialize)] @@ -88,17 +125,18 @@ pub struct NetworkStatePeer { /// If true, the peer is "enabled", which means that we try to open Substrate-related protocols /// with this peer. If false, we stick to Kademlia and/or other network-only protocols. pub enabled: bool, - /// List of protocols that we have open with the given peer. - pub open_protocols: HashSet, - /// List of addresses known for this node, with its reputation score. - pub known_addresses: HashMap, + /// If true, the peer is "open", which means that we have a Substrate-related protocol + /// with this peer. + pub open: bool, + /// List of addresses known for this node. + pub known_addresses: HashSet, } #[derive(Debug, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct NetworkStateNotConnectedPeer { - /// List of addresses known for this node, with its reputation score. - pub known_addresses: HashMap, + /// List of addresses known for this node. + pub known_addresses: HashSet, } #[derive(Debug, PartialEq, Serialize)] diff --git a/core/network-libp2p/src/secret.rs b/core/network-libp2p/src/secret.rs deleted file mode 100644 index 17bd053955e5bcb0f4e5ed50b18affde9c9274bb..0000000000000000000000000000000000000000 --- a/core/network-libp2p/src/secret.rs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::NetworkConfiguration; -use libp2p::secio; -use log::{trace, warn}; -use rand::Rng; -use std::io::{Error as IoError, ErrorKind as IoErrorKind, Read, Write}; -use std::{fs, path::Path}; - -// File where the private key is stored. -const SECRET_FILE: &str = "secret"; - -/// Obtains or generates the local private key using the configuration. -pub fn obtain_private_key_from_config( - config: &NetworkConfiguration -) -> Result { - obtain_private_key(&config.use_secret, &config.net_config_path) -} - -/// Obtains or generates the local private key using the configuration. -pub fn obtain_private_key( - secret: &Option<[u8; 32]>, - net_config_path: &Option, -) -> Result { - if let Some(ref secret) = secret { - // Key was specified in the configuration. - secio::SecioKeyPair::secp256k1_raw_key(&secret[..]) - .map_err(|err| IoError::new(IoErrorKind::InvalidData, err)) - } else { - if let Some(ref path) = net_config_path { - fs::create_dir_all(Path::new(path))?; - // Try fetch the key from a the file containing the secret. - let secret_path = Path::new(path).join(SECRET_FILE); - match load_private_key_from_file(&secret_path) { - Ok(s) => Ok(s), - Err(err) => { - // Failed to fetch existing file ; generate a new key - trace!(target: "sub-libp2p", - "Failed to load existing secret key file {:?}, generating new key ; err = {:?}", - secret_path, - err - ); - Ok(gen_key_and_try_write_to_file(&secret_path)) - } - } - - } else { - // No path in the configuration, nothing we can do except generate - // a new key. - let mut key: [u8; 32] = [0; 32]; - rand::rngs::EntropyRng::new().fill(&mut key); - Ok(secio::SecioKeyPair::secp256k1_raw_key(&key) - .expect("randomly-generated key with correct len should always be valid")) - } - } -} - -/// Tries to load a private key from a file located at the given path. -fn load_private_key_from_file

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

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

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

(path: P) -> Result - where P: AsRef { - fs::OpenOptions::new() - .write(true) - .create_new(true) - .open(path) -} diff --git a/core/network-libp2p/src/service_task.rs b/core/network-libp2p/src/service_task.rs index 78d58793434ffd8cd505a937051b0f1fe69b051d..37c4b05eaa3b9269bfe9f3758bd27e9cf10b0d5b 100644 --- a/core/network-libp2p/src/service_task.rs +++ b/core/network-libp2p/src/service_task.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,50 +15,81 @@ // along with Substrate. If not, see . use crate::{ - behaviour::Behaviour, behaviour::BehaviourOut, secret::obtain_private_key_from_config, + behaviour::Behaviour, behaviour::BehaviourOut, transport, NetworkState, NetworkStatePeer, NetworkStateNotConnectedPeer }; -use crate::custom_proto::{CustomMessage, RegisteredProtocol, RegisteredProtocols}; -use crate::{Error, NetworkConfiguration, NodeIndex, ProtocolId, parse_str_addr}; +use crate::custom_proto::{CustomMessage, RegisteredProtocol}; +use crate::{NetworkConfiguration, NonReservedPeerMode, parse_str_addr}; use fnv::FnvHashMap; use futures::{prelude::*, Stream}; -use libp2p::{multiaddr::Protocol, Multiaddr, PeerId, build_multiaddr}; +use libp2p::{multiaddr::Protocol, Multiaddr, core::swarm::NetworkBehaviour, PeerId}; use libp2p::core::{Swarm, nodes::Substream, transport::boxed::Boxed, muxing::StreamMuxerBox}; use libp2p::core::nodes::ConnectedPoint; -use log::{debug, error, info, warn}; -use std::collections::hash_map::Entry; +use log::{debug, info, warn}; use std::fs; -use std::io::{Error as IoError, ErrorKind as IoErrorKind}; -use std::net::SocketAddr; +use std::io::Error as IoError; use std::path::Path; use std::sync::Arc; -use std::time::{Duration, Instant}; -use tokio_timer::Interval; +use std::time::Duration; /// Starts the substrate libp2p service. /// /// Returns a stream that must be polled regularly in order for the networking to function. -pub fn start_service( +pub fn start_service( config: NetworkConfiguration, - registered_custom: TProtos, -) -> Result, Error> -where TProtos: IntoIterator>, - TMessage: CustomMessage + Send + 'static { + registered_custom: RegisteredProtocol, +) -> Result<(Service, Arc), IoError> +where TMessage: CustomMessage + Send + 'static { if let Some(ref path) = config.net_config_path { fs::create_dir_all(Path::new(path))?; } + // List of multiaddresses that we know in the network. + let mut known_addresses = Vec::new(); + let mut bootnodes = Vec::new(); + let mut reserved_nodes = Vec::new(); + + // Process the bootnodes. + for bootnode in config.boot_nodes.iter() { + match parse_str_addr(bootnode) { + Ok((peer_id, addr)) => { + bootnodes.push(peer_id.clone()); + known_addresses.push((peer_id, addr)); + }, + Err(_) => warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode), + } + } + + // Initialize the reserved peers. + for reserved in config.reserved_nodes.iter() { + if let Ok((peer_id, addr)) = parse_str_addr(reserved) { + reserved_nodes.push(peer_id.clone()); + known_addresses.push((peer_id, addr)); + } else { + warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved); + } + } + + // Build the peerset. + let (peerset, peerset_receiver) = substrate_peerset::Peerset::from_config(substrate_peerset::PeersetConfig { + in_peers: config.in_peers, + out_peers: config.out_peers, + bootnodes, + reserved_only: config.non_reserved_mode == NonReservedPeerMode::Deny, + reserved_nodes, + }); + // Private and public keys configuration. - let local_private_key = obtain_private_key_from_config(&config)?; - let local_public_key = local_private_key.to_public_key(); - let local_peer_id = local_public_key.clone().into_peer_id(); + let local_identity = config.node_key.clone().into_keypair()?; + let local_public = local_identity.public(); + let local_peer_id = local_public.clone().into_peer_id(); // Build the swarm. let (mut swarm, bandwidth) = { - let registered_custom = RegisteredProtocols(registered_custom.into_iter().collect()); - let behaviour = Behaviour::new(&config, local_public_key.clone(), registered_custom); - let (transport, bandwidth) = transport::build_transport(local_private_key); + let user_agent = format!("{} ({})", config.client_version, config.node_name); + let behaviour = Behaviour::new(user_agent, local_public, registered_custom, known_addresses, peerset_receiver, config.enable_mdns); + let (transport, bandwidth) = transport::build_transport(local_identity); (Swarm::new(transport, behaviour, local_peer_id.clone()), bandwidth) }; @@ -78,55 +109,14 @@ where TProtos: IntoIterator>, Swarm::add_external_address(&mut swarm, addr.clone()); } - // Connect to the bootnodes. - for bootnode in config.boot_nodes.iter() { - match parse_str_addr(bootnode) { - Ok((peer_id, _)) => { - Swarm::dial(&mut swarm, peer_id); - }, - Err(_) => { - // If the format of the bootstrap node is not a multiaddr, try to parse it as - // a `SocketAddr`. This corresponds to the format `IP:PORT`. - let addr = match bootnode.parse::() { - Ok(SocketAddr::V4(socket)) => build_multiaddr![Ip4(*socket.ip()), Tcp(socket.port())], - Ok(SocketAddr::V6(socket)) => build_multiaddr![Ip6(*socket.ip()), Tcp(socket.port())], - _ => { - warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode); - continue - } - }; - - info!(target: "sub-libp2p", "Dialing {} with no peer id. Keep in mind that doing \ - so is vulnerable to man-in-the-middle attacks.", addr); - if let Err(addr) = Swarm::dial_addr(&mut swarm, addr) { - warn!(target: "sub-libp2p", "Bootstrap address not supported: {}", addr) - } - }, - } - } - - // Initialize the reserved peers. - for reserved in config.reserved_nodes.iter() { - if let Ok((peer_id, addr)) = parse_str_addr(reserved) { - swarm.add_reserved_peer(peer_id.clone(), addr); - Swarm::dial(&mut swarm, peer_id); - } else { - warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved); - } - } - - debug!(target: "sub-libp2p", "Topology started with {} entries", - swarm.num_topology_peers()); - - Ok(Service { + let service = Service { swarm, bandwidth, nodes_info: Default::default(), - index_by_id: Default::default(), - next_node_id: 1, - cleanup: Interval::new_interval(Duration::from_secs(60)), injected_events: Vec::new(), - }) + }; + + Ok((service, peerset)) } /// Event produced by the service. @@ -134,12 +124,8 @@ where TProtos: IntoIterator>, pub enum ServiceEvent { /// A custom protocol substream has been opened with a node. OpenedCustomProtocol { - /// The Id of the node. + /// Identity of the node. peer_id: PeerId, - /// Index of the node. - node_index: NodeIndex, - /// Protocol that has been opened. - protocol: ProtocolId, /// Version of the protocol that was opened. version: u8, /// Node debug info @@ -148,32 +134,16 @@ pub enum ServiceEvent { /// A custom protocol substream has been closed. ClosedCustomProtocol { - /// Index of the node. - node_index: NodeIndex, - /// Protocol that has been closed. - protocol: ProtocolId, - /// Node debug info - debug_info: String, - }, - - /// Sustom protocol substreams has been closed. - /// - /// Same as `ClosedCustomProtocol` but with multiple protocols. - ClosedCustomProtocols { - /// Index of the node. - node_index: NodeIndex, - /// Protocols that have been closed. - protocols: Vec, + /// Identity of the node. + peer_id: PeerId, /// Node debug info debug_info: String, }, /// Receives a message on a custom protocol stream. CustomMessage { - /// Index of the node. - node_index: NodeIndex, - /// Protocol which generated the message. - protocol_id: ProtocolId, + /// Identity of the node. + peer_id: PeerId, /// Message that has been received. message: TMessage, }, @@ -181,9 +151,7 @@ pub enum ServiceEvent { /// The substream with a node is clogged. We should avoid sending data to it if possible. Clogged { /// Index of the node. - node_index: NodeIndex, - /// Protocol which generated the message. - protocol_id: ProtocolId, + peer_id: PeerId, /// Copy of the messages that are within the buffer, for further diagnostic. messages: Vec, }, @@ -198,17 +166,7 @@ pub struct Service where TMessage: CustomMessage { bandwidth: Arc, /// Information about all the nodes we're connected to. - nodes_info: FnvHashMap, - - /// Opposite of `nodes_info`. - index_by_id: FnvHashMap, - - /// Next index to assign to a node. - next_node_id: NodeIndex, - - /// Stream that fires when we need to cleanup and flush the topology, and cleanup the disabled - /// peers. - cleanup: Interval, + nodes_info: FnvHashMap, /// Events to produce on the Stream. injected_events: Vec>, @@ -217,8 +175,6 @@ pub struct Service where TMessage: CustomMessage { /// Information about a node we're connected to. #[derive(Debug)] struct NodeInfo { - /// Hash of the public key of the node. - peer_id: PeerId, /// How we're connected to the node. endpoint: ConnectedPoint, /// Version reported by the remote, or `None` if unknown. @@ -231,20 +187,18 @@ impl Service where TMessage: CustomMessage + Send + 'static { /// Returns a struct containing tons of useful information about the network. pub fn state(&mut self) -> NetworkState { - let now = Instant::now(); - let connected_peers = { let swarm = &mut self.swarm; - self.nodes_info.values().map(move |info| { - let known_addresses = swarm.known_addresses(&info.peer_id) - .map(|(a, s)| (a.clone(), s)).collect(); + self.nodes_info.iter().map(move |(peer_id, info)| { + let known_addresses = NetworkBehaviour::addresses_of_peer(&mut **swarm, peer_id) + .into_iter().collect(); - (info.peer_id.to_base58(), NetworkStatePeer { + (peer_id.to_base58(), NetworkStatePeer { endpoint: info.endpoint.clone().into(), version_string: info.client_version.clone(), latest_ping_time: info.latest_ping, - enabled: swarm.is_enabled(&info.peer_id), - open_protocols: swarm.open_protocols(&info.peer_id).collect(), + enabled: swarm.is_enabled(&peer_id), + open: swarm.is_open(&peer_id), known_addresses, }) }).collect() @@ -252,14 +206,13 @@ where TMessage: CustomMessage + Send + 'static { let not_connected_peers = { let swarm = &mut self.swarm; - let index_by_id = &self.index_by_id; - let list = swarm.known_peers().filter(|p| !index_by_id.contains_key(p)) + let nodes_info = &self.nodes_info; + let list = swarm.known_peers().filter(|p| !nodes_info.contains_key(p)) .cloned().collect::>(); list.into_iter().map(move |peer_id| { - let known_addresses = swarm.known_addresses(&peer_id) - .map(|(a, s)| (a.clone(), s)).collect(); (peer_id.to_base58(), NetworkStateNotConnectedPeer { - known_addresses, + known_addresses: NetworkBehaviour::addresses_of_peer(&mut **swarm, &peer_id) + .into_iter().collect(), }) }).collect() }; @@ -267,16 +220,12 @@ where TMessage: CustomMessage + Send + 'static { NetworkState { peer_id: Swarm::local_peer_id(&self.swarm).to_base58(), listened_addresses: Swarm::listeners(&self.swarm).cloned().collect(), - reserved_peers: self.swarm.reserved_peers().map(|p| p.to_base58()).collect(), - banned_peers: self.swarm.banned_nodes().map(|(p, until)| { - let dur = if until > now { until - now } else { Duration::new(0, 0) }; - (p.to_base58(), dur.as_secs()) - }).collect(), - is_reserved_only: self.swarm.is_reserved_only(), + external_addresses: Swarm::external_addresses(&self.swarm).cloned().collect(), average_download_per_sec: self.bandwidth.average_download_per_sec(), average_upload_per_sec: self.bandwidth.average_upload_per_sec(), connected_peers, not_connected_peers, + peerset: self.swarm.peerset_debug_info(), } } @@ -306,50 +255,19 @@ where TMessage: CustomMessage + Send + 'static { /// Returns the list of all the peers we are connected to. #[inline] - pub fn connected_peers<'a>(&'a self) -> impl Iterator + 'a { - self.nodes_info.keys().cloned() - } - - /// Try to add a reserved peer. - pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) { - self.swarm.add_reserved_peer(peer_id, addr); - } - - /// Try to remove a reserved peer. - /// - /// If we are in reserved mode and we were connected to a node with this peer ID, then this - /// method will disconnect it. - pub fn remove_reserved_peer(&mut self, peer_id: PeerId) { - self.swarm.remove_reserved_peer(peer_id); - } - - /// Start accepting all peers again if we weren't. - #[inline] - pub fn accept_unreserved_peers(&mut self) { - self.swarm.accept_unreserved_peers(); - } - - /// Start refusing non-reserved nodes. Disconnects the nodes that we are connected to that - /// aren't reserved. - pub fn deny_unreserved_peers(&mut self) { - self.swarm.deny_unreserved_peers(); - } - - /// Returns the `PeerId` of a node. - #[inline] - pub fn peer_id_of_node(&self, node_index: NodeIndex) -> Option<&PeerId> { - self.nodes_info.get(&node_index).map(|info| &info.peer_id) + pub fn connected_peers<'a>(&'a self) -> impl Iterator + 'a { + self.nodes_info.keys() } /// Returns the way we are connected to a node. #[inline] - pub fn node_endpoint(&self, node_index: NodeIndex) -> Option<&ConnectedPoint> { - self.nodes_info.get(&node_index).map(|info| &info.endpoint) + pub fn node_endpoint(&self, peer_id: &PeerId) -> Option<&ConnectedPoint> { + self.nodes_info.get(peer_id).map(|info| &info.endpoint) } /// Returns the client version reported by a node. - pub fn node_client_version(&self, node_index: NodeIndex) -> Option<&str> { - self.nodes_info.get(&node_index) + pub fn node_client_version(&self, peer_id: &PeerId) -> Option<&str> { + self.nodes_info.get(peer_id) .and_then(|info| info.client_version.as_ref().map(|s| &s[..])) } @@ -359,116 +277,72 @@ where TMessage: CustomMessage + Send + 'static { /// invalid. pub fn send_custom_message( &mut self, - node_index: NodeIndex, - protocol: ProtocolId, + peer_id: &PeerId, message: TMessage ) { - if let Some(peer_id) = self.nodes_info.get(&node_index).map(|info| &info.peer_id) { - self.swarm.send_custom_message(peer_id, protocol, message); - } else { - warn!(target: "sub-libp2p", "Tried to send message to unknown node: {:}", node_index); - } - } - - /// Disconnects a peer and bans it for a little while. - /// - /// Same as `drop_node`, except that the same peer will not be able to reconnect later. - #[inline] - pub fn ban_node(&mut self, node_index: NodeIndex) { - if let Some(info) = self.nodes_info.get(&node_index) { - info!(target: "sub-libp2p", "Banned {:?} (#{:?}, {:?}, {:?})", info.peer_id, - node_index, info.endpoint, info.client_version); - self.swarm.ban_node(info.peer_id.clone()); - } + self.swarm.send_custom_message(peer_id, message); } /// Disconnects a peer. /// /// This is asynchronous and will not immediately close the peer. /// Corresponding closing events will be generated once the closing actually happens. - #[inline] - pub fn drop_node(&mut self, node_index: NodeIndex) { - if let Some(info) = self.nodes_info.get(&node_index) { - debug!(target: "sub-libp2p", "Dropping {:?} on purpose (#{:?}, {:?}, {:?})", - info.peer_id, node_index, info.endpoint, info.client_version); - self.swarm.drop_node(&info.peer_id); + pub fn drop_node(&mut self, peer_id: &PeerId) { + if let Some(info) = self.nodes_info.get(peer_id) { + debug!(target: "sub-libp2p", "Dropping {:?} on purpose ({:?}, {:?})", + peer_id, info.endpoint, info.client_version); + self.swarm.drop_node(peer_id); } } + /// Adds a hard-coded address for the given peer, that never expires. + pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) { + self.swarm.add_known_address(peer_id, addr) + } + /// Get debug info for a given peer. - pub fn peer_debug_info(&self, who: NodeIndex) -> String { - if let Some(info) = self.nodes_info.get(&who) { - format!("{:?} (version: {:?}) through {:?}", info.peer_id, info.client_version, info.endpoint) + pub fn peer_debug_info(&self, who: &PeerId) -> String { + if let Some(info) = self.nodes_info.get(who) { + format!("{:?} (version: {:?}) through {:?}", who, info.client_version, info.endpoint) } else { "unknown".to_string() } } - /// Returns the `NodeIndex` of a peer, or assigns one if none exists. - fn index_of_peer_or_assign(&mut self, peer: PeerId, endpoint: ConnectedPoint) -> NodeIndex { - match self.index_by_id.entry(peer) { - Entry::Occupied(entry) => { - let id = *entry.get(); - self.nodes_info.insert(id, NodeInfo { - peer_id: entry.key().clone(), - endpoint, - client_version: None, - latest_ping: None, - }); - id - }, - Entry::Vacant(entry) => { - let id = self.next_node_id; - self.next_node_id += 1; - self.nodes_info.insert(id, NodeInfo { - peer_id: entry.key().clone(), - endpoint, - client_version: None, - latest_ping: None, - }); - entry.insert(id); - id - }, - } - } - /// Polls for what happened on the network. fn poll_swarm(&mut self) -> Poll>, IoError> { loop { match self.swarm.poll() { - Ok(Async::Ready(Some(BehaviourOut::CustomProtocolOpen { protocol_id, peer_id, version, endpoint }))) => { - debug!(target: "sub-libp2p", "Opened custom protocol with {:?}", peer_id); - let node_index = self.index_of_peer_or_assign(peer_id.clone(), endpoint); + Ok(Async::Ready(Some(BehaviourOut::CustomProtocolOpen { peer_id, version, endpoint }))) => { + self.nodes_info.insert(peer_id.clone(), NodeInfo { + endpoint, + client_version: None, + latest_ping: None, + }); + let debug_info = self.peer_debug_info(&peer_id); break Ok(Async::Ready(Some(ServiceEvent::OpenedCustomProtocol { peer_id, - node_index, - protocol: protocol_id, version, - debug_info: self.peer_debug_info(node_index), + debug_info, }))) } - Ok(Async::Ready(Some(BehaviourOut::CustomProtocolClosed { protocol_id, peer_id, result }))) => { - debug!(target: "sub-libp2p", "Custom protocol with {:?} closed: {:?}", peer_id, result); - let node_index = *self.index_by_id.get(&peer_id).expect("index_by_id is always kept in sync with the state of the behaviour"); + Ok(Async::Ready(Some(BehaviourOut::CustomProtocolClosed { peer_id, .. }))) => { + let debug_info = self.peer_debug_info(&peer_id); + self.nodes_info.remove(&peer_id); break Ok(Async::Ready(Some(ServiceEvent::ClosedCustomProtocol { - node_index, - protocol: protocol_id, - debug_info: self.peer_debug_info(node_index), + peer_id, + debug_info, }))) } - Ok(Async::Ready(Some(BehaviourOut::CustomMessage { protocol_id, peer_id, message }))) => { - let node_index = *self.index_by_id.get(&peer_id).expect("index_by_id is always kept in sync with the state of the behaviour"); + Ok(Async::Ready(Some(BehaviourOut::CustomMessage { peer_id, message }))) => { break Ok(Async::Ready(Some(ServiceEvent::CustomMessage { - node_index, - protocol_id, + peer_id, message, }))) } - Ok(Async::Ready(Some(BehaviourOut::Clogged { protocol_id, peer_id, messages }))) => { - let node_index = *self.index_by_id.get(&peer_id).expect("index_by_id is always kept in sync with the state of the behaviour"); + Ok(Async::Ready(Some(BehaviourOut::Clogged { peer_id, messages }))) => { break Ok(Async::Ready(Some(ServiceEvent::Clogged { - node_index, - protocol_id, + peer_id, messages, }))) } @@ -476,26 +350,16 @@ where TMessage: CustomMessage + Send + 'static { // Contrary to the other events, this one can happen even on nodes which don't // have any open custom protocol slot. Therefore it is not necessarily in the // list. - if let Some(id) = self.index_by_id.get(&peer_id) { - if let Some(n) = self.nodes_info.get_mut(id) { - n.client_version = Some(info.agent_version); - } else { - error!(target: "sub-libp2p", - "State inconsistency between index_by_id and nodes_info"); - } + if let Some(n) = self.nodes_info.get_mut(&peer_id) { + n.client_version = Some(info.agent_version); } } Ok(Async::Ready(Some(BehaviourOut::PingSuccess { peer_id, ping_time }))) => { // Contrary to the other events, this one can happen even on nodes which don't // have any open custom protocol slot. Therefore it is not necessarily in the // list. - if let Some(id) = self.index_by_id.get(&peer_id) { - if let Some(n) = self.nodes_info.get_mut(id) { - n.latest_ping = Some(ping_time); - } else { - error!(target: "sub-libp2p", - "State inconsistency between index_by_id and nodes_info"); - } + if let Some(n) = self.nodes_info.get_mut(&peer_id) { + n.latest_ping = Some(ping_time); } } Ok(Async::NotReady) => break Ok(Async::NotReady), @@ -504,40 +368,6 @@ where TMessage: CustomMessage + Send + 'static { } } } - - /// Polls the stream that fires when we need to cleanup and flush the topology. - fn poll_cleanup(&mut self) -> Poll>, IoError> { - loop { - match self.cleanup.poll() { - Ok(Async::NotReady) => return Ok(Async::NotReady), - Ok(Async::Ready(Some(_))) => { - debug!(target: "sub-libp2p", "Cleaning and flushing topology"); - self.swarm.cleanup(); - if let Err(err) = self.swarm.flush_topology() { - warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err); - } - debug!(target: "sub-libp2p", "Topology now contains {} nodes", - self.swarm.num_topology_peers()); - } - Ok(Async::Ready(None)) => { - warn!(target: "sub-libp2p", "Topology flush stream ended unexpectedly"); - return Ok(Async::Ready(None)) - } - Err(err) => { - warn!(target: "sub-libp2p", "Topology flush stream errored: {:?}", err); - return Err(IoError::new(IoErrorKind::Other, err)) - } - } - } - } -} - -impl Drop for Service where TMessage: CustomMessage { - fn drop(&mut self) { - if let Err(err) = self.swarm.flush_topology() { - warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err); - } - } } impl Stream for Service where TMessage: CustomMessage + Send + 'static { @@ -554,11 +384,6 @@ impl Stream for Service where TMessage: CustomMessage + Send Async::NotReady => (), } - match self.poll_cleanup()? { - Async::Ready(value) => return Ok(Async::Ready(value)), - Async::NotReady => (), - } - // The only way we reach this is if we went through all the `NotReady` paths above, // ensuring the current task is registered everywhere. Ok(Async::NotReady) diff --git a/core/network-libp2p/src/traits.rs b/core/network-libp2p/src/traits.rs deleted file mode 100644 index fc57a9aef3fab8665920f483dfc7548b8a2cdc8c..0000000000000000000000000000000000000000 --- a/core/network-libp2p/src/traits.rs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::{fmt, iter, net::Ipv4Addr, str}; -use libp2p::{multiaddr::Protocol, Multiaddr, PeerId}; - -/// Protocol / handler id -pub type ProtocolId = [u8; 3]; - -/// Node public key -pub type NodeId = PeerId; - -/// Local (temporary) peer session ID. -pub type NodeIndex = usize; - -/// secio secret key; -pub type Secret = [u8; 32]; - -/// Network service configuration -#[derive(Debug, PartialEq, Clone)] -pub struct NetworkConfiguration { - /// Directory path to store general network configuration. None means nothing will be saved - pub config_path: Option, - /// Directory path to store network-specific configuration. None means nothing will be saved - pub net_config_path: Option, - /// Multiaddresses to listen for incoming connections. - pub listen_addresses: Vec, - /// Multiaddresses to advertise. Detected automatically if empty. - pub public_addresses: Vec, - /// List of initial node addresses - pub boot_nodes: Vec, - /// Use provided node key instead of default - pub use_secret: Option, - /// Maximum allowed number of incoming connections - pub in_peers: u32, - /// Number of outgoing connections we're trying to maintain - pub out_peers: u32, - /// List of reserved node addresses. - pub reserved_nodes: Vec, - /// The non-reserved peer mode. - pub non_reserved_mode: NonReservedPeerMode, - /// Client identifier. Sent over the wire for debugging purposes. - pub client_version: String, - /// Name of the node. Sent over the wire for debugging purposes. - pub node_name: String, -} - -impl Default for NetworkConfiguration { - fn default() -> Self { - NetworkConfiguration::new() - } -} - -impl NetworkConfiguration { - /// Create a new instance of default settings. - pub fn new() -> Self { - NetworkConfiguration { - config_path: None, - net_config_path: None, - listen_addresses: Vec::new(), - public_addresses: Vec::new(), - boot_nodes: Vec::new(), - use_secret: None, - in_peers: 25, - out_peers: 75, - reserved_nodes: Vec::new(), - non_reserved_mode: NonReservedPeerMode::Accept, - client_version: "unknown".into(), - node_name: "unknown".into(), - } - } - - /// Create new default configuration for localhost-only connection with random port (useful for testing) - pub fn new_local() -> NetworkConfiguration { - let mut config = NetworkConfiguration::new(); - config.listen_addresses = vec![ - iter::once(Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) - .chain(iter::once(Protocol::Tcp(0))) - .collect() - ]; - config - } -} - -/// The severity of misbehaviour of a peer that is reported. -#[derive(Debug, PartialEq, Eq, Clone)] -pub enum Severity { - /// Peer is timing out. Could be bad connectivity of overload of work on either of our sides. - Timeout, - /// Peer has been notably useless. E.g. unable to answer a request that we might reasonably consider - /// it could answer. - Useless(String), - /// Peer has behaved in an invalid manner. This doesn't necessarily need to be Byzantine, but peer - /// must have taken concrete action in order to behave in such a way which is wantanly invalid. - Bad(String), -} - -impl fmt::Display for Severity { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self { - Severity::Timeout => write!(fmt, "Timeout"), - Severity::Useless(r) => write!(fmt, "Useless ({})", r), - Severity::Bad(r) => write!(fmt, "Bad ({})", r), - } - } -} - -/// Non-reserved peer modes. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum NonReservedPeerMode { - /// Accept them. This is the default. - Accept, - /// Deny them. - Deny, -} - -impl NonReservedPeerMode { - /// Attempt to parse the peer mode from a string. - pub fn parse(s: &str) -> Option { - match s { - "accept" => Some(NonReservedPeerMode::Accept), - "deny" => Some(NonReservedPeerMode::Deny), - _ => None, - } - } -} diff --git a/core/network-libp2p/src/transport.rs b/core/network-libp2p/src/transport.rs index c095602a11ede122676e26a73d760318f6bff6cc..404fdb6bdaad8d9244ee1dca62ac8e2aa70863d3 100644 --- a/core/network-libp2p/src/transport.rs +++ b/core/network-libp2p/src/transport.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ use futures::prelude::*; use libp2p::{ InboundUpgradeExt, OutboundUpgradeExt, PeerId, Transport, - mplex, secio, yamux, tcp, dns, websocket, bandwidth + mplex, identity, secio, yamux, tcp, dns, websocket, bandwidth }; use libp2p::core::{self, transport::boxed::Boxed, muxing::StreamMuxerBox}; use std::{io, sync::Arc, time::Duration, usize}; @@ -29,7 +29,7 @@ pub use self::bandwidth::BandwidthSinks; /// Returns a `BandwidthSinks` object that allows querying the average bandwidth produced by all /// the connections spawned with this transport. pub fn build_transport( - local_private_key: secio::SecioKeyPair + keypair: identity::Keypair ) -> (Boxed<(PeerId, StreamMuxerBox), io::Error>, Arc) { let mut mplex_config = mplex::MplexConfig::new(); mplex_config.max_buffer_len_behaviour(mplex::MaxBufferBehaviour::Block); @@ -42,7 +42,7 @@ pub fn build_transport( // TODO: rework the transport creation (https://github.com/libp2p/rust-libp2p/issues/783) let transport = transport - .with_upgrade(secio::SecioConfig::new(local_private_key)) + .with_upgrade(secio::SecioConfig::new(keypair)) .and_then(move |out, endpoint| { let peer_id = out.remote_key.into_peer_id(); let peer_id2 = peer_id.clone(); diff --git a/core/network-libp2p/tests/test.rs b/core/network-libp2p/tests/test.rs index 979cf9b0445097d03871079d66d809e937733e95..437f65118455d648129c5027f06ac64e8858a853 100644 --- a/core/network-libp2p/tests/test.rs +++ b/core/network-libp2p/tests/test.rs @@ -16,8 +16,8 @@ use futures::{future, stream, prelude::*, try_ready}; use rand::seq::SliceRandom; -use std::{io, iter}; -use substrate_network_libp2p::{CustomMessage, Protocol, ServiceEvent, build_multiaddr}; +use std::io; +use substrate_network_libp2p::{CustomMessage, multiaddr::Protocol, ServiceEvent, build_multiaddr}; /// Builds two services. The second one and further have the first one as its bootstrap node. /// This is to be used only for testing, and a panic will happen if something goes wrong. @@ -41,7 +41,7 @@ fn build_nodes(num: usize) -> Vec> }; let proto = substrate_network_libp2p::RegisteredProtocol::new(*b"tst", &[1]); - result.push(substrate_network_libp2p::start_service(config, iter::once(proto)).unwrap()); + result.push(substrate_network_libp2p::start_service(config, proto).unwrap().0); } result @@ -58,8 +58,7 @@ fn basic_two_nodes_connectivity() { let fut1 = future::poll_fn(move || -> io::Result<_> { match try_ready!(service1.poll()) { - Some(ServiceEvent::OpenedCustomProtocol { protocol, version, .. }) => { - assert_eq!(protocol, *b"tst"); + Some(ServiceEvent::OpenedCustomProtocol { version, .. }) => { assert_eq!(version, 1); Ok(Async::Ready(())) }, @@ -69,8 +68,7 @@ fn basic_two_nodes_connectivity() { let fut2 = future::poll_fn(move || -> io::Result<_> { match try_ready!(service2.poll()) { - Some(ServiceEvent::OpenedCustomProtocol { protocol, version, .. }) => { - assert_eq!(protocol, *b"tst"); + Some(ServiceEvent::OpenedCustomProtocol { version, .. }) => { assert_eq!(version, 1); Ok(Async::Ready(())) }, @@ -101,9 +99,9 @@ fn two_nodes_transfer_lots_of_packets() { let fut1 = future::poll_fn(move || -> io::Result<_> { loop { match try_ready!(service1.poll()) { - Some(ServiceEvent::OpenedCustomProtocol { node_index, protocol, .. }) => { + Some(ServiceEvent::OpenedCustomProtocol { peer_id, .. }) => { for n in 0 .. NUM_PACKETS { - service1.send_custom_message(node_index, protocol, vec![(n % 256) as u8]); + service1.send_custom_message(&peer_id, vec![(n % 256) as u8]); } }, _ => panic!(), @@ -133,8 +131,6 @@ fn two_nodes_transfer_lots_of_packets() { } #[test] -#[ignore] -// TODO: remove ignore once this test it fixed. #1777 fn many_nodes_connectivity() { // Creates many nodes, then make sure that they are all connected to each other. // Note: if you increase this number, keep in mind that there's a limit to the number of @@ -231,9 +227,9 @@ fn basic_two_nodes_requests_in_parallel() { let fut1 = future::poll_fn(move || -> io::Result<_> { loop { match try_ready!(service1.poll()) { - Some(ServiceEvent::OpenedCustomProtocol { node_index, protocol, .. }) => { + Some(ServiceEvent::OpenedCustomProtocol { peer_id, .. }) => { for msg in to_send.drain(..) { - service1.send_custom_message(node_index, protocol, msg); + service1.send_custom_message(&peer_id, msg); } }, _ => panic!(), diff --git a/core/network/Cargo.toml b/core/network/Cargo.toml index 4d78eeb60263d8eac5cf4f1cafb51a2b7dad3e2e..bed1946fa8f72655f50bc2e33c18f25b561a8e91 100644 --- a/core/network/Cargo.toml +++ b/core/network/Cargo.toml @@ -25,8 +25,9 @@ primitives = { package = "substrate-primitives", path = "../../core/primitives" consensus = { package = "substrate-consensus-common", path = "../../core/consensus/common" } client = { package = "substrate-client", path = "../../core/client" } runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } -parity-codec = { version = "3.1", features = ["derive"] } +parity-codec = { version = "3.2", features = ["derive"] } network_libp2p = { package = "substrate-network-libp2p", path = "../../core/network-libp2p" } +peerset = { package = "substrate-peerset", path = "../../core/peerset" } tokio = "0.1.11" keyring = { package = "substrate-keyring", path = "../../core/keyring", optional = true } test_client = { package = "substrate-test-client", path = "../../core/test-client", optional = true } diff --git a/core/network/src/blocks.rs b/core/network/src/blocks.rs index b0fadca7dae8656d29abecf5d7a137df44c3aba9..60c6886f09f27c210876825bcc4fa364235676e2 100644 --- a/core/network/src/blocks.rs +++ b/core/network/src/blocks.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ use std::ops::Range; use std::collections::{HashMap, BTreeMap}; use std::collections::hash_map::Entry; use log::trace; -use network_libp2p::NodeIndex; +use network_libp2p::PeerId; use runtime_primitives::traits::{Block as BlockT, NumberFor, As}; use crate::message; @@ -32,7 +32,7 @@ pub struct BlockData { /// The Block Message from the wire pub block: message::BlockData, /// The peer, we received this from - pub origin: Option, + pub origin: Option, } #[derive(Debug)] @@ -58,7 +58,7 @@ impl BlockRangeState { pub struct BlockCollection { /// Downloaded blocks. blocks: BTreeMap, BlockRangeState>, - peer_requests: HashMap>, + peer_requests: HashMap>, } impl BlockCollection { @@ -77,7 +77,7 @@ impl BlockCollection { } /// Insert a set of blocks into collection. - pub fn insert(&mut self, start: NumberFor, blocks: Vec>, who: NodeIndex) { + pub fn insert(&mut self, start: NumberFor, blocks: Vec>, who: PeerId) { if blocks.is_empty() { return; } @@ -96,11 +96,11 @@ impl BlockCollection { } self.blocks.insert(start, BlockRangeState::Complete(blocks.into_iter() - .map(|b| BlockData { origin: Some(who), block: b }).collect())); + .map(|b| BlockData { origin: Some(who.clone()), block: b }).collect())); } /// Returns a set of block hashes that require a header download. The returned set is marked as being downloaded. - pub fn needed_blocks(&mut self, who: NodeIndex, count: usize, peer_best: NumberFor, common: NumberFor) -> Option>> { + pub fn needed_blocks(&mut self, who: PeerId, count: usize, peer_best: NumberFor, common: NumberFor) -> Option>> { // First block number that we need to download let first_different = common + As::sa(1); let count = As::sa(count as u64); @@ -166,8 +166,8 @@ impl BlockCollection { drained } - pub fn clear_peer_download(&mut self, who: NodeIndex) { - match self.peer_requests.entry(who) { + pub fn clear_peer_download(&mut self, who: &PeerId) { + match self.peer_requests.entry(who.clone()) { Entry::Occupied(entry) => { let start = entry.remove(); let remove = match self.blocks.get_mut(&start) { @@ -195,7 +195,7 @@ impl BlockCollection { #[cfg(test)] mod test { use super::{BlockCollection, BlockData, BlockRangeState}; - use crate::message; + use crate::{message, PeerId}; use runtime_primitives::testing::{Block as RawBlock, ExtrinsicWrapper}; use primitives::H256; @@ -221,7 +221,7 @@ mod test { fn create_clear() { let mut bc = BlockCollection::new(); assert!(is_empty(&bc)); - bc.insert(1, generate_blocks(100), 0); + bc.insert(1, generate_blocks(100), PeerId::random()); assert!(!is_empty(&bc)); bc.clear(); assert!(is_empty(&bc)); @@ -231,43 +231,43 @@ mod test { fn insert_blocks() { let mut bc = BlockCollection::new(); assert!(is_empty(&bc)); - let peer0 = 0; - let peer1 = 1; - let peer2 = 2; + let peer0 = PeerId::random(); + let peer1 = PeerId::random(); + let peer2 = PeerId::random(); let blocks = generate_blocks(150); - assert_eq!(bc.needed_blocks(peer0, 40, 150, 0), Some(1 .. 41)); - assert_eq!(bc.needed_blocks(peer1, 40, 150, 0), Some(41 .. 81)); - assert_eq!(bc.needed_blocks(peer2, 40, 150, 0), Some(81 .. 121)); + assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0), Some(1 .. 41)); + assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0), Some(41 .. 81)); + assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 0), Some(81 .. 121)); - bc.clear_peer_download(peer1); - bc.insert(41, blocks[41..81].to_vec(), peer1); + bc.clear_peer_download(&peer1); + bc.insert(41, blocks[41..81].to_vec(), peer1.clone()); assert_eq!(bc.drain(1), vec![]); - assert_eq!(bc.needed_blocks(peer1, 40, 150, 0), Some(121 .. 151)); - bc.clear_peer_download(peer0); - bc.insert(1, blocks[1..11].to_vec(), peer0); + assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0), Some(121 .. 151)); + bc.clear_peer_download(&peer0); + bc.insert(1, blocks[1..11].to_vec(), peer0.clone()); - assert_eq!(bc.needed_blocks(peer0, 40, 150, 0), Some(11 .. 41)); - assert_eq!(bc.drain(1), blocks[1..11].iter().map(|b| BlockData { block: b.clone(), origin: Some(0) }).collect::>()); + assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0), Some(11 .. 41)); + assert_eq!(bc.drain(1), blocks[1..11].iter().map(|b| BlockData { block: b.clone(), origin: Some(peer0.clone()) }).collect::>()); - bc.clear_peer_download(peer0); - bc.insert(11, blocks[11..41].to_vec(), peer0); + bc.clear_peer_download(&peer0); + bc.insert(11, blocks[11..41].to_vec(), peer0.clone()); let drained = bc.drain(12); - assert_eq!(drained[..30], blocks[11..41].iter().map(|b| BlockData { block: b.clone(), origin: Some(0) }).collect::>()[..]); - assert_eq!(drained[30..], blocks[41..81].iter().map(|b| BlockData { block: b.clone(), origin: Some(1) }).collect::>()[..]); + assert_eq!(drained[..30], blocks[11..41].iter().map(|b| BlockData { block: b.clone(), origin: Some(peer0.clone()) }).collect::>()[..]); + assert_eq!(drained[30..], blocks[41..81].iter().map(|b| BlockData { block: b.clone(), origin: Some(peer1.clone()) }).collect::>()[..]); - bc.clear_peer_download(peer2); - assert_eq!(bc.needed_blocks(peer2, 40, 150, 80), Some(81 .. 121)); - bc.clear_peer_download(peer2); - bc.insert(81, blocks[81..121].to_vec(), peer2); - bc.clear_peer_download(peer1); - bc.insert(121, blocks[121..150].to_vec(), peer1); + bc.clear_peer_download(&peer2); + assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 80), Some(81 .. 121)); + bc.clear_peer_download(&peer2); + bc.insert(81, blocks[81..121].to_vec(), peer2.clone()); + bc.clear_peer_download(&peer1); + bc.insert(121, blocks[121..150].to_vec(), peer1.clone()); assert_eq!(bc.drain(80), vec![]); let drained = bc.drain(81); - assert_eq!(drained[..40], blocks[81..121].iter().map(|b| BlockData { block: b.clone(), origin: Some(2) }).collect::>()[..]); - assert_eq!(drained[40..], blocks[121..150].iter().map(|b| BlockData { block: b.clone(), origin: Some(1) }).collect::>()[..]); + assert_eq!(drained[..40], blocks[81..121].iter().map(|b| BlockData { block: b.clone(), origin: Some(peer2.clone()) }).collect::>()[..]); + assert_eq!(drained[40..], blocks[121..150].iter().map(|b| BlockData { block: b.clone(), origin: Some(peer1.clone()) }).collect::>()[..]); } #[test] @@ -280,7 +280,8 @@ mod test { let blocks = generate_blocks(10).into_iter().map(|b| BlockData { block: b, origin: None }).collect(); bc.blocks.insert(114305, BlockRangeState::Complete(blocks)); - assert_eq!(bc.needed_blocks(0, 128, 10000, 000), Some(1 .. 100)); - assert_eq!(bc.needed_blocks(0, 128, 10000, 600), Some(100 + 128 .. 100 + 128 + 128)); + let peer0 = PeerId::random(); + assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 000), Some(1 .. 100)); + assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 600), Some(100 + 128 .. 100 + 128 + 128)); } } diff --git a/core/network/src/chain.rs b/core/network/src/chain.rs index 51057df4dc9b5bcc639c086730be9adae0d7dce4..92236e7c6384860a58ff93751b1483b306f979cf 100644 --- a/core/network/src/chain.rs +++ b/core/network/src/chain.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,18 +20,13 @@ use client::{self, Client as SubstrateClient, ClientInfo, BlockStatus, CallExecu use client::error::Error; use client::light::fetcher::ChangesProof; use consensus::{BlockImport, Error as ConsensusError}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, AuthorityIdFor}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; use runtime_primitives::generic::{BlockId}; -use consensus::{ImportBlock, ImportResult}; use runtime_primitives::Justification; use primitives::{H256, Blake2Hasher, storage::StorageKey}; /// Local client abstraction for the network. pub trait Client: Send + Sync { - /// Import a new block. Parent is supposed to be existing in the blockchain. - fn import(&self, block: ImportBlock, new_authorities: Option>>) - -> Result; - /// Get blockchain info. fn info(&self) -> Result, Error>; @@ -80,12 +75,6 @@ impl Client for SubstrateClient where Block: BlockT, RA: Send + Sync { - fn import(&self, block: ImportBlock, new_authorities: Option>>) - -> Result - { - (self as &SubstrateClient).import_block(block, new_authorities) - } - fn info(&self) -> Result, Error> { (self as &SubstrateClient).info() } diff --git a/core/network/src/config.rs b/core/network/src/config.rs index b7a8ede0ec31ce02edce3235bee2dee3cc607d65..2491fc21c4c0746747a6a49d8341a3393a886c88 100644 --- a/core/network/src/config.rs +++ b/core/network/src/config.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ //! Configuration for the networking layer of Substrate. -pub use network_libp2p::{NonReservedPeerMode, NetworkConfiguration, Secret}; +pub use network_libp2p::{NonReservedPeerMode, NetworkConfiguration, NodeKeyConfig, Secret}; use bitflags::bitflags; use crate::chain::Client; diff --git a/core/network/src/consensus_gossip.rs b/core/network/src/consensus_gossip.rs index 8ed6f8ba58f75ac526081542b77a152555e9744c..433dd5b795fd72151ce58922d22b8d08e3f2f2e0 100644 --- a/core/network/src/consensus_gossip.rs +++ b/core/network/src/consensus_gossip.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,20 +19,18 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; -use std::time::{Instant, Duration}; use log::{trace, debug}; use futures::sync::mpsc; use rand::{self, seq::SliceRandom}; use lru_cache::LruCache; -use network_libp2p::{Severity, NodeIndex}; +use network_libp2p::{Severity, PeerId}; use runtime_primitives::traits::{Block as BlockT, Hash, HashFor}; +use runtime_primitives::ConsensusEngineId; pub use crate::message::generic::{Message, ConsensusMessage}; use crate::protocol::Context; use crate::config::Roles; -use crate::ConsensusEngineId; // FIXME: Add additional spam/DoS attack protection: https://github.com/paritytech/substrate/issues/1115 -const MESSAGE_LIFETIME: Duration = Duration::from_secs(120); const KNOWN_MESSAGES_CACHE_SIZE: usize = 4096; struct PeerConsensus { @@ -50,7 +48,6 @@ struct MessageEntry { message_hash: B::Hash, topic: B::Hash, message: ConsensusMessage, - timestamp: Instant, status: Status, } @@ -82,7 +79,7 @@ pub trait Validator { /// Consensus network protocol handler. Manages statements and candidate requests. pub struct ConsensusGossip { - peers: HashMap>, + peers: HashMap>, live_message_sinks: HashMap<(ConsensusEngineId, B::Hash), Vec>>>, messages: Vec>, known_messages: LruCache, @@ -112,18 +109,16 @@ impl ConsensusGossip { } /// Handle new connected peer. - pub fn new_peer(&mut self, protocol: &mut Context, who: NodeIndex, roles: Roles) { + pub fn new_peer(&mut self, protocol: &mut Context, who: PeerId, roles: Roles) { if roles.intersects(Roles::AUTHORITY) { trace!(target:"gossip", "Registering {:?} {}", roles, who); - let now = Instant::now(); // Send out all known messages to authorities. let mut known_messages = HashSet::new(); for entry in self.messages.iter() { - if entry.timestamp + MESSAGE_LIFETIME < now { continue } if let Status::Future = entry.status { continue } known_messages.insert(entry.message_hash); - protocol.send_message(who, Message::Consensus(entry.message.clone())); + protocol.send_message(who.clone(), Message::Consensus(entry.message.clone())); } self.peers.insert(who, PeerConsensus { known_messages, @@ -143,13 +138,14 @@ impl ConsensusGossip { protocol: &mut Context, message_hash: B::Hash, get_message: F, + force: bool, ) where F: Fn() -> ConsensusMessage, { let mut non_authorities: Vec<_> = self.peers.iter() .filter_map(|(id, ref peer)| - if !peer.is_authority && !peer.known_messages.contains(&message_hash) { - Some(*id) + if !peer.is_authority && (!peer.known_messages.contains(&message_hash) || force) { + Some(id.clone()) } else { None } @@ -165,17 +161,15 @@ impl ConsensusGossip { for (id, ref mut peer) in self.peers.iter_mut() { if peer.is_authority { - if peer.known_messages.insert(message_hash.clone()) { + if peer.known_messages.insert(message_hash.clone()) || force { let message = get_message(); trace!(target:"gossip", "Propagating to authority {}: {:?}", id, message); - protocol.send_message(*id, Message::Consensus(message)); + protocol.send_message(id.clone(), Message::Consensus(message)); } } else if non_authorities.contains(&id) { - if peer.known_messages.insert(message_hash.clone()) { - let message = get_message(); - trace!(target:"gossip", "Propagating to {}: {:?}", id, message); - protocol.send_message(*id, Message::Consensus(message)); - } + let message = get_message(); + trace!(target:"gossip", "Propagating to {}: {:?}", id, message); + protocol.send_message(id.clone(), Message::Consensus(message)); } } } @@ -194,14 +188,13 @@ impl ConsensusGossip { topic, message_hash, message: get_message(), - timestamp: Instant::now(), status, }); } } /// Call when a peer has been disconnected to stop tracking gossip status. - pub fn peer_disconnected(&mut self, _protocol: &mut Context, who: NodeIndex) { + pub fn peer_disconnected(&mut self, _protocol: &mut Context, who: PeerId) { self.peers.remove(&who); } @@ -218,7 +211,6 @@ impl ConsensusGossip { let known_messages = &mut self.known_messages; let before = self.messages.len(); let validators = &self.validators; - let now = Instant::now(); let mut check_fns = HashMap::new(); let mut message_expired = move |entry: &MessageEntry| { @@ -234,9 +226,7 @@ impl ConsensusGossip { (check_fn)(entry.topic, &entry.message.data) }; - self.messages.retain(|entry| - entry.timestamp + MESSAGE_LIFETIME >= now && !message_expired(entry) - ); + self.messages.retain(|entry| !message_expired(entry)); trace!(target: "gossip", "Cleaned up {} stale messages, {} left ({} known)", before - self.messages.len(), @@ -301,9 +291,8 @@ impl ConsensusGossip { pub fn on_incoming( &mut self, protocol: &mut Context, - who: NodeIndex, + who: PeerId, message: ConsensusMessage, - is_syncing: bool, ) -> Option<(B::Hash, ConsensusMessage)> { let message_hash = HashFor::::hash(&message.data[..]); @@ -316,7 +305,7 @@ impl ConsensusGossip { use std::collections::hash_map::Entry; let engine_id = message.engine_id; - //validate the message + // validate the message let (topic, status) = match self.validators.get(&engine_id) .map(|v| v.validate(&message.data)) { @@ -332,23 +321,17 @@ impl ConsensusGossip { }, Some(ValidationResult::Expired) => { trace!(target:"gossip", "Ignored expired message from {}", who); - if !is_syncing { - protocol.report_peer( - who, - Severity::Useless(format!("Sent expired consensus message")), - ); - } return None; - } + }, None => { protocol.report_peer( - who, + who.clone(), Severity::Useless(format!("Sent unknown consensus engine id")), ); trace!(target:"gossip", "Unknown message engine id {:?} from {}", engine_id, who); return None; - } + }, }; peer.known_messages.insert(message_hash); @@ -364,7 +347,7 @@ impl ConsensusGossip { entry.remove_entry(); } } - self.multicast_inner(protocol, message_hash, topic, status, || message.clone()); + self.multicast_inner(protocol, message_hash, topic, status, || message.clone(), false); Some((topic, message)) } else { trace!(target:"gossip", "Ignored statement from unregistered peer {}", who); @@ -378,9 +361,10 @@ impl ConsensusGossip { protocol: &mut Context, topic: B::Hash, message: ConsensusMessage, + force: bool, ) { let message_hash = HashFor::::hash(&message.data); - self.multicast_inner(protocol, message_hash, topic, Status::Live, || message.clone()); + self.multicast_inner(protocol, message_hash, topic, Status::Live, || message.clone(), force); } fn multicast_inner( @@ -390,25 +374,20 @@ impl ConsensusGossip { topic: B::Hash, status: Status, get_message: F, + force: bool, ) where F: Fn() -> ConsensusMessage { self.register_message(message_hash, topic, status, &get_message); if let Status::Live = status { - self.propagate(protocol, message_hash, get_message); + self.propagate(protocol, message_hash, get_message, force); } } - - /// Note new consensus session. - pub fn new_session(&mut self, _parent_hash: B::Hash) { - self.collect_garbage(); - } } #[cfg(test)] mod tests { use runtime_primitives::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; - use std::time::Instant; use futures::Stream; use super::*; @@ -416,13 +395,12 @@ mod tests { type Block = RawBlock>; macro_rules! push_msg { - ($consensus:expr, $topic:expr, $hash: expr, $now: expr, $m:expr) => { + ($consensus:expr, $topic:expr, $hash: expr, $m:expr) => { if $consensus.known_messages.insert($hash, ()).is_none() { $consensus.messages.push(MessageEntry { topic: $topic, message_hash: $hash, - message: ConsensusMessage { data: $m, engine_id: [0, 0, 0, 0]}, - timestamp: $now, + message: ConsensusMessage { data: $m, engine_id: [0, 0, 0, 0] }, status: Status::Live, }); } @@ -457,9 +435,8 @@ mod tests { let m1 = vec![1, 2, 3]; let m2 = vec![4, 5, 6]; - let now = Instant::now(); - push_msg!(consensus, prev_hash, m1_hash, now, m1); - push_msg!(consensus, best_hash, m2_hash, now, m2.clone()); + push_msg!(consensus, prev_hash, m1_hash, m1); + push_msg!(consensus, best_hash, m2_hash, m2.clone()); consensus.known_messages.insert(m1_hash, ()); consensus.known_messages.insert(m2_hash, ()); @@ -477,15 +454,6 @@ mod tests { // known messages are only pruned based on size. assert_eq!(consensus.known_messages.len(), 2); assert!(consensus.known_messages.contains_key(&m2_hash)); - - // make timestamp expired, but the message is still kept as known - consensus.messages.clear(); - consensus.known_messages.clear(); - consensus.register_validator(test_engine_id, Arc::new(AllowAll)); - push_msg!(consensus, best_hash, m2_hash, now - MESSAGE_LIFETIME, m2.clone()); - consensus.collect_garbage(); - assert!(consensus.messages.is_empty()); - assert_eq!(consensus.known_messages.len(), 1); } #[test] diff --git a/core/network/src/error.rs b/core/network/src/error.rs index 36b2b90a5d78e7e9d4dbef9778c77022ef9cee43..bf687f99698e91a796c3edbf5af11b8314a3b221 100644 --- a/core/network/src/error.rs +++ b/core/network/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,12 +22,10 @@ use error_chain::*; use std::io::Error as IoError; -use network_libp2p::Error as NetworkError; use client; error_chain! { foreign_links { - Network(NetworkError) #[doc = "Devp2p error."]; Io(IoError) #[doc = "IO error."]; } diff --git a/core/network/src/lib.rs b/core/network/src/lib.rs index 8e00a66e63b023953cc17322bcc0b9b39fda0d12..02004945178793062e06b700343719e4368d436d 100644 --- a/core/network/src/lib.rs +++ b/core/network/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -42,11 +42,13 @@ pub use service::{Service, FetchFuture, TransactionPool, ManageNetwork, NetworkM pub use protocol::{ProtocolStatus, PeerInfo, Context}; pub use sync::{Status as SyncStatus, SyncState}; pub use network_libp2p::{ - NodeIndex, ProtocolId, Severity, Protocol, Multiaddr, + identity, multiaddr, + ProtocolId, Severity, Multiaddr, NetworkState, NetworkStatePeer, NetworkStateNotConnectedPeer, NetworkStatePeerEndpoint, - obtain_private_key, build_multiaddr, PeerId, PublicKey + NodeKeyConfig, Secret, Secp256k1Secret, Ed25519Secret, + build_multiaddr, PeerId, PublicKey }; -pub use message::{generic as generic_message, RequestId, Status as StatusMessage, ConsensusEngineId}; +pub use message::{generic as generic_message, RequestId, Status as StatusMessage}; pub use error::Error; pub use on_demand::{OnDemand, OnDemandService, RemoteResponse}; #[doc(hidden)] diff --git a/core/network/src/message.rs b/core/network/src/message.rs index 98860cae887d6b4aa9f75cc0f093d12f2bac0831..d0f697b8ab40672ce43349df926eacb22c0e8e8c 100644 --- a/core/network/src/message.rs +++ b/core/network/src/message.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ //! Network packet message types. These get serialized and put into the lower level protocol payload. use bitflags::bitflags; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; +use runtime_primitives::{ConsensusEngineId, traits::{Block as BlockT, Header as HeaderT}}; use parity_codec::{Encode, Decode, Input, Output}; pub use self::generic::{ BlockAnnounce, RemoteCallRequest, RemoteReadRequest, @@ -29,9 +29,6 @@ pub use self::generic::{ /// A unique ID of a request. pub type RequestId = u64; -/// Consensus engine unique ID. -pub type ConsensusEngineId = [u8; 4]; - /// Type alias for using the message type using block type parameters. pub type Message = generic::Message< ::Header, @@ -69,7 +66,7 @@ pub type BlockResponse = generic::BlockResponse< /// A set of transactions. pub type Transactions = Vec; -/// Bits of block data and associated artefacts to request. +/// Bits of block data and associated artifacts to request. bitflags! { /// Node roles bitmask. pub struct BlockAttributes: u8 { diff --git a/core/network/src/on_demand.rs b/core/network/src/on_demand.rs index 62868693598882c0a457f6db4df7ce6a96a4b28d..6a890144655c9d7656004b60a60d01c8c66f5090 100644 --- a/core/network/src/on_demand.rs +++ b/core/network/src/on_demand.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -29,7 +29,7 @@ use client::{error::{Error as ClientError, ErrorKind as ClientErrorKind}}; use client::light::fetcher::{Fetcher, FetchChecker, RemoteHeaderRequest, RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof}; use crate::message; -use network_libp2p::{Severity, NodeIndex}; +use network_libp2p::{Severity, PeerId}; use crate::config::Roles; use crate::service::{NetworkChan, NetworkMsg}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; @@ -42,13 +42,13 @@ const RETRY_COUNT: usize = 1; /// On-demand service API. pub trait OnDemandService: Send + Sync { /// When new node is connected. - fn on_connect(&self, peer: NodeIndex, role: Roles, best_number: NumberFor); + fn on_connect(&self, peer: PeerId, role: Roles, best_number: NumberFor); /// When block is announced by the peer. - fn on_block_announce(&self, peer: NodeIndex, best_number: NumberFor); + fn on_block_announce(&self, peer: PeerId, best_number: NumberFor); /// When node is disconnected. - fn on_disconnect(&self, peer: NodeIndex); + fn on_disconnect(&self, peer: PeerId); /// Maintain peers requests. fn maintain_peers(&self); @@ -56,20 +56,20 @@ pub trait OnDemandService: Send + Sync { /// When header response is received from remote node. fn on_remote_header_response( &self, - peer: NodeIndex, + peer: PeerId, response: message::RemoteHeaderResponse ); /// When read response is received from remote node. - fn on_remote_read_response(&self, peer: NodeIndex, response: message::RemoteReadResponse); + fn on_remote_read_response(&self, peer: PeerId, response: message::RemoteReadResponse); /// When call response is received from remote node. - fn on_remote_call_response(&self, peer: NodeIndex, response: message::RemoteCallResponse); + fn on_remote_call_response(&self, peer: PeerId, response: message::RemoteCallResponse); /// When changes response is received from remote node. fn on_remote_changes_response( &self, - peer: NodeIndex, + peer: PeerId, response: message::RemoteChangesResponse, Block::Hash> ); } @@ -90,9 +90,9 @@ pub struct RemoteResponse { struct OnDemandCore { next_request_id: u64, pending_requests: VecDeque>, - active_peers: LinkedHashMap>, - idle_peers: VecDeque, - best_blocks: HashMap>, + active_peers: LinkedHashMap>, + idle_peers: VecDeque, + best_blocks: HashMap>, } struct Request { @@ -170,13 +170,13 @@ impl OnDemand where } /// Try to accept response from given peer. - fn accept_response) -> Accept>(&self, rtype: &str, peer: NodeIndex, request_id: u64, try_accept: F) { + fn accept_response) -> Accept>(&self, rtype: &str, peer: PeerId, request_id: u64, try_accept: F) { let mut core = self.core.lock(); - let request = match core.remove(peer, request_id) { + let request = match core.remove(peer.clone(), request_id) { Some(request) => request, None => { let reason = format!("Invalid remote {} response from peer", rtype); - self.send(NetworkMsg::ReportPeer(peer, Severity::Bad(reason))); + self.send(NetworkMsg::ReportPeer(peer.clone(), Severity::Bad(reason))); core.remove_peer(peer); return; }, @@ -187,7 +187,7 @@ impl OnDemand where Accept::Ok => (retry_count, None), Accept::CheckFailed(error, retry_request_data) => { let reason = format!("Failed to check remote {} response from peer: {}", rtype, error); - self.send(NetworkMsg::ReportPeer(peer, Severity::Bad(reason))); + self.send(NetworkMsg::ReportPeer(peer.clone(), Severity::Bad(reason))); core.remove_peer(peer); if retry_count > 0 { @@ -200,7 +200,7 @@ impl OnDemand where }, Accept::Unexpected(retry_request_data) => { let reason = format!("Unexpected response to remote {} from peer", rtype); - self.send(NetworkMsg::ReportPeer(peer, Severity::Bad(reason))); + self.send(NetworkMsg::ReportPeer(peer.clone(), Severity::Bad(reason))); core.remove_peer(peer); (retry_count, Some(retry_request_data)) @@ -219,7 +219,7 @@ impl OnDemandService for OnDemand where B: BlockT, B::Header: HeaderT, { - fn on_connect(&self, peer: NodeIndex, role: Roles, best_number: NumberFor) { + fn on_connect(&self, peer: PeerId, role: Roles, best_number: NumberFor) { if !role.intersects(Roles::FULL | Roles::AUTHORITY) { return; } @@ -229,13 +229,13 @@ impl OnDemandService for OnDemand where core.dispatch(self); } - fn on_block_announce(&self, peer: NodeIndex, best_number: NumberFor) { + fn on_block_announce(&self, peer: PeerId, best_number: NumberFor) { let mut core = self.core.lock(); core.update_peer(peer, best_number); core.dispatch(self); } - fn on_disconnect(&self, peer: NodeIndex) { + fn on_disconnect(&self, peer: PeerId) { let mut core = self.core.lock(); core.remove_peer(peer); core.dispatch(self); @@ -249,7 +249,7 @@ impl OnDemandService for OnDemand where core.dispatch(self); } - fn on_remote_header_response(&self, peer: NodeIndex, response: message::RemoteHeaderResponse) { + fn on_remote_header_response(&self, peer: PeerId, response: message::RemoteHeaderResponse) { self.accept_response("header", peer, response.id, |request| match request.data { RequestData::RemoteHeader(request, sender) => match self.checker.check_header_proof(&request, response.header, response.proof) { Ok(response) => { @@ -263,7 +263,7 @@ impl OnDemandService for OnDemand where }) } - fn on_remote_read_response(&self, peer: NodeIndex, response: message::RemoteReadResponse) { + fn on_remote_read_response(&self, peer: PeerId, response: message::RemoteReadResponse) { self.accept_response("read", peer, response.id, |request| match request.data { RequestData::RemoteRead(request, sender) => match self.checker.check_read_proof(&request, response.proof) { Ok(response) => { @@ -277,7 +277,7 @@ impl OnDemandService for OnDemand where }) } - fn on_remote_call_response(&self, peer: NodeIndex, response: message::RemoteCallResponse) { + fn on_remote_call_response(&self, peer: PeerId, response: message::RemoteCallResponse) { self.accept_response("call", peer, response.id, |request| match request.data { RequestData::RemoteCall(request, sender) => match self.checker.check_execution_proof(&request, response.proof) { Ok(response) => { @@ -291,7 +291,7 @@ impl OnDemandService for OnDemand where }) } - fn on_remote_changes_response(&self, peer: NodeIndex, response: message::RemoteChangesResponse, B::Hash>) { + fn on_remote_changes_response(&self, peer: PeerId, response: message::RemoteChangesResponse, B::Hash>) { self.accept_response("changes", peer, response.id, |request| match request.data { RequestData::RemoteChanges(request, sender) => match self.checker.check_changes_proof( &request, ChangesProof { @@ -350,16 +350,16 @@ impl OnDemandCore where B: BlockT, B::Header: HeaderT, { - pub fn add_peer(&mut self, peer: NodeIndex, best_number: NumberFor) { - self.idle_peers.push_back(peer); + pub fn add_peer(&mut self, peer: PeerId, best_number: NumberFor) { + self.idle_peers.push_back(peer.clone()); self.best_blocks.insert(peer, best_number); } - pub fn update_peer(&mut self, peer: NodeIndex, best_number: NumberFor) { + pub fn update_peer(&mut self, peer: PeerId, best_number: NumberFor) { self.best_blocks.insert(peer, best_number); } - pub fn remove_peer(&mut self, peer: NodeIndex) { + pub fn remove_peer(&mut self, peer: PeerId) { self.best_blocks.remove(&peer); if let Some(request) = self.active_peers.remove(&peer) { @@ -372,7 +372,7 @@ impl OnDemandCore where } } - pub fn maintain_peers(&mut self) -> Vec { + pub fn maintain_peers(&mut self) -> Vec { let now = Instant::now(); let mut bad_peers = Vec::new(); loop { @@ -399,8 +399,8 @@ impl OnDemandCore where }); } - pub fn remove(&mut self, peer: NodeIndex, id: u64) -> Option> { - match self.active_peers.entry(peer) { + pub fn remove(&mut self, peer: PeerId, id: u64) -> Option> { + match self.active_peers.entry(peer.clone()) { Entry::Occupied(entry) => match entry.get().id == id { true => { self.idle_peers.push_back(peer); @@ -441,7 +441,7 @@ impl OnDemandCore where if !can_be_processed_by_peer { // return peer to the back of the queue - self.idle_peers.push_back(peer); + self.idle_peers.push_back(peer.clone()); // we have enumerated all peers and noone can handle request if Some(peer) == last_peer { @@ -458,7 +458,7 @@ impl OnDemandCore where let mut request = self.pending_requests.pop_front().expect("checked in loop condition; qed"); request.timestamp = Instant::now(); trace!(target: "sync", "Dispatching remote request {} to peer {}", request.id, peer); - on_demand.send(NetworkMsg::Outgoing(peer, request.message())); + on_demand.send(NetworkMsg::Outgoing(peer.clone(), request.message())); self.active_peers.insert(peer, request); } @@ -532,7 +532,7 @@ pub mod tests { RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof}; use crate::config::Roles; use crate::message; - use network_libp2p::{NodeIndex, ProtocolId, Severity}; + use network_libp2p::{PeerId, Severity}; use crate::service::{network_channel, NetworkPort, NetworkMsg}; use super::{REQUEST_TIMEOUT, OnDemand, OnDemandService}; use test_client::runtime::{changes_trie_config, Block, Header}; @@ -586,7 +586,7 @@ pub mod tests { core.idle_peers.len() + core.active_peers.len() } - fn receive_call_response(on_demand: &OnDemand, peer: NodeIndex, id: message::RequestId) { + fn receive_call_response(on_demand: &OnDemand, peer: PeerId, id: message::RequestId) { on_demand.on_remote_call_response(peer, message::RemoteCallResponse { id: id, proof: vec![vec![2]], @@ -621,22 +621,27 @@ pub mod tests { #[test] fn knows_about_peers_roles() { let (_, on_demand) = dummy(true); - on_demand.on_connect(0, Roles::LIGHT, 1000); - on_demand.on_connect(1, Roles::FULL, 2000); - on_demand.on_connect(2, Roles::AUTHORITY, 3000); - assert_eq!(vec![1, 2], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); - assert_eq!(on_demand.core.lock().best_blocks.get(&1), Some(&2000)); - assert_eq!(on_demand.core.lock().best_blocks.get(&2), Some(&3000)); + let peer0 = PeerId::random(); + let peer1 = PeerId::random(); + let peer2 = PeerId::random(); + on_demand.on_connect(peer0, Roles::LIGHT, 1000); + on_demand.on_connect(peer1.clone(), Roles::FULL, 2000); + on_demand.on_connect(peer2.clone(), Roles::AUTHORITY, 3000); + assert_eq!(vec![peer1.clone(), peer2.clone()], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); + assert_eq!(on_demand.core.lock().best_blocks.get(&peer1), Some(&2000)); + assert_eq!(on_demand.core.lock().best_blocks.get(&peer2), Some(&3000)); } #[test] fn disconnects_from_idle_peer() { + let peer0 = PeerId::random(); + let (_, on_demand) = dummy(true); - on_demand.on_connect(0, Roles::FULL, 100); + on_demand.on_connect(peer0.clone(), Roles::FULL, 100); assert_eq!(1, total_peers(&*on_demand)); assert!(!on_demand.core.lock().best_blocks.is_empty()); - on_demand.on_disconnect(0); + on_demand.on_disconnect(peer0); assert_eq!(0, total_peers(&*on_demand)); assert!(on_demand.core.lock().best_blocks.is_empty()); } @@ -644,11 +649,13 @@ pub mod tests { #[test] fn disconnects_from_timeouted_peer() { let (_x, on_demand) = dummy(true); - let (network_sender, network_port) = network_channel(ProtocolId::default()); + let (network_sender, network_port) = network_channel(); + let peer0 = PeerId::random(); + let peer1 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(0, Roles::FULL, 1000); - on_demand.on_connect(1, Roles::FULL, 1000); - assert_eq!(vec![0, 1], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); + on_demand.on_connect(peer1.clone(), Roles::FULL, 1000); + assert_eq!(vec![peer0.clone(), peer1.clone()], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); assert!(on_demand.core.lock().active_peers.is_empty()); on_demand.remote_call(RemoteCallRequest { @@ -658,22 +665,23 @@ pub mod tests { call_data: vec![], retry_count: None, }); - assert_eq!(vec![1], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); - assert_eq!(vec![0], on_demand.core.lock().active_peers.keys().cloned().collect::>()); + assert_eq!(vec![peer1.clone()], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); + assert_eq!(vec![peer0.clone()], on_demand.core.lock().active_peers.keys().cloned().collect::>()); - on_demand.core.lock().active_peers[&0].timestamp = Instant::now() - REQUEST_TIMEOUT - REQUEST_TIMEOUT; + on_demand.core.lock().active_peers[&peer0].timestamp = Instant::now() - REQUEST_TIMEOUT - REQUEST_TIMEOUT; on_demand.maintain_peers(); assert!(on_demand.core.lock().idle_peers.is_empty()); - assert_eq!(vec![1], on_demand.core.lock().active_peers.keys().cloned().collect::>()); + assert_eq!(vec![peer1.clone()], on_demand.core.lock().active_peers.keys().cloned().collect::>()); assert_disconnected_peer(network_port, Severity::Timeout); } #[test] fn disconnects_from_peer_on_response_with_wrong_id() { let (_x, on_demand) = dummy(true); - let (network_sender, network_port) = network_channel(ProtocolId::default()); + let peer0 = PeerId::random(); + let (network_sender, network_port) = network_channel(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(0, Roles::FULL, 1000); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); on_demand.remote_call(RemoteCallRequest { block: Default::default(), @@ -682,7 +690,7 @@ pub mod tests { call_data: vec![], retry_count: None, }); - receive_call_response(&*on_demand, 0, 1); + receive_call_response(&*on_demand, peer0, 1); assert_disconnected_peer(network_port, Severity::Bad("Invalid remote call response from peer".to_string())); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); } @@ -690,7 +698,8 @@ pub mod tests { #[test] fn disconnects_from_peer_on_incorrect_response() { let (_x, on_demand) = dummy(false); - let (network_sender, network_port) = network_channel(ProtocolId::default()); + let (network_sender, network_port) = network_channel(); + let peer0 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); on_demand.remote_call(RemoteCallRequest { block: Default::default(), @@ -700,8 +709,8 @@ pub mod tests { retry_count: Some(1), }); - on_demand.on_connect(0, Roles::FULL, 1000); - receive_call_response(&*on_demand, 0, 0); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); + receive_call_response(&*on_demand, peer0.clone(), 0); assert_disconnected_peer(network_port, Severity::Bad("Failed to check remote call response from peer: Backend error: Test error".to_string())); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); } @@ -709,20 +718,22 @@ pub mod tests { #[test] fn disconnects_from_peer_on_unexpected_response() { let (_x, on_demand) = dummy(true); - let (network_sender, network_port) = network_channel(ProtocolId::default()); + let (network_sender, network_port) = network_channel(); + let peer0 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(0, Roles::FULL, 1000); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); - receive_call_response(&*on_demand, 0, 0); + receive_call_response(&*on_demand, peer0, 0); assert_disconnected_peer(network_port, Severity::Bad("Invalid remote call response from peer".to_string())); } #[test] fn disconnects_from_peer_on_wrong_response_type() { let (_x, on_demand) = dummy(false); - let (network_sender, network_port) = network_channel(ProtocolId::default()); + let peer0 = PeerId::random(); + let (network_sender, network_port) = network_channel(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(0, Roles::FULL, 1000); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); on_demand.remote_call(RemoteCallRequest { block: Default::default(), @@ -732,7 +743,7 @@ pub mod tests { retry_count: Some(1), }); - on_demand.on_remote_read_response(0, message::RemoteReadResponse { + on_demand.on_remote_read_response(peer0.clone(), message::RemoteReadResponse { id: 0, proof: vec![vec![2]], }); @@ -745,11 +756,12 @@ pub mod tests { use parking_lot::{Condvar, Mutex}; let retry_count = 2; + let peer_ids = (0 .. retry_count + 1).map(|_| PeerId::random()).collect::>(); let (_x, on_demand) = dummy(false); - let (network_sender, _network_port) = network_channel(ProtocolId::default()); + let (network_sender, _network_port) = network_channel(); on_demand.set_network_sender(network_sender.clone()); for i in 0..retry_count+1 { - on_demand.on_connect(i, Roles::FULL, 1000); + on_demand.on_connect(peer_ids[i].clone(), Roles::FULL, 1000); } let sync = Arc::new((Mutex::new(0), Mutex::new(0), Condvar::new())); @@ -773,7 +785,7 @@ pub mod tests { for i in 0..retry_count+1 { let mut current = current.lock(); *current = *current + 1; - receive_call_response(&*on_demand, i, i as u64); + receive_call_response(&*on_demand, peer_ids[i].clone(), i as u64); } let mut finished_at = finished_at.lock(); @@ -786,9 +798,10 @@ pub mod tests { #[test] fn receives_remote_call_response() { let (_x, on_demand) = dummy(true); - let (network_sender, _network_port) = network_channel(ProtocolId::default()); + let (network_sender, _network_port) = network_channel(); + let peer0 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(0, Roles::FULL, 1000); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); let response = on_demand.remote_call(RemoteCallRequest { block: Default::default(), @@ -802,16 +815,17 @@ pub mod tests { assert_eq!(result, vec![42]); }); - receive_call_response(&*on_demand, 0, 0); + receive_call_response(&*on_demand, peer0.clone(), 0); thread.join().unwrap(); } #[test] fn receives_remote_read_response() { let (_x, on_demand) = dummy(true); - let (network_sender, _network_port) = network_channel(ProtocolId::default()); + let (network_sender, _network_port) = network_channel(); + let peer0 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(0, Roles::FULL, 1000); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); let response = on_demand.remote_read(RemoteReadRequest { header: dummy_header(), @@ -824,7 +838,7 @@ pub mod tests { assert_eq!(result, Some(vec![42])); }); - on_demand.on_remote_read_response(0, message::RemoteReadResponse { + on_demand.on_remote_read_response(peer0.clone(), message::RemoteReadResponse { id: 0, proof: vec![vec![2]], }); @@ -834,9 +848,10 @@ pub mod tests { #[test] fn receives_remote_header_response() { let (_x, on_demand) = dummy(true); - let (network_sender, _network_port) = network_channel(ProtocolId::default()); + let (network_sender, _network_port) = network_channel(); + let peer0 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(0, Roles::FULL, 1000); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); let response = on_demand.remote_header(RemoteHeaderRequest { cht_root: Default::default(), @@ -852,7 +867,7 @@ pub mod tests { ); }); - on_demand.on_remote_header_response(0, message::RemoteHeaderResponse { + on_demand.on_remote_header_response(peer0.clone(), message::RemoteHeaderResponse { id: 0, header: Some(Header { parent_hash: Default::default(), @@ -869,9 +884,10 @@ pub mod tests { #[test] fn receives_remote_changes_response() { let (_x, on_demand) = dummy(true); - let (network_sender, _network_port) = network_channel(ProtocolId::default()); + let (network_sender, _network_port) = network_channel(); + let peer0 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(0, Roles::FULL, 1000); + on_demand.on_connect(peer0.clone(), Roles::FULL, 1000); let response = on_demand.remote_changes(RemoteChangesRequest { changes_trie_config: changes_trie_config(), @@ -887,7 +903,7 @@ pub mod tests { assert_eq!(result, vec![(100, 2)]); }); - on_demand.on_remote_changes_response(0, message::RemoteChangesResponse { + on_demand.on_remote_changes_response(peer0.clone(), message::RemoteChangesResponse { id: 0, max: 1000, proof: vec![vec![2]], @@ -900,10 +916,12 @@ pub mod tests { #[test] fn does_not_sends_request_to_peer_who_has_no_required_block() { let (_x, on_demand) = dummy(true); - let (network_sender, _network_port) = network_channel(ProtocolId::default()); + let (network_sender, _network_port) = network_channel(); + let peer1 = PeerId::random(); + let peer2 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); - on_demand.on_connect(1, Roles::FULL, 100); + on_demand.on_connect(peer1.clone(), Roles::FULL, 100); on_demand.remote_header(RemoteHeaderRequest { cht_root: Default::default(), @@ -921,22 +939,22 @@ pub mod tests { retry_count: None, }); - on_demand.on_connect(2, Roles::FULL, 150); + on_demand.on_connect(peer2.clone(), Roles::FULL, 150); - assert_eq!(vec![1, 2], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); + assert_eq!(vec![peer1.clone(), peer2.clone()], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); assert_eq!(on_demand.core.lock().pending_requests.len(), 3); - on_demand.on_block_announce(1, 250); + on_demand.on_block_announce(peer1.clone(), 250); - assert_eq!(vec![2], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); + assert_eq!(vec![peer2.clone()], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); assert_eq!(on_demand.core.lock().pending_requests.len(), 2); - on_demand.on_block_announce(2, 250); + on_demand.on_block_announce(peer2.clone(), 250); assert!(!on_demand.core.lock().idle_peers.iter().any(|_| true)); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); - on_demand.on_remote_header_response(1, message::RemoteHeaderResponse { + on_demand.on_remote_header_response(peer1.clone(), message::RemoteHeaderResponse { id: 0, header: Some(dummy_header()), proof: vec![], @@ -952,7 +970,10 @@ pub mod tests { // loop forever after dispatching a request to the last peer, since the // last peer was not updated let (_x, on_demand) = dummy(true); - let (network_sender, _network_port) = network_channel(ProtocolId::default()); + let (network_sender, _network_port) = network_channel(); + let peer1 = PeerId::random(); + let peer2 = PeerId::random(); + let peer3 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); on_demand.remote_header(RemoteHeaderRequest { @@ -966,18 +987,19 @@ pub mod tests { retry_count: None, }); - on_demand.on_connect(1, Roles::FULL, 200); - on_demand.on_connect(2, Roles::FULL, 200); - on_demand.on_connect(3, Roles::FULL, 250); + on_demand.on_connect(peer1.clone(), Roles::FULL, 200); + on_demand.on_connect(peer2.clone(), Roles::FULL, 200); + on_demand.on_connect(peer3.clone(), Roles::FULL, 250); - assert_eq!(vec![1, 2], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); + assert_eq!(vec![peer1.clone(), peer2.clone()], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); } #[test] fn tries_to_send_all_pending_requests() { let (_x, on_demand) = dummy(true); - let (network_sender, _network_port) = network_channel(ProtocolId::default()); + let (network_sender, _network_port) = network_channel(); + let peer1 = PeerId::random(); on_demand.set_network_sender(network_sender.clone()); on_demand.remote_header(RemoteHeaderRequest { @@ -991,7 +1013,7 @@ pub mod tests { retry_count: None, }); - on_demand.on_connect(1, Roles::FULL, 250); + on_demand.on_connect(peer1.clone(), Roles::FULL, 250); assert!(on_demand.core.lock().idle_peers.iter().cloned().collect::>().is_empty()); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); diff --git a/core/network/src/protocol.rs b/core/network/src/protocol.rs index 7c6e973c6991926d44f8fc025ce325412f313feb..185f595cc09129b18f80df7cd3f1373eb441355b 100644 --- a/core/network/src/protocol.rs +++ b/core/network/src/protocol.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,12 +17,12 @@ use crossbeam_channel::{self as channel, Receiver, Sender, select}; use futures::sync::mpsc; use parking_lot::Mutex; -use network_libp2p::{NodeIndex, PeerId, Severity}; +use network_libp2p::{PeerId, Severity}; use primitives::storage::StorageKey; -use runtime_primitives::generic::BlockId; +use runtime_primitives::{generic::BlockId, ConsensusEngineId}; use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT, NumberFor, Zero}; use consensus::import_queue::ImportQueue; -use crate::message::{self, Message, ConsensusEngineId}; +use crate::message::{self, Message}; use crate::message::generic::{Message as GenericMessage, ConsensusMessage}; use crate::consensus_gossip::ConsensusGossip; use crate::on_demand::OnDemandService; @@ -75,10 +75,10 @@ pub struct Protocol, H: ExHashT> { consensus_gossip: ConsensusGossip, context_data: ContextData, // Connected peers pending Status message. - handshaking_peers: HashMap, + handshaking_peers: HashMap, // Connected peers from whom we received a Status message, // similar to context_data.peers but shared with the SyncProvider. - connected_peers: Arc>>>, + connected_peers: Arc>>>, transaction_pool: Arc>, } @@ -92,7 +92,6 @@ pub struct ConnectedPeer { /// and from whom we have not yet received a Status message. struct HandshakingPeer { timestamp: time::Instant, - peer_id: PeerId, } /// Syncing status and statistics @@ -125,8 +124,6 @@ struct Peer { /// Info about a peer's known state. #[derive(Clone, Debug)] pub struct PeerInfo { - /// Network id. - pub peer_id: PeerId, /// Roles pub roles: Roles, /// Protocol version @@ -143,13 +140,13 @@ pub trait Context { fn client(&self) -> &crate::chain::Client; /// Point out that a peer has been malign or irresponsible or appeared lazy. - fn report_peer(&mut self, who: NodeIndex, reason: Severity); + fn report_peer(&mut self, who: PeerId, reason: Severity); /// Get peer info. - fn peer_info(&self, peer: NodeIndex) -> Option>; + fn peer_info(&self, peer: &PeerId) -> Option>; /// Send a message to a peer. - fn send_message(&mut self, who: NodeIndex, data: crate::message::Message); + fn send_message(&mut self, who: PeerId, data: crate::message::Message); } /// Protocol context. @@ -165,16 +162,16 @@ impl<'a, B: BlockT + 'a, H: 'a + ExHashT> ProtocolContext<'a, B, H> { } impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context for ProtocolContext<'a, B, H> { - fn send_message(&mut self, who: NodeIndex, message: Message) { + fn send_message(&mut self, who: PeerId, message: Message) { send_message(&mut self.context_data.peers, &self.network_chan, who, message) } - fn report_peer(&mut self, who: NodeIndex, reason: Severity) { + fn report_peer(&mut self, who: PeerId, reason: Severity) { self.network_chan.send(NetworkMsg::ReportPeer(who, reason)) } - fn peer_info(&self, who: NodeIndex) -> Option> { - self.context_data.peers.get(&who).map(|p| p.info.clone()) + fn peer_info(&self, who: &PeerId) -> Option> { + self.context_data.peers.get(who).map(|p| p.info.clone()) } fn client(&self) -> &Client { @@ -185,7 +182,7 @@ impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context for ProtocolContext<'a, B, /// Data necessary to create a context. struct ContextData { // All connected peers - peers: HashMap>, + peers: HashMap>, pub chain: Arc>, } @@ -240,7 +237,7 @@ pub enum ProtocolMsg> { /// Execute a closure with the consensus gossip. ExecuteWithGossip(Box + Send + 'static>), /// Incoming gossip consensus message. - GossipConsensusMessage(B::Hash, ConsensusEngineId, Vec), + GossipConsensusMessage(B::Hash, ConsensusEngineId, Vec, bool), /// Tell protocol to abort sync (does not stop protocol). /// Only used in tests. #[cfg(any(test, feature = "test-helpers"))] @@ -254,13 +251,13 @@ pub enum ProtocolMsg> { /// Messages sent to Protocol from Network-libp2p. pub enum FromNetworkMsg { /// A peer connected, with debug info. - PeerConnected(PeerId, NodeIndex, String), + PeerConnected(PeerId, String), /// A peer disconnected, with debug info. - PeerDisconnected(NodeIndex, String), + PeerDisconnected(PeerId, String), /// A custom message from another peer. - CustomMessage(NodeIndex, Message), + CustomMessage(PeerId, Message), /// Let protocol know a peer is currenlty clogged. - PeerClogged(NodeIndex, Option>), + PeerClogged(PeerId, Option>), } enum Incoming> { @@ -274,7 +271,7 @@ impl, H: ExHashT> Protocol { status_sinks: Arc>>>>, is_offline: Arc, is_major_syncing: Arc, - connected_peers: Arc>>>, + connected_peers: Arc>>>, network_chan: NetworkChan, config: ProtocolConfig, chain: Arc>, @@ -380,8 +377,8 @@ impl, H: ExHashT> Protocol { ProtocolContext::new(&mut self.context_data, &self.network_chan); task.call_box(&mut self.consensus_gossip, &mut context); } - ProtocolMsg::GossipConsensusMessage(topic, engine_id, message) => { - self.gossip_consensus_message(topic, engine_id, message) + ProtocolMsg::GossipConsensusMessage(topic, engine_id, message, force) => { + self.gossip_consensus_message(topic, engine_id, message, force) } ProtocolMsg::BlocksProcessed(hashes, has_error) => { self.sync.blocks_processed(hashes, has_error); @@ -418,7 +415,7 @@ impl, H: ExHashT> Protocol { fn handle_network_msg(&mut self, msg: FromNetworkMsg) -> bool { match msg { FromNetworkMsg::PeerDisconnected(who, debug_info) => self.on_peer_disconnected(who, debug_info), - FromNetworkMsg::PeerConnected(peer_id, who, debug_info) => self.on_peer_connected(peer_id, who, debug_info), + FromNetworkMsg::PeerConnected(who, debug_info) => self.on_peer_connected(who, debug_info), FromNetworkMsg::PeerClogged(who, message) => self.on_clogged_peer(who, message), FromNetworkMsg::CustomMessage(who, message) => { self.on_custom_message(who, message) @@ -427,7 +424,7 @@ impl, H: ExHashT> Protocol { true } - fn handle_response(&mut self, who: NodeIndex, response: &message::BlockResponse) -> Option> { + fn handle_response(&mut self, who: PeerId, response: &message::BlockResponse) -> Option> { if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { if let Some(_) = peer.obsolete_requests.remove(&response.id) { trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", who, response.id,); @@ -445,6 +442,20 @@ impl, H: ExHashT> Protocol { None } + fn update_peer_info(&mut self, who: &PeerId) { + if let Some(info) = self.sync.peer_info(who) { + if let Some(ref mut peer) = self.context_data.peers.get_mut(who) { + peer.info.best_hash = info.best_hash; + peer.info.best_number = info.best_number; + } + let mut peers = self.connected_peers.write(); + if let Some(ref mut peer) = peers.get_mut(who) { + peer.peer_info.best_hash = info.best_hash; + peer.peer_info.best_number = info.best_number; + } + } + } + /// Propagates protocol statuses. fn on_status(&mut self) { let status = ProtocolStatus { @@ -460,16 +471,20 @@ impl, H: ExHashT> Protocol { self.status_sinks.lock().retain(|sink| sink.unbounded_send(status.clone()).is_ok()); } - fn on_custom_message(&mut self, who: NodeIndex, message: Message) { + fn on_custom_message(&mut self, who: PeerId, message: Message) { match message { GenericMessage::Status(s) => self.on_status_message(who, s), GenericMessage::BlockRequest(r) => self.on_block_request(who, r), GenericMessage::BlockResponse(r) => { - if let Some(request) = self.handle_response(who, &r) { - self.on_block_response(who, request, r); + if let Some(request) = self.handle_response(who.clone(), &r) { + self.on_block_response(who.clone(), request, r); + self.update_peer_info(&who); } }, - GenericMessage::BlockAnnounce(announce) => self.on_block_announce(who, announce), + GenericMessage::BlockAnnounce(announce) => { + self.on_block_announce(who.clone(), announce); + self.update_peer_info(&who); + }, GenericMessage::Transactions(m) => self.on_extrinsics(who, m), GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(who, request), GenericMessage::RemoteCallResponse(response) => self.on_remote_call_response(who, response), @@ -484,7 +499,6 @@ impl, H: ExHashT> Protocol { &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), who, msg, - self.sync.status().is_major_syncing(), ); } other => self.specialization.on_message( @@ -495,7 +509,7 @@ impl, H: ExHashT> Protocol { } } - fn send_message(&mut self, who: NodeIndex, message: Message) { + fn send_message(&mut self, who: PeerId, message: Message) { send_message::( &mut self.context_data.peers, &self.network_chan, @@ -504,23 +518,30 @@ impl, H: ExHashT> Protocol { ); } - fn gossip_consensus_message(&mut self, topic: B::Hash, engine_id: ConsensusEngineId, message: Vec) { + fn gossip_consensus_message( + &mut self, + topic: B::Hash, + engine_id: ConsensusEngineId, + message: Vec, + force: bool, + ) { self.consensus_gossip.multicast( &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), topic, ConsensusMessage{ data: message, engine_id }, + force, ); } /// Called when a new peer is connected - fn on_peer_connected(&mut self, peer_id: PeerId, who: NodeIndex, debug_info: String) { + fn on_peer_connected(&mut self, who: PeerId, debug_info: String) { trace!(target: "sync", "Connecting {}: {}", who, debug_info); - self.handshaking_peers.insert(who, HandshakingPeer { timestamp: time::Instant::now(), peer_id }); + self.handshaking_peers.insert(who.clone(), HandshakingPeer { timestamp: time::Instant::now() }); self.send_status(who); } /// Called by peer when it is disconnecting - fn on_peer_disconnected(&mut self, peer: NodeIndex, debug_info: String) { + fn on_peer_disconnected(&mut self, peer: PeerId, debug_info: String) { trace!(target: "sync", "Disconnecting {}: {}", peer, debug_info); // lock all the the peer lists so that add/remove peer events are in order let removed = { @@ -530,16 +551,16 @@ impl, H: ExHashT> Protocol { }; if removed { let mut context = ProtocolContext::new(&mut self.context_data, &self.network_chan); - self.consensus_gossip.peer_disconnected(&mut context, peer); - self.sync.peer_disconnected(&mut context, peer); - self.specialization.on_disconnect(&mut context, peer); + self.consensus_gossip.peer_disconnected(&mut context, peer.clone()); + self.sync.peer_disconnected(&mut context, peer.clone()); + self.specialization.on_disconnect(&mut context, peer.clone()); self.on_demand.as_ref().map(|s| s.on_disconnect(peer)); } } /// Called as a back-pressure mechanism if the networking detects that the peer cannot process /// our messaging rate fast enough. - pub fn on_clogged_peer(&self, who: NodeIndex, _msg: Option>) { + pub fn on_clogged_peer(&self, who: PeerId, _msg: Option>) { // We don't do anything but print some diagnostics for now. if let Some(peer) = self.context_data.peers.get(&who) { debug!(target: "sync", "Clogged peer {} (protocol_version: {:?}; roles: {:?}; \ @@ -551,7 +572,7 @@ impl, H: ExHashT> Protocol { } } - fn on_block_request(&mut self, peer: NodeIndex, request: message::BlockRequest) { + fn on_block_request(&mut self, peer: PeerId, request: message::BlockRequest) { trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", request.id, peer, @@ -617,7 +638,7 @@ impl, H: ExHashT> Protocol { fn on_block_response( &mut self, - peer: NodeIndex, + peer: PeerId, request: message::BlockRequest, response: message::BlockResponse, ) { @@ -663,15 +684,15 @@ impl, H: ExHashT> Protocol { for (who, peer) in self.context_data.peers.iter() { if peer.block_request.as_ref().map_or(false, |(t, _)| (tick - *t).as_secs() > REQUEST_TIMEOUT_SEC) { trace!(target: "sync", "Reqeust timeout {}", who); - aborting.push(*who); + aborting.push(who.clone()); } else if peer.obsolete_requests.values().any(|t| (tick - *t).as_secs() > REQUEST_TIMEOUT_SEC) { trace!(target: "sync", "Obsolete timeout {}", who); - aborting.push(*who); + aborting.push(who.clone()); } } for (who, _) in self.handshaking_peers.iter().filter(|(_, handshaking)| (tick - handshaking.timestamp).as_secs() > REQUEST_TIMEOUT_SEC) { trace!(target: "sync", "Handshake timeout {}", who); - aborting.push(*who); + aborting.push(who.clone()); } } @@ -684,7 +705,7 @@ impl, H: ExHashT> Protocol { } /// Called by peer to report status - fn on_status_message(&mut self, who: NodeIndex, status: message::Status) { + fn on_status_message(&mut self, who: PeerId, status: message::Status) { trace!(target: "sync", "New peer {} {:?}", who, status); { if self.context_data.peers.contains_key(&who) { @@ -737,9 +758,8 @@ impl, H: ExHashT> Protocol { let cache_limit = NonZeroUsize::new(1_000_000).expect("1_000_000 > 0; qed"); let info = match self.handshaking_peers.remove(&who) { - Some(handshaking) => { + Some(_handshaking) => { let peer_info = PeerInfo { - peer_id: handshaking.peer_id, protocol_version: status.version, roles: status.roles, best_hash: status.best_hash, @@ -747,7 +767,7 @@ impl, H: ExHashT> Protocol { }; self.connected_peers .write() - .insert(who, ConnectedPeer { peer_info: peer_info.clone() }); + .insert(who.clone(), ConnectedPeer { peer_info: peer_info.clone() }); peer_info }, None => { @@ -772,15 +792,15 @@ impl, H: ExHashT> Protocol { let mut context = ProtocolContext::new(&mut self.context_data, &self.network_chan); self.on_demand .as_ref() - .map(|s| s.on_connect(who, status.roles, status.best_number)); - self.sync.new_peer(&mut context, who); + .map(|s| s.on_connect(who.clone(), status.roles, status.best_number)); + self.sync.new_peer(&mut context, who.clone()); self.consensus_gossip - .new_peer(&mut context, who, status.roles); + .new_peer(&mut context, who.clone(), status.roles); self.specialization.on_connect(&mut context, who, status); } /// Called when peer sends us new extrinsics - fn on_extrinsics(&mut self, who: NodeIndex, extrinsics: message::Transactions) { + fn on_extrinsics(&mut self, who: PeerId, extrinsics: message::Transactions) { // Accept extrinsics only when fully synced if self.sync.status().state != SyncState::Idle { trace!(target: "sync", "{} Ignoring extrinsics while syncing", who); @@ -821,10 +841,10 @@ impl, H: ExHashT> Protocol { propagated_to .entry(hash) .or_insert_with(Vec::new) - .push(peer.info.peer_id.to_base58()); + .push(who.to_base58()); } trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), who); - self.network_chan.send(NetworkMsg::Outgoing(*who, GenericMessage::Transactions(to_send))) + self.network_chan.send(NetworkMsg::Outgoing(who.clone(), GenericMessage::Transactions(to_send))) } } self.transaction_pool.on_broadcasted(propagated_to); @@ -853,12 +873,12 @@ impl, H: ExHashT> Protocol { for (who, ref mut peer) in self.context_data.peers.iter_mut() { trace!(target: "sync", "Reannouncing block {:?} to {}", hash, who); peer.known_blocks.insert(hash); - self.network_chan.send(NetworkMsg::Outgoing(*who, message.clone())) + self.network_chan.send(NetworkMsg::Outgoing(who.clone(), message.clone())) } } /// Send Status message - fn send_status(&mut self, who: NodeIndex) { + fn send_status(&mut self, who: PeerId) { if let Ok(info) = self.context_data.chain.info() { let status = message::generic::Status { version: CURRENT_VERSION, @@ -889,7 +909,7 @@ impl, H: ExHashT> Protocol { self.abort(); } - fn on_block_announce(&mut self, who: NodeIndex, announce: message::BlockAnnounce) { + fn on_block_announce(&mut self, who: PeerId, announce: message::BlockAnnounce) { let header = announce.header; let hash = header.hash(); { @@ -899,7 +919,7 @@ impl, H: ExHashT> Protocol { } self.on_demand .as_ref() - .map(|s| s.on_block_announce(who, *header.number())); + .map(|s| s.on_block_announce(who.clone(), *header.number())); self.sync.on_block_announce( &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), who, @@ -928,7 +948,7 @@ impl, H: ExHashT> Protocol { for (who, ref mut peer) in self.context_data.peers.iter_mut() { if peer.known_blocks.insert(hash.clone()) { trace!(target: "sync", "Announcing block {:?} to {}", hash, who); - self.network_chan.send(NetworkMsg::Outgoing(*who, message.clone())) + self.network_chan.send(NetworkMsg::Outgoing(who.clone(), message.clone())) } } } @@ -943,7 +963,7 @@ impl, H: ExHashT> Protocol { fn on_remote_call_request( &mut self, - who: NodeIndex, + who: PeerId, request: message::RemoteCallRequest, ) { trace!(target: "sync", "Remote call request {} from {} ({} at {})", request.id, who, request.method, request.block); @@ -969,7 +989,7 @@ impl, H: ExHashT> Protocol { ); } - fn on_remote_call_response(&mut self, who: NodeIndex, response: message::RemoteCallResponse) { + fn on_remote_call_response(&mut self, who: PeerId, response: message::RemoteCallResponse) { trace!(target: "sync", "Remote call response {} from {}", response.id, who); self.on_demand .as_ref() @@ -978,7 +998,7 @@ impl, H: ExHashT> Protocol { fn on_remote_read_request( &mut self, - who: NodeIndex, + who: PeerId, request: message::RemoteReadRequest, ) { trace!(target: "sync", "Remote read request {} from {} ({} at {})", @@ -999,7 +1019,7 @@ impl, H: ExHashT> Protocol { }), ); } - fn on_remote_read_response(&mut self, who: NodeIndex, response: message::RemoteReadResponse) { + fn on_remote_read_response(&mut self, who: PeerId, response: message::RemoteReadResponse) { trace!(target: "sync", "Remote read response {} from {}", response.id, who); self.on_demand .as_ref() @@ -1008,7 +1028,7 @@ impl, H: ExHashT> Protocol { fn on_remote_header_request( &mut self, - who: NodeIndex, + who: PeerId, request: message::RemoteHeaderRequest>, ) { trace!(target: "sync", "Remote header proof request {} from {} ({})", @@ -1033,7 +1053,7 @@ impl, H: ExHashT> Protocol { fn on_remote_header_response( &mut self, - who: NodeIndex, + who: PeerId, response: message::RemoteHeaderResponse, ) { trace!(target: "sync", "Remote header proof response {} from {}", response.id, who); @@ -1044,7 +1064,7 @@ impl, H: ExHashT> Protocol { fn on_remote_changes_request( &mut self, - who: NodeIndex, + who: PeerId, request: message::RemoteChangesRequest, ) { trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{})", @@ -1077,7 +1097,7 @@ impl, H: ExHashT> Protocol { fn on_remote_changes_response( &mut self, - who: NodeIndex, + who: PeerId, response: message::RemoteChangesResponse, B::Hash>, ) { trace!(target: "sync", "Remote changes proof response {} from {} (max={})", @@ -1089,9 +1109,9 @@ impl, H: ExHashT> Protocol { } fn send_message( - peers: &mut HashMap>, + peers: &mut HashMap>, network_chan: &NetworkChan, - who: NodeIndex, + who: PeerId, mut message: Message, ) { if let GenericMessage::BlockRequest(ref mut r) = message { @@ -1168,20 +1188,20 @@ macro_rules! construct_simple_protocol { fn on_connect( &mut self, _ctx: &mut $crate::Context<$block>, - _who: $crate::NodeIndex, + _who: $crate::PeerId, _status: $crate::StatusMessage<$block> ) { $( self.$sub_protocol_name.on_connect(_ctx, _who, _status); )* } - fn on_disconnect(&mut self, _ctx: &mut $crate::Context<$block>, _who: $crate::NodeIndex) { + fn on_disconnect(&mut self, _ctx: &mut $crate::Context<$block>, _who: $crate::PeerId) { $( self.$sub_protocol_name.on_disconnect(_ctx, _who); )* } fn on_message( &mut self, _ctx: &mut $crate::Context<$block>, - _who: $crate::NodeIndex, + _who: $crate::PeerId, _message: &mut Option<$crate::message::Message<$block>> ) { $( self.$sub_protocol_name.on_message(_ctx, _who, _message); )* diff --git a/core/network/src/service.rs b/core/network/src/service.rs index ac982f936edf265408c47485134a5ca911412af4..8e8658739884e1dde5f1730b86573544aa569e13 100644 --- a/core/network/src/service.rs +++ b/core/network/src/service.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,17 +21,18 @@ use std::{io, thread}; use log::{warn, debug, error, trace, info}; use futures::{Async, Future, Stream, stream, sync::oneshot, sync::mpsc}; use parking_lot::{Mutex, RwLock}; -use network_libp2p::{ProtocolId, NetworkConfiguration, NodeIndex, ErrorKind, Severity}; +use network_libp2p::{ProtocolId, NetworkConfiguration, Severity}; use network_libp2p::{start_service, parse_str_addr, Service as NetworkService, ServiceEvent as NetworkServiceEvent}; -use network_libp2p::{Protocol as Libp2pProtocol, RegisteredProtocol, NetworkState}; +use network_libp2p::{multiaddr, RegisteredProtocol, NetworkState}; +use peerset::Peerset; use consensus::import_queue::{ImportQueue, Link}; use crate::consensus_gossip::ConsensusGossip; -use crate::message::{Message, ConsensusEngineId}; +use crate::message::Message; use crate::protocol::{self, Context, FromNetworkMsg, Protocol, ConnectedPeer, ProtocolMsg, ProtocolStatus, PeerInfo}; use crate::config::Params; use crossbeam_channel::{self as channel, Receiver, Sender, TryRecvError}; use crate::error::Error; -use runtime_primitives::traits::{Block as BlockT, NumberFor}; +use runtime_primitives::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId}; use crate::specialization::NetworkSpecialization; use tokio::prelude::task::AtomicTask; @@ -50,7 +51,7 @@ pub trait SyncProvider: Send + Sync { /// Get network state. fn network_state(&self) -> NetworkState; /// Get currently connected peers - fn peers(&self) -> Vec<(NodeIndex, PeerInfo)>; + fn peers(&self) -> Vec<(PeerId, PeerInfo)>; /// Are we in the process of downloading the chain? fn is_major_syncing(&self) -> bool; } @@ -93,7 +94,7 @@ impl> Link for NetworkLink { let _ = self.protocol_sender.send(ProtocolMsg::BlocksProcessed(processed_blocks, has_error)); } - fn justification_imported(&self, who: NodeIndex, hash: &B::Hash, number: NumberFor, success: bool) { + fn justification_imported(&self, who: PeerId, hash: &B::Hash, number: NumberFor, success: bool) { let _ = self.protocol_sender.send(ProtocolMsg::JustificationImportResult(hash.clone(), number, success)); if !success { let reason = Severity::Bad(format!("Invalid justification provided for #{}", hash).to_string()); @@ -109,12 +110,12 @@ impl> Link for NetworkLink { let _ = self.protocol_sender.send(ProtocolMsg::RequestJustification(hash.clone(), number)); } - fn useless_peer(&self, who: NodeIndex, reason: &str) { + fn useless_peer(&self, who: PeerId, reason: &str) { trace!(target:"sync", "Useless peer {}, {}", who, reason); self.network_sender.send(NetworkMsg::ReportPeer(who, Severity::Useless(reason.to_string()))); } - fn note_useless_and_restart_sync(&self, who: NodeIndex, reason: &str) { + fn note_useless_and_restart_sync(&self, who: PeerId, reason: &str) { trace!(target:"sync", "Bad peer {}, {}", who, reason); // is this actually malign or just useless? self.network_sender.send(NetworkMsg::ReportPeer(who, Severity::Useless(reason.to_string()))); @@ -135,9 +136,12 @@ pub struct Service> { /// Are we actively catching up with the chain? is_major_syncing: Arc, /// Peers whom we are connected with. - peers: Arc>>>, + peers: Arc>>>, /// Network service network: Arc>>>, + /// Peerset manager (PSM); manages the reputation of nodes and indicates the network which + /// nodes it should be connected to or not. + peerset: Arc, /// Protocol sender protocol_sender: Sender>, /// Sender for messages to the background service task, and handle for the background thread. @@ -153,12 +157,12 @@ impl> Service { protocol_id: ProtocolId, import_queue: Box>, ) -> Result<(Arc>, NetworkChan), Error> { - let (network_chan, network_port) = network_channel(protocol_id); + let (network_chan, network_port) = network_channel(); let status_sinks = Arc::new(Mutex::new(Vec::new())); // Start in off-line mode, since we're not connected to any nodes yet. let is_offline = Arc::new(AtomicBool::new(true)); let is_major_syncing = Arc::new(AtomicBool::new(false)); - let peers: Arc>>> = Arc::new(Default::default()); + let peers: Arc>>> = Arc::new(Default::default()); let (protocol_sender, network_to_protocol_sender) = Protocol::new( status_sinks.clone(), is_offline.clone(), @@ -174,7 +178,7 @@ impl> Service { )?; let versions = [(protocol::CURRENT_VERSION as u8)]; let registered = RegisteredProtocol::new(protocol_id, &versions[..]); - let (thread, network) = start_thread( + let (thread, network, peerset) = start_thread( network_to_protocol_sender, network_port, params.network_config, @@ -186,6 +190,7 @@ impl> Service { is_offline, is_major_syncing, peers, + peerset, network, protocol_sender: protocol_sender.clone(), bg_thread: Some(thread), @@ -247,11 +252,17 @@ impl> Service { } /// Send a consensus message through the gossip - pub fn gossip_consensus_message(&self, topic: B::Hash, engine_id: ConsensusEngineId, message: Vec) { + pub fn gossip_consensus_message( + &self, + topic: B::Hash, + engine_id: ConsensusEngineId, + message: Vec, + force: bool, + ) { let _ = self .protocol_sender .send(ProtocolMsg::GossipConsensusMessage( - topic, engine_id, message, + topic, engine_id, message, force, )); } @@ -284,6 +295,7 @@ impl> ::consensus::SyncOracle f fn is_major_syncing(&self) -> bool { self.is_major_syncing() } + fn is_offline(&self) -> bool { self.is_offline.load(Ordering::Relaxed) } @@ -304,6 +316,7 @@ impl> SyncProvider for Servi fn is_major_syncing(&self) -> bool { self.is_major_syncing() } + /// Get sync status fn status(&self) -> mpsc::UnboundedReceiver> { let (sink, stream) = mpsc::unbounded(); @@ -315,7 +328,7 @@ impl> SyncProvider for Servi self.network.lock().state() } - fn peers(&self) -> Vec<(NodeIndex, PeerInfo)> { + fn peers(&self) -> Vec<(PeerId, PeerInfo)> { let peers = (*self.peers.read()).clone(); peers.into_iter().map(|(idx, connected)| (idx, connected.peer_info)).collect() } @@ -337,20 +350,21 @@ pub trait ManageNetwork { impl> ManageNetwork for Service { fn accept_unreserved_peers(&self) { - self.network.lock().accept_unreserved_peers(); + self.peerset.set_reserved_only(false); } fn deny_unreserved_peers(&self) { - self.network.lock().deny_unreserved_peers(); + self.peerset.set_reserved_only(true); } fn remove_reserved_peer(&self, peer: PeerId) { - self.network.lock().remove_reserved_peer(peer); + self.peerset.remove_reserved_peer(&peer); } fn add_reserved_peer(&self, peer: String) -> Result<(), String> { - let (addr, peer_id) = parse_str_addr(&peer).map_err(|e| format!("{:?}", e))?; - self.network.lock().add_reserved_peer(addr, peer_id); + let (peer_id, addr) = parse_str_addr(&peer).map_err(|e| format!("{:?}", e))?; + self.peerset.add_reserved_peer(peer_id.clone()); + self.network.lock().add_known_address(peer_id, addr); Ok(()) } @@ -361,7 +375,7 @@ impl> ManageNetwork for Service .next() .map(|addr| { let mut addr = addr.clone(); - addr.append(Libp2pProtocol::P2p(network.peer_id().clone().into())); + addr.append(multiaddr::Protocol::P2p(network.peer_id().clone().into())); addr.to_string() }); ret @@ -370,10 +384,10 @@ impl> ManageNetwork for Service /// Create a NetworkPort/Chan pair. -pub fn network_channel(protocol_id: ProtocolId) -> (NetworkChan, NetworkPort) { +pub fn network_channel() -> (NetworkChan, NetworkPort) { let (network_sender, network_receiver) = channel::unbounded(); let task_notify = Arc::new(AtomicTask::new()); - let network_port = NetworkPort::new(network_receiver, protocol_id, task_notify.clone()); + let network_port = NetworkPort::new(network_receiver, task_notify.clone()); let network_chan = NetworkChan::new(network_sender, task_notify); (network_chan, network_port) } @@ -413,26 +427,24 @@ impl Drop for NetworkChan { /// A receiver of NetworkMsg that makes the protocol-id available with each message. pub struct NetworkPort { receiver: Receiver>, - protocol_id: ProtocolId, task_notify: Arc, } impl NetworkPort { /// Create a new network port for a given protocol-id. - pub fn new(receiver: Receiver>, protocol_id: ProtocolId, task_notify: Arc) -> Self { + pub fn new(receiver: Receiver>, task_notify: Arc) -> Self { Self { receiver, - protocol_id, task_notify, } } /// Receive a message, if any is currently-enqueued. /// Register the current tokio task for notification when a new message is available. - pub fn take_one_message(&self) -> Result)>, ()> { + pub fn take_one_message(&self) -> Result>, ()> { self.task_notify.register(); match self.receiver.try_recv() { - Ok(msg) => Ok(Some((self.protocol_id.clone(), msg))), + Ok(msg) => Ok(Some(msg)), Err(TryRecvError::Empty) => Ok(None), Err(TryRecvError::Disconnected) => Err(()), } @@ -448,12 +460,10 @@ impl NetworkPort { /// Messages to be handled by NetworkService. #[derive(Debug)] pub enum NetworkMsg { - /// Ask network to convert a list of nodes, to a list of peers. - PeerIds(Vec, Sender)>>), /// Send an outgoing custom message. - Outgoing(NodeIndex, Message), + Outgoing(PeerId, Message), /// Report a peer. - ReportPeer(NodeIndex, Severity), + ReportPeer(PeerId, Severity), } /// Starts the background thread that handles the networking. @@ -462,18 +472,12 @@ fn start_thread( network_port: NetworkPort, config: NetworkConfiguration, registered: RegisteredProtocol>, -) -> Result<((oneshot::Sender<()>, thread::JoinHandle<()>), Arc>>>), Error> { - let protocol_id = registered.id(); - +) -> Result<((oneshot::Sender<()>, thread::JoinHandle<()>), Arc>>>, Arc), Error> { // Start the main service. - let service = match start_service(config, Some(registered)) { - Ok(service) => Arc::new(Mutex::new(service)), + let (service, peerset) = match start_service(config, registered) { + Ok((service, peerset)) => (Arc::new(Mutex::new(service)), peerset), Err(err) => { - match err.kind() { - ErrorKind::Io(ref e) if e.kind() == io::ErrorKind::AddrInUse => - warn!("Network port is already in use, make sure that another instance of Substrate client is not running or change the port using the --port option."), - _ => warn!("Error starting network: {}", err), - }; + warn!("Error starting network: {}", err); return Err(err.into()) }, }; @@ -482,7 +486,7 @@ fn start_thread( let service_clone = service.clone(); let mut runtime = RuntimeBuilder::new().name_prefix("libp2p-").build()?; let thread = thread::Builder::new().name("network".to_string()).spawn(move || { - let fut = run_thread(protocol_sender, service_clone, network_port, protocol_id) + let fut = run_thread(protocol_sender, service_clone, network_port) .select(close_rx.then(|_| Ok(()))) .map(|(val, _)| val) .map_err(|(err,_ )| err); @@ -495,7 +499,7 @@ fn start_thread( }; })?; - Ok(((close_tx, thread), service)) + Ok(((close_tx, thread), service, peerset)) } /// Runs the background thread that handles the networking. @@ -503,7 +507,6 @@ fn run_thread( protocol_sender: Sender>, network_service: Arc>>>, network_port: NetworkPort, - protocol_id: ProtocolId, ) -> impl Future { let network_service_2 = network_service.clone(); @@ -515,33 +518,29 @@ fn run_thread( Ok(None) => Ok(Async::NotReady), Err(_) => Err(()) } - }).for_each(move |(protocol_id, msg)| { + }).for_each(move |msg| { // Handle message from Protocol. match msg { - NetworkMsg::PeerIds(node_idxs, sender) => { - let reply = node_idxs.into_iter().map(|idx| { - (idx, network_service_2.lock().peer_id_of_node(idx).map(|p| p.clone())) - }).collect::>(); - let _ = sender.send(reply); - } NetworkMsg::Outgoing(who, outgoing_message) => { network_service_2 .lock() - .send_custom_message(who, protocol_id, outgoing_message); + .send_custom_message(&who, outgoing_message); }, NetworkMsg::ReportPeer(who, severity) => { match severity { Severity::Bad(message) => { info!(target: "sync", "Banning {:?} because {:?}", who, message); - network_service_2.lock().ban_node(who) + warn!(target: "sync", "Banning a node is a deprecated mechanism that \ + should be removed"); + network_service_2.lock().drop_node(&who) }, Severity::Useless(message) => { - info!(target: "sync", "Dropping {:?} because {:?}", who, message); - network_service_2.lock().drop_node(who) + debug!(target: "sync", "Dropping {:?} because {:?}", who, message); + network_service_2.lock().drop_node(&who) }, Severity::Timeout => { - info!(target: "sync", "Dropping {:?} because it timed out", who); - network_service_2.lock().drop_node(who) + debug!(target: "sync", "Dropping {:?} because it timed out", who); + network_service_2.lock().drop_node(&who) }, } }, @@ -559,29 +558,22 @@ fn run_thread( // The network service produces events about what happens on the network. Let's process them. let network = stream::poll_fn(move || network_service.lock().poll()).for_each(move |event| { match event { - NetworkServiceEvent::ClosedCustomProtocols { node_index, protocols, debug_info } => { - if !protocols.is_empty() { - debug_assert_eq!(protocols, &[protocol_id]); - let _ = protocol_sender.send( - FromNetworkMsg::PeerDisconnected(node_index, debug_info)); - } - } - NetworkServiceEvent::OpenedCustomProtocol { peer_id, node_index, version, debug_info, .. } => { + NetworkServiceEvent::OpenedCustomProtocol { peer_id, version, debug_info, .. } => { debug_assert_eq!(version, protocol::CURRENT_VERSION as u8); - let _ = protocol_sender.send(FromNetworkMsg::PeerConnected(peer_id, node_index, debug_info)); + let _ = protocol_sender.send(FromNetworkMsg::PeerConnected(peer_id, debug_info)); } - NetworkServiceEvent::ClosedCustomProtocol { node_index, debug_info, .. } => { - let _ = protocol_sender.send(FromNetworkMsg::PeerDisconnected(node_index, debug_info)); + NetworkServiceEvent::ClosedCustomProtocol { peer_id, debug_info, .. } => { + let _ = protocol_sender.send(FromNetworkMsg::PeerDisconnected(peer_id, debug_info)); } - NetworkServiceEvent::CustomMessage { node_index, message, .. } => { - let _ = protocol_sender.send(FromNetworkMsg::CustomMessage(node_index, message)); + NetworkServiceEvent::CustomMessage { peer_id, message, .. } => { + let _ = protocol_sender.send(FromNetworkMsg::CustomMessage(peer_id, message)); return Ok(()) } - NetworkServiceEvent::Clogged { node_index, messages, .. } => { + NetworkServiceEvent::Clogged { peer_id, messages, .. } => { debug!(target: "sync", "{} clogging messages:", messages.len()); for msg in messages.into_iter().take(5) { debug!(target: "sync", "{:?}", msg); - let _ = protocol_sender.send(FromNetworkMsg::PeerClogged(node_index, Some(msg))); + let _ = protocol_sender.send(FromNetworkMsg::PeerClogged(peer_id.clone(), Some(msg))); } } }; diff --git a/core/network/src/specialization.rs b/core/network/src/specialization.rs index 662dfdad75151865cad4c86690f16359cda90ec6..e440097dd1f674cc5e0afc41751e9b12dd1dcce9 100644 --- a/core/network/src/specialization.rs +++ b/core/network/src/specialization.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ //! Specializations of the substrate network protocol to allow more complex forms of communication. -use crate::NodeIndex; +use crate::PeerId; use runtime_primitives::traits::Block as BlockT; use crate::protocol::Context; @@ -26,13 +26,13 @@ pub trait NetworkSpecialization: Send + Sync + 'static { fn status(&self) -> Vec; /// Called when a peer successfully handshakes. - fn on_connect(&mut self, ctx: &mut Context, who: NodeIndex, status: crate::message::Status); + fn on_connect(&mut self, ctx: &mut Context, who: PeerId, status: crate::message::Status); /// Called when a peer is disconnected. If the peer ID is unknown, it should be ignored. - fn on_disconnect(&mut self, ctx: &mut Context, who: NodeIndex); + fn on_disconnect(&mut self, ctx: &mut Context, who: PeerId); /// Called when a network-specific message arrives. - fn on_message(&mut self, ctx: &mut Context, who: NodeIndex, message: &mut Option>); + fn on_message(&mut self, ctx: &mut Context, who: PeerId, message: &mut Option>); /// Called on abort. fn on_abort(&mut self) { } diff --git a/core/network/src/sync.rs b/core/network/src/sync.rs index abc215a597bb402028b0985c1f9af75f56a8ef7f..80ff8221a1a02fb844c1fcc8874c0fe27223f68a 100644 --- a/core/network/src/sync.rs +++ b/core/network/src/sync.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,14 +20,14 @@ use std::time::{Duration, Instant}; use log::{debug, trace, warn}; use crate::protocol::Context; use fork_tree::ForkTree; -use network_libp2p::{Severity, NodeIndex}; +use network_libp2p::{Severity, PeerId}; use client::{BlockStatus, ClientInfo}; use consensus::BlockOrigin; use consensus::import_queue::{ImportQueue, IncomingBlock}; use client::error::Error as ClientError; use crate::blocks::BlockCollection; use runtime_primitives::Justification; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero, CheckedSub}; use runtime_primitives::generic::BlockId; use crate::message::{self, generic::Message as GenericMessage}; use crate::config::Roles; @@ -46,7 +46,6 @@ const JUSTIFICATION_RETRY_WAIT: Duration = Duration::from_secs(10); // Number of recently announced blocks to track for each peer. const ANNOUNCE_HISTORY_SIZE: usize = 64; // Max number of blocks to download for unknown forks. -// TODO: this should take finality into account. See https://github.com/paritytech/substrate/issues/1606 const MAX_UNKNOWN_FORK_DOWNLOAD_LEN: u32 = 32; #[derive(Debug)] @@ -58,9 +57,28 @@ struct PeerSync { pub recently_announced: VecDeque, } +#[derive(Debug)] +/// Peer sync status. +pub(crate) struct PeerInfo { + /// Their best block hash. + pub best_hash: B::Hash, + /// Their best block number. + pub best_number: NumberFor, +} + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum AncestorSearchState { + /// Use exponential backoff to find an ancestor, then switch to binary search. + /// We keep track of the exponent. + ExponentialBackoff(NumberFor), + /// Using binary search to find the best ancestor. + /// We keep track of left and right bounds. + BinarySearch(NumberFor, NumberFor), +} + #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum PeerSyncState { - AncestorSearch(NumberFor), + AncestorSearch(NumberFor, AncestorSearchState), Available, DownloadingNew(NumberFor), DownloadingStale(B::Hash), @@ -78,8 +96,9 @@ type PendingJustification = (::Hash, NumberFor); struct PendingJustifications { justifications: ForkTree, ()>, pending_requests: VecDeque>, - peer_requests: HashMap>, - previous_requests: HashMap, Vec<(NodeIndex, Instant)>>, + peer_requests: HashMap>, + previous_requests: HashMap, Vec<(PeerId, Instant)>>, + importing_requests: HashSet>, } impl PendingJustifications { @@ -89,6 +108,7 @@ impl PendingJustifications { pending_requests: VecDeque::new(), peer_requests: HashMap::new(), previous_requests: HashMap::new(), + importing_requests: HashSet::new(), } } @@ -97,7 +117,7 @@ impl PendingJustifications { /// justification request for block #10 to a peer at block #2), and we also /// throttle requests to the same peer if a previous justification request /// yielded no results. - fn dispatch(&mut self, peers: &mut HashMap>, protocol: &mut Context) { + fn dispatch(&mut self, peers: &mut HashMap>, protocol: &mut Context) { if self.pending_requests.is_empty() { return; } @@ -114,11 +134,11 @@ impl PendingJustifications { if sync.state != PeerSyncState::Available || self.peer_requests.contains_key(&peer) { None } else { - Some((*peer, sync.best_number)) + Some((peer.clone(), sync.best_number)) } }).collect::>(); - let mut last_peer = available_peers.back().map(|p| p.0); + let mut last_peer = available_peers.back().map(|p| p.0.clone()); let mut unhandled_requests = VecDeque::new(); loop { @@ -138,17 +158,17 @@ impl PendingJustifications { peer_best_number >= request.1 && !self.previous_requests - .get(&request) - .map(|requests| requests.iter().any(|i| i.0 == peer)) - .unwrap_or(false) + .get(&request) + .map(|requests| requests.iter().any(|i| i.0 == peer)) + .unwrap_or(false) }; if !peer_eligible { - available_peers.push_back((peer, peer_best_number)); + available_peers.push_back((peer.clone(), peer_best_number)); // we tried all peers and none can answer this request if Some(peer) == last_peer { - last_peer = available_peers.back().map(|p| p.0); + last_peer = available_peers.back().map(|p| p.0.clone()); let request = self.pending_requests.pop_front() .expect("verified to be Some in the beginning of the loop; qed"); @@ -159,12 +179,12 @@ impl PendingJustifications { continue; } - last_peer = available_peers.back().map(|p| p.0); + last_peer = available_peers.back().map(|p| p.0.clone()); let request = self.pending_requests.pop_front() .expect("verified to be Some in the beginning of the loop; qed"); - self.peer_requests.insert(peer, request); + self.peer_requests.insert(peer.clone(), request); peers.get_mut(&peer) .expect("peer was is taken from available_peers; available_peers is a subset of peers; qed") @@ -215,7 +235,7 @@ impl PendingJustifications { } /// Retry any pending request if a peer disconnected. - fn peer_disconnected(&mut self, who: NodeIndex) { + fn peer_disconnected(&mut self, who: PeerId) { if let Some(request) = self.peer_requests.remove(&who) { self.pending_requests.push_front(request); } @@ -225,13 +245,24 @@ impl PendingJustifications { /// Queues a retry in case the import failed. fn justification_import_result(&mut self, hash: B::Hash, number: NumberFor, success: bool) { let request = (hash, number); + + if !self.importing_requests.remove(&request) { + debug!(target: "sync", "Got justification import result for unknown justification {:?} {:?} request.", + request.0, + request.1, + ); + + return; + }; + if success { if self.justifications.finalize_root(&request.0).is_none() { warn!(target: "sync", "Imported justification for {:?} {:?} which isn't a root in the tree: {:?}", - request.0, - request.1, - self.justifications.roots().collect::>(), + request.0, + request.1, + self.justifications.roots().collect::>(), ); + return; }; @@ -250,7 +281,7 @@ impl PendingJustifications { /// was `None`. fn on_response( &mut self, - who: NodeIndex, + who: PeerId, justification: Option, import_queue: &ImportQueue, ) { @@ -260,6 +291,7 @@ impl PendingJustifications { if let Some(request) = self.peer_requests.remove(&who) { if let Some(justification) = justification { import_queue.import_justification(who.clone(), request.0, request.1, justification); + self.importing_requests.insert(request); return } @@ -267,6 +299,7 @@ impl PendingJustifications { .entry(request) .or_insert(Vec::new()) .push((who, Instant::now())); + self.pending_requests.push_front(request); } } @@ -281,7 +314,11 @@ impl PendingJustifications { ) -> Result<(), fork_tree::Error> where F: Fn(&B::Hash, &B::Hash) -> Result { - use std::collections::HashSet; + if self.importing_requests.contains(&(*best_finalized_hash, best_finalized_number)) { + // we imported this justification ourselves, so we should get back a response + // from the import queue through `justification_import_result` + return Ok(()); + } self.justifications.finalize(best_finalized_hash, best_finalized_number, &is_descendent_of)?; @@ -306,7 +343,7 @@ impl PendingJustifications { /// Relay chain sync strategy. pub struct ChainSync { genesis_hash: B::Hash, - peers: HashMap>, + peers: HashMap>, blocks: BlockCollection, best_queued_number: NumberFor, best_queued_hash: B::Hash, @@ -398,6 +435,16 @@ impl ChainSync { } } + /// Returns peer sync status (if any). + pub(crate) fn peer_info(&self, who: &PeerId) -> Option> { + self.peers.get(who).map(|peer| { + PeerInfo { + best_hash: peer.best_hash, + best_number: peer.best_number, + } + }) + } + /// Returns sync status. pub(crate) fn status(&self) -> Status { let best_seen = self.best_seen_block(); @@ -410,7 +457,7 @@ impl ChainSync { } /// Handle new connected peer. - pub(crate) fn new_peer(&mut self, protocol: &mut Context, who: NodeIndex) { + pub(crate) fn new_peer(&mut self, protocol: &mut Context, who: PeerId) { // Initialize some variables to determine if // is_offline or is_major_syncing should be updated // after processing this new peer. @@ -418,8 +465,9 @@ impl ChainSync { let previous_best_seen = self.best_seen_block(); let previous_state = self.state(&previous_best_seen); - if let Some(info) = protocol.peer_info(who) { - match (block_status(&*protocol.client(), &self.queue_blocks, info.best_hash), info.best_number) { + if let Some(info) = protocol.peer_info(&who) { + let status = block_status(&*protocol.client(), &self.queue_blocks, info.best_hash); + match (status, info.best_number) { (Err(e), _) => { debug!(target:"sync", "Error reading blockchain: {:?}", e); let reason = format!("Error legimimately reading blockchain status: {:?}", e); @@ -449,18 +497,18 @@ impl ChainSync { if our_best > As::sa(0) { let common_best = ::std::cmp::min(our_best, info.best_number); debug!(target:"sync", "New peer with unknown best hash {} ({}), searching for common ancestor.", info.best_hash, info.best_number); - self.peers.insert(who, PeerSync { + self.peers.insert(who.clone(), PeerSync { common_number: As::sa(0), best_hash: info.best_hash, best_number: info.best_number, - state: PeerSyncState::AncestorSearch(common_best), + state: PeerSyncState::AncestorSearch(common_best, AncestorSearchState::ExponentialBackoff(As::sa(1))), recently_announced: Default::default(), }); Self::request_ancestry(protocol, who, common_best) } else { // We are at genesis, just start downloading debug!(target:"sync", "New peer with best hash {} ({}).", info.best_hash, info.best_number); - self.peers.insert(who, PeerSync { + self.peers.insert(who.clone(), PeerSync { common_number: As::sa(0), best_hash: info.best_hash, best_number: info.best_number, @@ -470,9 +518,9 @@ impl ChainSync { self.download_new(protocol, who) } }, - (Ok(BlockStatus::Queued), _) | (Ok(BlockStatus::InChain), _) => { + (Ok(BlockStatus::Queued), _) | (Ok(BlockStatus::InChainWithState), _) | (Ok(BlockStatus::InChainPruned), _) => { debug!(target:"sync", "New peer with known best hash {} ({}).", info.best_hash, info.best_number); - self.peers.insert(who, PeerSync { + self.peers.insert(who.clone(), PeerSync { common_number: info.best_number, best_hash: info.best_hash, best_number: info.best_number, @@ -500,11 +548,49 @@ impl ChainSync { } } + fn handle_ancestor_search_state( + state: AncestorSearchState, + curr_block_num: NumberFor, + block_hash_match: bool, + ) -> Option<(AncestorSearchState, NumberFor)> { + match state { + AncestorSearchState::ExponentialBackoff(next_distance_to_tip) => { + if block_hash_match && next_distance_to_tip == As::sa(1) { + // We found the ancestor in the first step so there is no need to execute binary search. + return None; + } + if block_hash_match { + let left = curr_block_num; + let right = left + next_distance_to_tip / As::sa(2); + let middle = left + (right - left) / As::sa(2); + Some((AncestorSearchState::BinarySearch(left, right), middle)) + } else { + let next_block_num = curr_block_num.checked_sub(&next_distance_to_tip).unwrap_or(As::sa(0)); + let next_distance_to_tip = next_distance_to_tip * As::sa(2); + Some((AncestorSearchState::ExponentialBackoff(next_distance_to_tip), next_block_num)) + } + }, + AncestorSearchState::BinarySearch(mut left, mut right) => { + if left >= curr_block_num { + return None; + } + if block_hash_match { + left = curr_block_num; + } else { + right = curr_block_num; + } + assert!(right >= left); + let middle = left + (right - left) / As::sa(2); + Some((AncestorSearchState::BinarySearch(left, right), middle)) + }, + } + } + /// Handle new block data. pub(crate) fn on_block_data( &mut self, protocol: &mut Context, - who: NodeIndex, + who: PeerId, request: message::BlockRequest, response: message::BlockResponse ) { @@ -514,9 +600,10 @@ impl ChainSync { trace!(target: "sync", "Reversing incoming block list"); blocks.reverse(); } - match peer.state { + let peer_state = peer.state.clone(); + match peer_state { PeerSyncState::DownloadingNew(start_block) => { - self.blocks.clear_peer_download(who); + self.blocks.clear_peer_download(&who); peer.state = PeerSyncState::Available; self.blocks.insert(start_block, blocks, who); self.blocks @@ -540,47 +627,42 @@ impl ChainSync { header: b.header, body: b.body, justification: b.justification, - origin: Some(who), + origin: Some(who.clone()), } }).collect() }, - PeerSyncState::AncestorSearch(n) => { - match blocks.get(0) { - Some(ref block) => { - trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", n, block.hash, who); - match protocol.client().block_hash(n) { - Ok(Some(block_hash)) if block_hash == block.hash => { - if peer.common_number < n { - peer.common_number = n; - } - peer.state = PeerSyncState::Available; - trace!(target:"sync", "Found common ancestor for peer {}: {} ({})", who, block.hash, n); - vec![] - }, - Ok(our_best) if n > As::sa(0) => { - trace!(target:"sync", "Ancestry block mismatch for peer {}: theirs: {} ({}), ours: {:?}", who, block.hash, n, our_best); - let n = n - As::sa(1); - peer.state = PeerSyncState::AncestorSearch(n); - Self::request_ancestry(protocol, who, n); - return; - }, - Ok(_) => { // genesis mismatch - trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); - protocol.report_peer(who, Severity::Bad("Ancestry search: genesis mismatch for peer".to_string())); - return; - }, - Err(e) => { - let reason = format!("Error answering legitimate blockchain query: {:?}", e); - protocol.report_peer(who, Severity::Useless(reason)); - return; - } - } + PeerSyncState::AncestorSearch(num, state) => { + let block_hash_match = match (blocks.get(0), protocol.client().block_hash(num)) { + (Some(ref block), Ok(maybe_our_block_hash)) => { + trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", num, block.hash, who); + maybe_our_block_hash.map_or(false, |x| x == block.hash) }, - None => { + (None, _) => { trace!(target:"sync", "Invalid response when searching for ancestor from {}", who); protocol.report_peer(who, Severity::Bad("Invalid response when searching for ancestor".to_string())); return; - } + }, + (_, Err(e)) => { + let reason = format!("Error answering legitimate blockchain query: {:?}", e); + protocol.report_peer(who, Severity::Useless(reason)); + return; + }, + }; + if block_hash_match && peer.common_number < num { + peer.common_number = num; + } + if !block_hash_match && num == As::sa(0) { + trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); + protocol.report_peer(who, Severity::Bad("Ancestry search: genesis mismatch for peer".to_string())); + return; + } + if let Some((next_state, next_block_num)) = Self::handle_ancestor_search_state(state, num, block_hash_match) { + peer.state = PeerSyncState::AncestorSearch(next_block_num, next_state); + Self::request_ancestry(protocol, who, next_block_num); + return; + } else { + peer.state = PeerSyncState::Available; + vec![] } }, PeerSyncState::Available | PeerSyncState::DownloadingJustification(..) => Vec::new(), @@ -616,7 +698,7 @@ impl ChainSync { pub(crate) fn on_block_justification_data( &mut self, protocol: &mut Context, - who: NodeIndex, + who: PeerId, _request: message::BlockRequest, response: message::BlockResponse, ) { @@ -675,7 +757,7 @@ impl ChainSync { if self.is_stopping.load(Ordering::SeqCst) { return } - let peers: Vec = self.peers.keys().map(|p| *p).collect(); + let peers: Vec = self.peers.keys().map(|p| p.clone()).collect(); for peer in peers { self.download_new(protocol, peer); } @@ -745,7 +827,7 @@ impl ChainSync { } // Update common blocks for (n, peer) in self.peers.iter_mut() { - if let PeerSyncState::AncestorSearch(_) = peer.state { + if let PeerSyncState::AncestorSearch(_, _) = peer.state { // Abort search. peer.state = PeerSyncState::Available; } @@ -764,13 +846,17 @@ impl ChainSync { } /// Handle new block announcement. - pub(crate) fn on_block_announce(&mut self, protocol: &mut Context, who: NodeIndex, hash: B::Hash, header: &B::Header) { + pub(crate) fn on_block_announce(&mut self, protocol: &mut Context, who: PeerId, hash: B::Hash, header: &B::Header) { let number = *header.number(); if number <= As::sa(0) { trace!(target: "sync", "Ignored invalid block announcement from {}: {}", who, hash); return; } - let known_parent = self.is_known(protocol, &header.parent_hash()); + let parent_status = block_status(&*protocol.client(), &self.queue_blocks, header.parent_hash().clone()).ok() + .unwrap_or(BlockStatus::Unknown); + let known_parent = parent_status != BlockStatus::Unknown; + let ancient_parent = parent_status == BlockStatus::InChainPruned; + let known = self.is_known(protocol, &hash); if let Some(ref mut peer) = self.peers.get_mut(&who) { while peer.recently_announced.len() >= ANNOUNCE_HISTORY_SIZE { @@ -782,7 +868,7 @@ impl ChainSync { peer.best_number = number; peer.best_hash = hash; } - if let PeerSyncState::AncestorSearch(_) = peer.state { + if let PeerSyncState::AncestorSearch(_, _) = peer.state { return; } if header.parent_hash() == &self.best_queued_hash || known_parent { @@ -798,15 +884,28 @@ impl ChainSync { let stale = number <= self.best_queued_number; if stale { if !(known_parent || self.is_already_downloading(header.parent_hash())) { - trace!(target: "sync", "Considering new unknown stale block announced from {}: {} {:?}", who, hash, header); - self.download_unknown_stale(protocol, who, &hash); + if protocol.client().block_status(&BlockId::Number(*header.number())) + .unwrap_or(BlockStatus::Unknown) == BlockStatus::InChainPruned + { + trace!(target: "sync", "Ignored unknown ancient block announced from {}: {} {:?}", who, hash, header); + } else { + trace!(target: "sync", "Considering new unknown stale block announced from {}: {} {:?}", who, hash, header); + self.download_unknown_stale(protocol, who, &hash); + } } else { - trace!(target: "sync", "Considering new stale block announced from {}: {} {:?}", who, hash, header); - self.download_stale(protocol, who, &hash); + if ancient_parent { + trace!(target: "sync", "Ignored ancient stale block announced from {}: {} {:?}", who, hash, header); + } else { + self.download_stale(protocol, who, &hash); + } } } else { - trace!(target: "sync", "Considering new block announced from {}: {} {:?}", who, hash, header); - self.download_new(protocol, who); + if ancient_parent { + trace!(target: "sync", "Ignored ancient block announced from {}: {} {:?}", who, hash, header); + } else { + trace!(target: "sync", "Considering new block announced from {}: {} {:?}", who, hash, header); + self.download_new(protocol, who); + } } } else { trace!(target: "sync", "Known block announce from {}: {}", who, hash); @@ -822,10 +921,10 @@ impl ChainSync { } /// Handle disconnected peer. - pub(crate) fn peer_disconnected(&mut self, protocol: &mut Context, who: NodeIndex) { + pub(crate) fn peer_disconnected(&mut self, protocol: &mut Context, who: PeerId) { let previous_best_seen = self.best_seen_block(); let previous_state = self.state(&previous_best_seen); - self.blocks.clear_peer_download(who); + self.blocks.clear_peer_download(&who); self.peers.remove(&who); if self.peers.len() == 0 { // We're not connected to any peer anymore. @@ -859,7 +958,7 @@ impl ChainSync { self.best_queued_number = As::sa(0); } } - let ids: Vec = self.peers.drain().map(|(id, _)| id).collect(); + let ids: Vec = self.peers.drain().map(|(id, _)| id).collect(); for id in ids { self.new_peer(protocol, id); } @@ -872,7 +971,7 @@ impl ChainSync { } // Download old block with known parent. - fn download_stale(&mut self, protocol: &mut Context, who: NodeIndex, hash: &B::Hash) { + fn download_stale(&mut self, protocol: &mut Context, who: PeerId, hash: &B::Hash) { if let Some(ref mut peer) = self.peers.get_mut(&who) { match peer.state { PeerSyncState::Available => { @@ -893,7 +992,7 @@ impl ChainSync { } // Download old block with unknown parent. - fn download_unknown_stale(&mut self, protocol: &mut Context, who: NodeIndex, hash: &B::Hash) { + fn download_unknown_stale(&mut self, protocol: &mut Context, who: PeerId, hash: &B::Hash) { if let Some(ref mut peer) = self.peers.get_mut(&who) { match peer.state { PeerSyncState::Available => { @@ -914,7 +1013,7 @@ impl ChainSync { } // Issue a request for a peer to download new blocks, if any are available - fn download_new(&mut self, protocol: &mut Context, who: NodeIndex) { + fn download_new(&mut self, protocol: &mut Context, who: PeerId) { if let Some(ref mut peer) = self.peers.get_mut(&who) { // when there are too many blocks in the queue => do not try to download new blocks if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { @@ -924,7 +1023,7 @@ impl ChainSync { match peer.state { PeerSyncState::Available => { trace!(target: "sync", "Considering new block download from {}, common block is {}, best is {:?}", who, peer.common_number, peer.best_number); - if let Some(range) = self.blocks.needed_blocks(who, MAX_BLOCKS_TO_REQUEST, peer.best_number, peer.common_number) { + if let Some(range) = self.blocks.needed_blocks(who.clone(), MAX_BLOCKS_TO_REQUEST, peer.best_number, peer.common_number) { trace!(target: "sync", "Requesting blocks from {}, ({} to {})", who, range.start, range.end); let request = message::generic::BlockRequest { id: 0, @@ -945,7 +1044,7 @@ impl ChainSync { } } - fn request_ancestry(protocol: &mut Context, who: NodeIndex, block: NumberFor) { + fn request_ancestry(protocol: &mut Context, who: PeerId, block: NumberFor) { trace!(target: "sync", "Requesting ancestry block #{} from {}", block, who); let request = message::generic::BlockRequest { id: 0, diff --git a/core/network/src/test/block_import.rs b/core/network/src/test/block_import.rs index c8999419aa936b73071f879f5f5ff3642a0a9104..3b5e44cc47e5a76d1b2b65de3ded66a0f78abdfa 100644 --- a/core/network/src/test/block_import.rs +++ b/core/network/src/test/block_import.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -26,7 +26,7 @@ struct TestLink {} impl Link for TestLink {} -fn prepare_good_block() -> (client::Client, Hash, u64, IncomingBlock) { +fn prepare_good_block() -> (client::Client, Hash, u64, PeerId, IncomingBlock) { let client = test_client::new(); let block = client.new_block().unwrap().bake().unwrap(); client.import(BlockOrigin::File, block).unwrap(); @@ -34,27 +34,28 @@ fn prepare_good_block() -> (client::Client for DummySpecialization { vec![] } - fn on_connect(&mut self, _ctx: &mut Context, _peer_id: NodeIndex, _status: crate::message::Status) { + fn on_connect(&mut self, _ctx: &mut Context, _peer_id: PeerId, _status: crate::message::Status) { } - fn on_disconnect(&mut self, _ctx: &mut Context, _peer_id: NodeIndex) { + fn on_disconnect(&mut self, _ctx: &mut Context, _peer_id: PeerId) { } fn on_message( &mut self, _ctx: &mut Context, - _peer_id: NodeIndex, + _peer_id: PeerId, _message: &mut Option>, ) { } @@ -167,7 +166,7 @@ impl + Clone> Link for TestLink { self.link.blocks_processed(processed_blocks, has_error); } - fn justification_imported(&self, who: NodeIndex, hash: &Hash, number:NumberFor, success: bool) { + fn justification_imported(&self, who: PeerId, hash: &Hash, number:NumberFor, success: bool) { self.link.justification_imported(who, hash, number, success); } @@ -175,11 +174,11 @@ impl + Clone> Link for TestLink { self.link.request_justification(hash, number); } - fn useless_peer(&self, who: NodeIndex, reason: &str) { + fn useless_peer(&self, who: PeerId, reason: &str) { self.link.useless_peer(who, reason); } - fn note_useless_and_restart_sync(&self, who: NodeIndex, reason: &str) { + fn note_useless_and_restart_sync(&self, who: PeerId, reason: &str) { self.link.note_useless_and_restart_sync(who, reason); } @@ -191,7 +190,8 @@ impl + Clone> Link for TestLink { pub struct Peer + Clone> { pub is_offline: Arc, pub is_major_syncing: Arc, - pub peers: Arc>>>, + pub peers: Arc>>>, + pub peer_id: PeerId, client: Arc, network_to_protocol_sender: Sender>, pub protocol_sender: Sender>, @@ -207,7 +207,7 @@ impl + Clone> Peer { fn new( is_offline: Arc, is_major_syncing: Arc, - peers: Arc>>>, + peers: Arc>>>, client: Arc, import_queue: Box>, network_to_protocol_sender: Sender>, @@ -223,6 +223,7 @@ impl + Clone> Peer { is_offline, is_major_syncing, peers, + peer_id: PeerId::random(), client, network_to_protocol_sender, protocol_sender, @@ -259,32 +260,34 @@ impl + Clone> Peer { } // SyncOracle: are we connected to any peer? + #[cfg(test)] fn is_offline(&self) -> bool { self.is_offline.load(Ordering::Relaxed) } // SyncOracle: are we in the process of catching-up with the chain? + #[cfg(test)] fn is_major_syncing(&self) -> bool { self.is_major_syncing.load(Ordering::Relaxed) } /// Called on connection to other indicated peer. - fn on_connect(&self, other: NodeIndex) { - let _ = self.network_to_protocol_sender.send(FromNetworkMsg::PeerConnected(PeerId::random(), other, String::new())); + fn on_connect(&self, other: &Self) { + let _ = self.network_to_protocol_sender.send(FromNetworkMsg::PeerConnected(other.peer_id.clone(), String::new())); } /// Called on disconnect from other indicated peer. - fn on_disconnect(&self, other: NodeIndex) { + fn on_disconnect(&self, other: &Self) { let _ = self .network_to_protocol_sender - .send(FromNetworkMsg::PeerDisconnected(other, String::new())); + .send(FromNetworkMsg::PeerDisconnected(other.peer_id.clone(), String::new())); } /// Receive a message from another peer. Return a set of peers to disconnect. - fn receive_message(&self, from: NodeIndex, msg: Message) { + fn receive_message(&self, from: &Self, msg: Message) { let _ = self .network_to_protocol_sender - .send(FromNetworkMsg::CustomMessage(from, msg)); + .send(FromNetworkMsg::CustomMessage(from.peer_id.clone(), msg)); } /// Produce the next pending message to send to another peer. @@ -356,10 +359,16 @@ impl + Clone> Peer { /// Push a message into the gossip network and relay to peers. /// `TestNet::sync_step` needs to be called to ensure it's propagated. - pub fn gossip_message(&self, topic: ::Hash, engine_id: ConsensusEngineId, data: Vec) { + pub fn gossip_message( + &self, + topic: ::Hash, + engine_id: ConsensusEngineId, + data: Vec, + force: bool, + ) { let _ = self .protocol_sender - .send(ProtocolMsg::GossipConsensusMessage(topic, engine_id, data)); + .send(ProtocolMsg::GossipConsensusMessage(topic, engine_id, data, force)); } pub fn consensus_gossip_collect_garbage_for_topic(&self, _topic: ::Hash) { @@ -458,12 +467,12 @@ impl + Clone> Peer { if with_tx { self.generate_blocks_at(at, count, BlockOrigin::File, |mut builder| { let transfer = Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Alice.into(), amount: 1, nonce, }; - let signature = Keyring::from_raw_public(transfer.from.to_fixed_bytes()).unwrap().sign(&transfer.encode()).into(); + let signature = AccountKeyring::from_public(&transfer.from).unwrap().sign(&transfer.encode()).into(); builder.push(Extrinsic::Transfer(transfer, signature)).unwrap(); nonce = nonce + 1; builder.bake().unwrap() @@ -473,7 +482,7 @@ impl + Clone> Peer { } } - pub fn push_authorities_change_block(&self, new_authorities: Vec) -> H256 { + pub fn push_authorities_change_block(&self, new_authorities: Vec) -> H256 { self.generate_blocks(1, BlockOrigin::File, |mut builder| { builder.push(Extrinsic::AuthoritiesChange(new_authorities.clone())).unwrap(); builder.bake().unwrap() @@ -555,14 +564,14 @@ pub trait TestNetFactory: Sized { let tx_pool = Arc::new(EmptyTransactionPool); let verifier = self.make_verifier(client.clone(), config); let (block_import, justification_import, data) = self.make_block_import(client.clone()); - let (network_sender, network_port) = network_channel(ProtocolId::default()); + let (network_sender, network_port) = network_channel(); let import_queue = Box::new(BasicQueue::new(verifier, block_import, justification_import)); let status_sinks = Arc::new(Mutex::new(Vec::new())); let is_offline = Arc::new(AtomicBool::new(true)); let is_major_syncing = Arc::new(AtomicBool::new(false)); let specialization = self::SpecializationFactory::create(); - let peers: Arc>>> = Arc::new(Default::default()); + let peers: Arc>>> = Arc::new(Default::default()); let (protocol_sender, network_to_protocol_sender) = Protocol::new( status_sinks, @@ -601,49 +610,49 @@ pub trait TestNetFactory: Sized { if self.started() { return; } - self.mut_peers(|peers| { - for peer in 0..peers.len() { - peers[peer].start(); - for client in 0..peers.len() { - if peer != client { - peers[peer].on_connect(client as NodeIndex); - } + for peer in self.peers() { + peer.start(); + for client in self.peers() { + if peer.peer_id != client.peer_id { + peer.on_connect(client); } } - }); + } self.route(None); self.set_started(true); } /// Do one step of routing. - fn route(&mut self, disconnected: Option>) { + fn route(&mut self, disconnected: Option>) { self.mut_peers(move |peers| { let mut to_disconnect = HashSet::new(); - for peer in 0..peers.len() { - let packet = peers[peer].pending_message(); + for (peer_pos, peer) in peers.iter().enumerate() { + let packet = peer.pending_message(); match packet { None => continue, Some(NetworkMsg::Outgoing(recipient, packet)) => { + let recipient = peers.iter().position(|p| p.peer_id == recipient).unwrap(); if let Some(disconnected) = disconnected.as_ref() { let mut current = HashSet::new(); - current.insert(peer); + current.insert(peer_pos); current.insert(recipient); // Not routing message between "disconnected" nodes. if disconnected.is_subset(¤t) { continue; } } - peers[recipient].receive_message(peer as NodeIndex, packet) + peers[recipient].receive_message(peer, packet) } Some(NetworkMsg::ReportPeer(who, _)) => { to_disconnect.insert(who); } - Some(_msg) => continue, } } for d in to_disconnect { - for peer in 0..peers.len() { - peers[peer].on_disconnect(d); + if let Some(d) = peers.iter().find(|p| p.peer_id == d) { + for peer in 0..peers.len() { + peers[peer].on_disconnect(d); + } } } }); @@ -654,7 +663,9 @@ pub trait TestNetFactory: Sized { self.mut_peers(move |peers| { for peer in 0..peers.len() { while let Some(NetworkMsg::Outgoing(recipient, packet)) = peers[peer].pending_message_fast() { - peers[recipient].receive_message(peer as NodeIndex, packet) + if let Some(p) = peers.iter().find(|p| p.peer_id == recipient) { + p.receive_message(&peers[peer], packet) + } } } }); @@ -696,7 +707,7 @@ pub trait TestNetFactory: Sized { /// Perform synchronization until complete, if provided the /// given nodes set are excluded from sync. - fn sync_with(&mut self, disconnected: Option>) -> u32 { + fn sync_with(&mut self, disconnected: Option>) -> u32 { self.start(); let mut total_steps = 0; let mut done = 0; @@ -725,7 +736,7 @@ pub trait TestNetFactory: Sized { /// Perform synchronization until complete, /// excluding sync between certain nodes. - fn sync_with_disconnected(&mut self, disconnected: HashSet) -> u32 { + fn sync_with_disconnected(&mut self, disconnected: HashSet) -> u32 { self.sync_with(Some(disconnected)) } diff --git a/core/network/src/test/sync.rs b/core/network/src/test/sync.rs index d23b98496b1ec35db75b824192e3e28e7a181431..9bbf0a32b7fd1a993e07f1ea85bd1cb0a7225a99 100644 --- a/core/network/src/test/sync.rs +++ b/core/network/src/test/sync.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,12 +18,29 @@ use client::backend::Backend; use client::blockchain::HeaderBackend as BlockchainHeaderBackend; use crate::config::Roles; use consensus::BlockOrigin; -use network_libp2p::NodeIndex; use std::collections::HashSet; use std::thread; use std::time::Duration; use super::*; +fn test_ancestor_search_when_common_is(n: usize) { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + net.peer(0).push_blocks(n, false); + net.peer(1).push_blocks(n, false); + net.peer(2).push_blocks(n, false); + + net.peer(0).push_blocks(10, true); + net.peer(1).push_blocks(100, false); + net.peer(2).push_blocks(100, false); + + net.restart_peer(0); + net.sync(); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); +} + #[test] fn sync_peers_works() { let _ = ::env_logger::try_init(); @@ -36,7 +53,7 @@ fn sync_peers_works() { // And then disconnect. for other in 0..3 { if other != peer { - net.peer(peer).on_disconnect(other); + net.peer(peer).on_disconnect(net.peer(other)); } } } @@ -82,7 +99,7 @@ fn sync_cycle_from_offline_to_syncing_to_offline() { for peer in 0..3 { for other in 0..3 { if other != peer { - net.peer(peer).on_disconnect(other); + net.peer(peer).on_disconnect(net.peer(other)); } } thread::sleep(Duration::from_millis(100)); @@ -107,8 +124,8 @@ fn syncing_node_not_major_syncing_when_disconnected() { assert!(net.peer(1).is_major_syncing()); // Disconnect peer 1 form everyone else. - net.peer(1).on_disconnect(0); - net.peer(1).on_disconnect(2); + net.peer(1).on_disconnect(net.peer(0)); + net.peer(1).on_disconnect(net.peer(2)); thread::sleep(Duration::from_millis(100)); // Peer 1 is not major-syncing. @@ -140,6 +157,51 @@ fn sync_from_two_peers_with_ancestry_search_works() { .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); } +#[test] +fn ancestry_search_works_when_backoff_is_one() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + net.peer(0).push_blocks(1, false); + net.peer(1).push_blocks(2, false); + net.peer(2).push_blocks(2, false); + + net.restart_peer(0); + net.sync(); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); +} + +#[test] +fn ancestry_search_works_when_ancestor_is_genesis() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + net.peer(0).push_blocks(13, true); + net.peer(1).push_blocks(100, false); + net.peer(2).push_blocks(100, false); + + net.restart_peer(0); + net.sync(); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); +} + +#[test] +fn ancestry_search_works_when_common_is_one() { + test_ancestor_search_when_common_is(1); +} + +#[test] +fn ancestry_search_works_when_common_is_two() { + test_ancestor_search_when_common_is(2); +} + +#[test] +fn ancestry_search_works_when_common_is_hundred() { + test_ancestor_search_when_common_is(100); +} + #[test] fn sync_long_chain_works() { let mut net = TestNet::new(2); @@ -294,13 +356,13 @@ fn blocks_are_not_announced_by_light_nodes() { net.peer(0).start(); net.peer(1).start(); net.peer(2).start(); - net.peer(0).on_connect(1); - net.peer(1).on_connect(2); + net.peer(0).on_connect(net.peer(1)); + net.peer(1).on_connect(net.peer(2)); // Only sync between 0 -> 1, and 1 -> 2 let mut disconnected = HashSet::new(); - disconnected.insert(0 as NodeIndex); - disconnected.insert(2 as NodeIndex); + disconnected.insert(0); + disconnected.insert(2); net.sync_with_disconnected(disconnected); // peer 0 has the best chain diff --git a/core/offchain/Cargo.toml b/core/offchain/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..8cd1d2edc557db77fe5b4785e3e514919af4f147 --- /dev/null +++ b/core/offchain/Cargo.toml @@ -0,0 +1,27 @@ +[package] +description = "Substrate offchain workers" +name = "substrate-offchain" +version = "0.1.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +client = { package = "substrate-client", path = "../../core/client" } +consensus = { package = "substrate-consensus-common", path = "../../core/consensus/common" } +futures = "0.1.25" +inherents = { package = "substrate-inherents", path = "../../core/inherents" } +log = "0.4" +offchain-primitives = { package = "substrate-offchain-primitives", path = "./primitives" } +parity-codec = { version = "3.1", features = ["derive"] } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } +tokio = "0.1.7" +transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } + +[dev-dependencies] +env_logger = "0.6" +test_client = { package = "substrate-test-client", path = "../../core/test-client" } + +[features] +default = [] diff --git a/core/offchain/primitives/Cargo.toml b/core/offchain/primitives/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..4d10e08f92dd603176b18fc5bc554fe909ae76a6 --- /dev/null +++ b/core/offchain/primitives/Cargo.toml @@ -0,0 +1,18 @@ +[package] +description = "Substrate offchain workers primitives" +name = "substrate-offchain-primitives" +version = "0.1.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +client = { package = "substrate-client", path = "../../client", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "client/std", + "runtime_primitives/std" +] diff --git a/core/offchain/primitives/src/lib.rs b/core/offchain/primitives/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..c05e8dceb90cec525835929e92e5c7788ebc05cf --- /dev/null +++ b/core/offchain/primitives/src/lib.rs @@ -0,0 +1,31 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! The Offchain Worker runtime api primitives. + +#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] + +use client::decl_runtime_apis; +use runtime_primitives::traits::NumberFor; + +decl_runtime_apis! { + /// The offchain worker api. + pub trait OffchainWorkerApi { + /// Starts the off-chain task for given block number. + fn offchain_worker(number: NumberFor); + } +} diff --git a/core/offchain/src/api.rs b/core/offchain/src/api.rs new file mode 100644 index 0000000000000000000000000000000000000000..5d2a636be3924d82a18453750ae94130fdc95aa5 --- /dev/null +++ b/core/offchain/src/api.rs @@ -0,0 +1,99 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::sync::Arc; +use futures::{Stream, Future, sync::mpsc}; +use inherents::pool::InherentsPool; +use log::{info, debug, warn}; +use parity_codec::Decode; +use primitives::OffchainExt; +use runtime_primitives::{ + generic::BlockId, + traits::{self, Extrinsic}, +}; +use transaction_pool::txpool::{Pool, ChainApi}; + +/// A message between the offchain extension and the processing thread. +enum ExtMessage { + SubmitExtrinsic(Vec), +} + +/// Asynchronous offchain API. +/// +/// NOTE this is done to prevent recursive calls into the runtime (which are not supported currently). +pub(crate) struct AsyncApi(mpsc::UnboundedSender); + +impl OffchainExt for AsyncApi { + fn submit_extrinsic(&mut self, ext: Vec) { + let _ = self.0.unbounded_send(ExtMessage::SubmitExtrinsic(ext)); + } +} + +/// Offchain extensions implementation API +pub(crate) struct Api { + receiver: Option>, + transaction_pool: Arc>, + inherents_pool: Arc::Extrinsic>>, + at: BlockId, +} + +impl Api { + pub fn new( + transaction_pool: Arc>, + inherents_pool: Arc::Extrinsic>>, + at: BlockId, + ) -> (AsyncApi, Self) { + let (tx, rx) = mpsc::unbounded(); + let api = Self { + receiver: Some(rx), + transaction_pool, + inherents_pool, + at, + }; + (AsyncApi(tx), api) + } + + /// Run a processing task for the API + pub fn process(mut self) -> impl Future { + let receiver = self.receiver.take().expect("Take invoked only once."); + + receiver.for_each(move |msg| { + match msg { + ExtMessage::SubmitExtrinsic(ext) => self.submit_extrinsic(ext), + } + Ok(()) + }) + } + + fn submit_extrinsic(&mut self, ext: Vec) { + let xt = match ::Extrinsic::decode(&mut &*ext) { + Some(xt) => xt, + None => { + warn!("Unable to decode extrinsic: {:?}", ext); + return + }, + }; + + info!("Submitting to the pool: {:?} (isSigned: {:?})", xt, xt.is_signed()); + match self.transaction_pool.submit_one(&self.at, xt.clone()) { + Ok(hash) => debug!("[{:?}] Offchain transaction added to the pool.", hash), + Err(_) => { + debug!("Offchain inherent added to the pool."); + self.inherents_pool.add(xt); + }, + } + } +} diff --git a/core/offchain/src/lib.rs b/core/offchain/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..cac960f2506f26ec409791065b68efdd8d565407 --- /dev/null +++ b/core/offchain/src/lib.rs @@ -0,0 +1,132 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate offchain workers. +//! +//! The offchain workers is a special function of the runtime that +//! gets executed after block is imported. During execution +//! it's able to asynchronously submit extrinsics that will either +//! be propagated to other nodes (transactions) or will be +//! added to the next block produced by the node as inherents. +//! +//! Offchain workers can be used for computation-heavy tasks +//! that are not feasible for execution during regular block processing. +//! It can either be tasks that no consensus is required for, +//! or some form of consensus over the data can be built on-chain +//! for instance via: +//! 1. Challenge period for incorrect computations +//! 2. Majority voting for results +//! 3. etc + +#![warn(missing_docs)] + +use std::{ + marker::PhantomData, + sync::Arc, +}; + +use client::runtime_api::ApiExt; +use inherents::pool::InherentsPool; +use log::{debug, warn}; +use primitives::ExecutionContext; +use runtime_primitives::{ + generic::BlockId, + traits::{self, ProvideRuntimeApi}, +}; +use tokio::runtime::TaskExecutor; +use transaction_pool::txpool::{Pool, ChainApi}; + +mod api; + +pub use offchain_primitives::OffchainWorkerApi; + +/// An offchain workers manager. +#[derive(Debug)] +pub struct OffchainWorkers { + client: Arc, + inherents_pool: Arc::Extrinsic>>, + executor: TaskExecutor, + _block: PhantomData, +} + +impl OffchainWorkers { + /// Creates new `OffchainWorkers`. + pub fn new( + client: Arc, + inherents_pool: Arc::Extrinsic>>, + executor: TaskExecutor, + ) -> Self { + Self { + client, + inherents_pool, + executor, + _block: PhantomData, + } + } +} + +impl OffchainWorkers where + Block: traits::Block, + C: ProvideRuntimeApi, + C::Api: OffchainWorkerApi, +{ + /// Start the offchain workers after given block. + pub fn on_block_imported( + &self, + number: &::Number, + pool: &Arc>, + ) where + A: ChainApi + 'static, + { + let runtime = self.client.runtime_api(); + let at = BlockId::number(*number); + let has_api = runtime.has_api::>(&at); + debug!("Checking offchain workers at {:?}: {:?}", at, has_api); + + if has_api.unwrap_or(false) { + let (api, runner) = api::Api::new(pool.clone(), self.inherents_pool.clone(), at.clone()); + self.executor.spawn(runner.process()); + + debug!("Running offchain workers at {:?}", at); + let api = Box::new(api); + runtime.offchain_worker_with_context(&at, ExecutionContext::OffchainWorker(api), *number).unwrap(); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures::Future; + + #[test] + fn should_call_into_runtime_and_produce_extrinsic() { + // given + let _ = env_logger::try_init(); + let runtime = tokio::runtime::Runtime::new().unwrap(); + let client = Arc::new(test_client::new()); + let pool = Arc::new(Pool::new(Default::default(), ::transaction_pool::ChainApi::new(client.clone()))); + let inherents = Arc::new(InherentsPool::default()); + + // when + let offchain = OffchainWorkers::new(client, inherents.clone(), runtime.executor()); + offchain.on_block_imported(&0u64, &pool); + + // then + runtime.shutdown_on_idle().wait().unwrap(); + assert_eq!(inherents.drain().len(), 1); + } +} diff --git a/core/panic-handler/src/lib.rs b/core/panic-handler/src/lib.rs index 91f7c0af97dd3c685b569a1b994bd923fdb3646c..b2fd7238e0d2e77621af4a0c345ed4433b931bab 100644 --- a/core/panic-handler/src/lib.rs +++ b/core/panic-handler/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/peerset/Cargo.toml b/core/peerset/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..c2247cdd0b2b2fe9fbf0037ace278371b68f20ec --- /dev/null +++ b/core/peerset/Cargo.toml @@ -0,0 +1,20 @@ +[package] +description = "Connectivity manager based on reputation" +homepage = "http://parity.io" +license = "GPL-3.0" +name = "substrate-peerset" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +fnv = "1.0" +futures = "0.1" +libp2p = { version = "0.6.0", default-features = false } +log = "0.4" +parking_lot = "0.7" +rand = "0.6" +serde = "1.0.70" +serde_derive = "1.0.70" +serde_json = "1.0.24" +tokio-io = "0.1" diff --git a/core/peerset/src/lib.rs b/core/peerset/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..b64cafc3e564fa5d3c452f2618bbb102485caf68 --- /dev/null +++ b/core/peerset/src/lib.rs @@ -0,0 +1,316 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Peer Set Manager (PSM). Contains the strategy for choosing which nodes the network should be +//! connected to. + +use std::collections::HashSet; +use futures::{prelude::*, sync::mpsc}; +use libp2p::PeerId; +use parking_lot::Mutex; +use std::sync::Arc; + +pub use serde_json::Value; + +/// Shared part of the peer set manager (PSM). Distributed around the code. +pub struct Peerset { + tx: mpsc::UnboundedSender, + inner: Mutex, +} + +struct Inner { + /// List of nodes that we know exist but we are not connected to. + /// Elements in this list must never be in `out_slots` or `in_slots`. + discovered: Vec, + /// List of reserved nodes. + reserved: HashSet, + /// If true, we only accept reserved nodes. + reserved_only: bool, + /// Node slots for outgoing connections. Each slot contains either `None` if the node is free, + /// or `Some` if it is assigned to a peer. + out_slots: Vec>, + /// Node slots for incoming connections. Each slot contains either `None` if the node is free, + /// or `Some` if it is assigned to a peer. + in_slots: Vec>, +} + +/// Message that can be sent by the peer set manager (PSM). +#[derive(Debug)] +pub enum Message { + /// Request to open a connection to the given peer. From the point of view of the PSM, we are + /// immediately connected. + Connect(PeerId), + + /// Drop the connection to the given peer, or cancel the connection attempt after a `Connect`. + Drop(PeerId), + + /// Equivalent to `Connect` for the peer corresponding to this incoming index. + Accept(IncomingIndex), + + /// Equivalent to `Drop` for the peer corresponding to this incoming index. + Reject(IncomingIndex), +} + +/// Opaque identifier for an incoming connection. Allocated by the network. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct IncomingIndex(pub u64); + +impl From for IncomingIndex { + fn from(val: u64) -> IncomingIndex { + IncomingIndex(val) + } +} + +/// Configuration to pass when creating the peer set manager. +#[derive(Debug)] +pub struct PeersetConfig { + /// Maximum number of ingoing links to peers. + pub in_peers: u32, + + /// Maximum number of outgoing links to peers. + pub out_peers: u32, + + /// List of bootstrap nodes to initialize the peer with. + /// + /// > **Note**: Keep in mind that the networking has to know an address for these nodes, + /// > otherwise it will not be able to connect to them. + pub bootnodes: Vec, + + /// If true, we only accept reserved nodes. + pub reserved_only: bool, + + /// List of nodes that we should always be connected to. + /// + /// > **Note**: Keep in mind that the networking has to know an address for these nodes, + /// > otherwise it will not be able to connect to them. + pub reserved_nodes: Vec, +} + +/// Side of the peer set manager owned by the network. In other words, the "receiving" side. +/// +/// Implements the `Stream` trait and can be polled for messages. The `Stream` never ends and never +/// errors. +pub struct PeersetMut { + parent: Arc, + rx: mpsc::UnboundedReceiver, +} + +impl Peerset { + /// Builds a new peerset from the given configuration. + pub fn from_config(config: PeersetConfig) -> (Arc, PeersetMut) { + let (tx, rx) = mpsc::unbounded(); + + let mut inner = Inner { + discovered: config.bootnodes.into_iter().collect(), + reserved: Default::default(), + reserved_only: config.reserved_only, + out_slots: (0 .. config.out_peers).map(|_| None).collect(), + in_slots: (0 .. config.in_peers).map(|_| None).collect(), + }; + + alloc_slots(&mut inner, &tx); + + let peerset = Arc::new(Peerset { + tx, + inner: Mutex::new(inner), + }); + + let rx = PeersetMut { + parent: peerset.clone(), + rx, + }; + + for reserved in config.reserved_nodes { + peerset.add_reserved_peer(reserved); + } + + (peerset, rx) + } + + /// Adds a new reserved peer. The peerset will make an effort to always remain connected to + /// this peer. + /// + /// Has no effect if the node was already a reserved peer. + /// + /// > **Note**: Keep in mind that the networking has to know an address for this node, + /// > otherwise it will not be able to connect to it. + pub fn add_reserved_peer(&self, peer_id: PeerId) { + let mut inner = self.inner.lock(); + if !inner.reserved.insert(peer_id.clone()) { + // Immediately return if this peer was already in the list. + return; + } + + // Nothing more to do if we're already connected. + if inner.out_slots.iter().chain(inner.in_slots.iter()).any(|s| s.as_ref() == Some(&peer_id)) { + return; + } + + // Assign a slot for this reserved peer. + if let Some(pos) = inner.out_slots.iter().position(|s| s.as_ref().map(|n| !inner.reserved.contains(n)).unwrap_or(true)) { + let _ = self.tx.unbounded_send(Message::Connect(peer_id.clone())); + inner.out_slots[pos] = Some(peer_id); + + } else { + // All slots are filled with reserved peers. + if inner.discovered.iter().all(|p| *p != peer_id) { + inner.discovered.push(peer_id); + } + } + } + + /// Remove a previously-added reserved peer. + /// + /// Has no effect if the node was not a reserved peer. + pub fn remove_reserved_peer(&self, peer_id: &PeerId) { + let mut inner = self.inner.lock(); + inner.reserved.remove(peer_id); + } + + /// Sets whether or not the peerset only has connections . + pub fn set_reserved_only(&self, reserved_only: bool) { + let mut inner = self.inner.lock(); + let inner = &mut *inner; // Fixes a borrowing issue. + inner.reserved_only = reserved_only; + + // Disconnect non-reserved nodes. + if reserved_only { + for slot in inner.out_slots.iter_mut().chain(inner.in_slots.iter_mut()) { + if let Some(peer) = slot.as_ref() { + if inner.reserved.contains(peer) { + continue; + } + + let _ = self.tx.unbounded_send(Message::Drop(peer.clone())); + } + + *slot = None; + } + } + } + + /// Reports an adjustement to the reputation of the given peer. + pub fn report_peer(&self, _peer_id: &PeerId, _score_diff: i32) { + // This is not implemented in this dummy implementation. + } +} + +fn alloc_slots(inner: &mut Inner, tx: &mpsc::UnboundedSender) { + if inner.reserved_only { + return; + } + + for slot in inner.out_slots.iter_mut() { + if slot.is_some() { + continue; + } + + if !inner.discovered.is_empty() { + let elem = inner.discovered.remove(0); + *slot = Some(elem.clone()); + let _ = tx.unbounded_send(Message::Connect(elem)); + } + } +} + +impl PeersetMut { + /// Indicate that we received an incoming connection. Must be answered either with + /// a corresponding `Accept` or `Reject`, except if we were already connected to this peer. + /// + /// Note that this mechanism is orthogonal to `Connect`/`Drop`. Accepting an incoming + /// connection implicitely means `Accept`, but incoming connections aren't cancelled by + /// `dropped`. + /// + /// Because of concurrency issues, it is acceptable to call `incoming` with a `PeerId` the + /// peerset is already connected to, in which case it must not answer. + pub fn incoming(&self, peer_id: PeerId, index: IncomingIndex) { + let mut inner = self.parent.inner.lock(); + if inner.out_slots.iter().chain(inner.in_slots.iter()).any(|s| s.as_ref() == Some(&peer_id)) { + return + } + + if let Some(pos) = inner.in_slots.iter().position(|s| s.is_none()) { + inner.in_slots[pos] = Some(peer_id); + let _ = self.parent.tx.unbounded_send(Message::Accept(index)); + } else { + if inner.discovered.iter().all(|p| *p != peer_id) { + inner.discovered.push(peer_id); + } + let _ = self.parent.tx.unbounded_send(Message::Reject(index)); + } + } + + /// Indicate that we dropped an active connection with a peer, or that we failed to connect. + /// + /// Must only be called after the PSM has either generated a `Connect` message with this + /// `PeerId`, or accepted an incoming connection with this `PeerId`. + pub fn dropped(&self, peer_id: &PeerId) { + let mut inner = self.parent.inner.lock(); + let inner = &mut *inner; // Fixes a borrowing issue. + + // Automatically connect back if reserved. + if inner.reserved.contains(peer_id) { + let _ = self.parent.tx.unbounded_send(Message::Connect(peer_id.clone())); + return + } + + // Otherwise, free the slot. + for slot in inner.out_slots.iter_mut().chain(inner.in_slots.iter_mut()) { + if slot.as_ref() == Some(peer_id) { + *slot = None; + break; + } + } + + // Note: in this dummy implementation we consider that peers never expire. As soon as we + // are disconnected from a peer, we try again. + if inner.discovered.iter().all(|p| p != peer_id) { + inner.discovered.push(peer_id.clone()); + } + alloc_slots(inner, &self.parent.tx); + } + + /// Adds a discovered peer id to the PSM. + /// + /// > **Note**: There is no equivalent "expired" message, meaning that it is the responsibility + /// > of the PSM to remove `PeerId`s that fail to dial too often. + pub fn discovered(&self, peer_id: PeerId) { + let mut inner = self.parent.inner.lock(); + + if inner.out_slots.iter().chain(inner.in_slots.iter()).any(|p| p.as_ref() == Some(&peer_id)) { + return; + } + + if inner.discovered.iter().all(|p| *p != peer_id) { + inner.discovered.push(peer_id); + } + alloc_slots(&mut inner, &self.parent.tx); + } + + /// Produces a JSON object containing the state of the peerset manager, for debugging purposes. + pub fn debug_info(&self) -> serde_json::Value { + serde_json::Value::Null + } +} + +impl Stream for PeersetMut { + type Item = Message; + type Error = (); + + fn poll(&mut self) -> Poll, Self::Error> { + self.rx.poll() + } +} diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index ad42502ddc936fc872cc417fca7cd9cbf2d3a0a2..fb4893613858bb8f9ec62952fe75259214e4fdd8 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -6,25 +6,29 @@ edition = "2018" [dependencies] rstd = { package = "sr-std", path = "../sr-std", default-features = false } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } rustc-hex = { version = "2.0", default-features = false } -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } twox-hash = { version = "1.1.0", optional = true } byteorder = { version = "1.1", default-features = false } primitive-types = { version = "0.2", default-features = false, features = ["codec"] } impl-serde = { version = "0.1", optional = true } wasmi = { version = "0.4.3", optional = true } -hash-db = { version = "0.11", default-features = false } -hash256-std-hasher = { version = "0.11", default-features = false } +hash-db = { version = "0.12", default-features = false } +hash256-std-hasher = { version = "0.12", default-features = false } ring = { version = "0.14", optional = true } untrusted = { version = "0.6", optional = true } hex-literal = { version = "0.1", optional = true } base58 = { version = "0.1", optional = true } blake2-rfc = { version = "0.2.18", optional = true } -schnorrkel = { version = "0.0", optional = true } +schnorrkel = { version = "0.1", optional = true } rand = { version = "0.6", optional = true } sha2 = { version = "0.8", optional = true } +substrate-bip39 = { git = "https://github.com/paritytech/substrate-bip39", optional = true } +tiny-bip39 = { version = "0.6.0", optional = true } +hex = { version = "0.3", optional = true } +regex = {version = "1.1", optional = true } [dev-dependencies] substrate-serializer = { path = "../serializer" } @@ -46,17 +50,21 @@ std = [ "hash256-std-hasher/std", "hash-db/std", "rstd/std", - "serde/std", + "serde", "rustc-hex/std", "twox-hash", "blake2-rfc", "ring", "untrusted", "hex-literal", + "hex", "base58", + "substrate-bip39", + "tiny-bip39", "serde_derive", "byteorder/std", "rand", "sha2", "schnorrkel", + "regex", ] diff --git a/core/primitives/src/authority_id.rs b/core/primitives/src/authority_id.rs deleted file mode 100644 index 5f2c84fd06870c190f8a7c683f948956784f20da..0000000000000000000000000000000000000000 --- a/core/primitives/src/authority_id.rs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#[cfg(feature = "std")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; -use parity_codec::{Encode, Decode}; -use crate::H256; - -/// An identifier for an authority in the consensus algorithm. The same size as ed25519::Public. -#[derive(Clone, Copy, PartialEq, Eq, Default, Encode, Decode)] -pub struct Ed25519AuthorityId(pub [u8; 32]); - -#[cfg(feature = "std")] -impl ::std::fmt::Display for Ed25519AuthorityId { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", crate::ed25519::Public(self.0).to_ss58check()) - } -} - -#[cfg(feature = "std")] -impl ::std::fmt::Debug for Ed25519AuthorityId { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - let h = format!("{}", crate::hexdisplay::HexDisplay::from(&self.0)); - write!(f, "{} ({}…{})", crate::ed25519::Public(self.0).to_ss58check(), &h[0..8], &h[60..]) - } -} - -#[cfg(feature = "std")] -impl ::std::hash::Hash for Ed25519AuthorityId { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl AsRef<[u8; 32]> for Ed25519AuthorityId { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Ed25519AuthorityId { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl Into<[u8; 32]> for Ed25519AuthorityId { - fn into(self) -> [u8; 32] { - self.0 - } -} - -impl From<[u8; 32]> for Ed25519AuthorityId { - fn from(a: [u8; 32]) -> Self { - Ed25519AuthorityId(a) - } -} - -impl AsRef for Ed25519AuthorityId { - fn as_ref(&self) -> &Ed25519AuthorityId { - &self - } -} - -impl Into for Ed25519AuthorityId { - fn into(self) -> H256 { - self.0.into() - } -} - -#[cfg(feature = "std")] -impl Serialize for Ed25519AuthorityId { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - crate::ed25519::serialize(&self, serializer) - } -} - -#[cfg(feature = "std")] -impl<'de> Deserialize<'de> for Ed25519AuthorityId { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - crate::ed25519::deserialize(deserializer) - } -} diff --git a/core/primitives/src/changes_trie.rs b/core/primitives/src/changes_trie.rs index f06bf49a8edbf2e1afb27a302b583067017e6ae1..c8776a6f0873f210f2fac9c246aada2661960fbb 100644 --- a/core/primitives/src/changes_trie.rs +++ b/core/primitives/src/changes_trie.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/crypto.rs b/core/primitives/src/crypto.rs new file mode 100644 index 0000000000000000000000000000000000000000..e0ecd4ce42ec9b2ba5a908c15db833f4c8d3c5a1 --- /dev/null +++ b/core/primitives/src/crypto.rs @@ -0,0 +1,509 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Cryptographic utilities. +// end::description[] + +#[cfg(feature = "std")] +use parity_codec::{Encode, Decode}; +#[cfg(feature = "std")] +use regex::Regex; +#[cfg(feature = "std")] +use base58::{FromBase58, ToBase58}; + +/// The root phrase for our publicly known keys. +pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; + +/// The address of the associated root phrase for our publicly known keys. +pub const DEV_ADDRESS: &str = "5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV"; + +/// The infallible type. +#[derive(Debug)] +pub enum Infallible {} + +/// The length of the junction identifier. Note that this is also referred to as the +/// `CHAIN_CODE_LENGTH` in the context of Schnorrkel. +#[cfg(feature = "std")] +pub const JUNCTION_ID_LEN: usize = 32; + +/// Similar to `From`, except that the onus is on the part of the caller to ensure +/// that data passed in makes sense. Basically, you're not guaranteed to get anything +/// sensible out. +pub trait UncheckedFrom { + /// Convert from an instance of `T` to Self. This is not guaranteed to be + /// whatever counts as a valid instance of `T` and it's up to the caller to + /// ensure that it makes sense. + fn unchecked_from(t: T) -> Self; +} + +/// The counterpart to `UncheckedFrom`. +pub trait UncheckedInto { + /// The counterpart to `unchecked_from`. + fn unchecked_into(self) -> T; +} + +impl> UncheckedInto for S { + fn unchecked_into(self) -> T { + T::unchecked_from(self) + } +} + +/// An error with the interpretation of a secret. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg(feature = "std")] +pub enum SecretStringError { + /// The overall format was invalid (e.g. the seed phrase contained symbols). + InvalidFormat, + /// The seed phrase provided is not a valid BIP39 phrase. + InvalidPhrase, + /// The supplied password was invalid. + InvalidPassword, + /// The seed is invalid (bad content). + InvalidSeed, + /// The seed has an invalid length. + InvalidSeedLength, + /// The derivation path was invalid (e.g. contains soft junctions when they are not supported). + InvalidPath, +} + +/// A since derivation junction description. It is the single parameter used when creating +/// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex` +/// a new public key from an existing public key. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)] +#[cfg(feature = "std")] +pub enum DeriveJunction { + /// Soft (vanilla) derivation. Public keys have a correspondent derivation. + Soft([u8; JUNCTION_ID_LEN]), + /// Hard ("hardened") derivation. Public keys do not have a correspondent derivation. + Hard([u8; JUNCTION_ID_LEN]), +} + +#[cfg(feature = "std")] +impl DeriveJunction { + /// Consume self to return a soft derive junction with the same chain code. + pub fn soften(self) -> Self { DeriveJunction::Soft(self.unwrap_inner()) } + + /// Consume self to return a hard derive junction with the same chain code. + pub fn harden(self) -> Self { DeriveJunction::Hard(self.unwrap_inner()) } + + /// Create a new soft (vanilla) DeriveJunction from a given, encodable, value. + /// + /// If you need a hard junction, use `hard()`. + pub fn soft(index: T) -> Self { + let mut cc: [u8; JUNCTION_ID_LEN] = Default::default(); + index.using_encoded(|data| if data.len() > JUNCTION_ID_LEN { + let hash_result = blake2_rfc::blake2b::blake2b(JUNCTION_ID_LEN, &[], data); + let hash = hash_result.as_bytes(); + cc.copy_from_slice(hash); + } else { + cc[0..data.len()].copy_from_slice(data); + }); + DeriveJunction::Soft(cc) + } + + /// Create a new hard (hardened) DeriveJunction from a given, encodable, value. + /// + /// If you need a soft junction, use `soft()`. + pub fn hard(index: T) -> Self { + Self::soft(index).harden() + } + + /// Consume self to return the chain code. + pub fn unwrap_inner(self) -> [u8; JUNCTION_ID_LEN] { + match self { + DeriveJunction::Hard(c) | DeriveJunction::Soft(c) => c, + } + } + + /// Get a reference to the inner junction id. + pub fn inner(&self) -> &[u8; JUNCTION_ID_LEN] { + match self { + DeriveJunction::Hard(ref c) | DeriveJunction::Soft(ref c) => c, + } + } + + /// Return `true` if the junction is soft. + pub fn is_soft(&self) -> bool { + match *self { + DeriveJunction::Soft(_) => true, + _ => false, + } + } + + /// Return `true` if the junction is hard. + pub fn is_hard(&self) -> bool { + match *self { + DeriveJunction::Hard(_) => true, + _ => false, + } + } +} + +#[cfg(feature = "std")] +impl> From for DeriveJunction { + fn from(j: T) -> DeriveJunction { + let j = j.as_ref(); + let (code, hard) = if j.starts_with("/") { + (&j[1..], true) + } else { + (j, false) + }; + + let res = if let Ok(n) = str::parse::(code) { + // number + DeriveJunction::soft(n) + } else { + // something else + DeriveJunction::soft(code) + }; + + if hard { + res.harden() + } else { + res + } + } +} + +/// An error type for SS58 decoding. +#[cfg(feature = "std")] +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub enum PublicError { + /// Bad alphabet. + BadBase58, + /// Bad length. + BadLength, + /// Unknown version. + UnknownVersion, + /// Invalid checksum. + InvalidChecksum, + /// Invalid format. + InvalidFormat, + /// Invalid derivation path. + InvalidPath, +} + +/// Key that can be encoded to/from SS58. +#[cfg(feature = "std")] +pub trait Ss58Codec: Sized { + /// Some if the string is a properly encoded SS58Check address. + fn from_ss58check(s: &str) -> Result; + /// Some if the string is a properly encoded SS58Check address, optionally with + /// a derivation path following. + fn from_string(s: &str) -> Result { Self::from_ss58check(s) } + /// Return the ss58-check string for this key. + fn to_ss58check(&self) -> String; +} + +#[cfg(feature = "std")] +/// Derivable key trait. +pub trait Derive: Sized { + /// Derive a child key from a series of given junctions. + /// + /// Will be `None` for public keys if there are any hard junctions in there. + fn derive>(&self, _path: Iter) -> Option { None } +} + +#[cfg(feature = "std")] +const PREFIX: &[u8] = b"SS58PRE"; + +#[cfg(feature = "std")] +fn ss58hash(data: &[u8]) -> blake2_rfc::blake2b::Blake2bResult { + let mut context = blake2_rfc::blake2b::Blake2b::new(64); + context.update(PREFIX); + context.update(data); + context.finalize() +} + +#[cfg(feature = "std")] +impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { + fn from_ss58check(s: &str) -> Result { + let mut res = T::default(); + let len = res.as_mut().len(); + let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. + if d.len() != len + 3 { + // Invalid length. + return Err(PublicError::BadLength); + } + if d[0] != 42 { + // Invalid version. + return Err(PublicError::UnknownVersion); + } + + if d[len+1..len+3] != ss58hash(&d[0..len+1]).as_bytes()[0..2] { + // Invalid checksum. + return Err(PublicError::InvalidChecksum); + } + res.as_mut().copy_from_slice(&d[1..len+1]); + Ok(res) + } + + fn to_ss58check(&self) -> String { + let mut v = vec![42u8]; + v.extend(self.as_ref()); + let r = ss58hash(&v); + v.extend(&r.as_bytes()[0..2]); + v.to_base58() + } + + fn from_string(s: &str) -> Result { + let re = Regex::new(r"^(?P[\w\d]+)?(?P(//?[^/]+)*)$") + .expect("constructed from known-good static value; qed"); + let cap = re.captures(s).ok_or(PublicError::InvalidFormat)?; + let re_junction = Regex::new(r"/(/?[^/]+)") + .expect("constructed from known-good static value; qed"); + let path = re_junction.captures_iter(&cap["path"]) + .map(|f| DeriveJunction::from(&f[1])); + Self::from_ss58check(cap.name("ss58").map(|r| r.as_str()).unwrap_or(DEV_ADDRESS))? + .derive(path) + .ok_or(PublicError::InvalidPath) + } +} + +/// Trait suitable for typical cryptographic PKI key pair type. +/// +/// For now it just specifies how to create a key from a phrase and derivation path. +#[cfg(feature = "std")] +pub trait Pair: Sized { + /// TThe type which is used to encode a public key. + type Public; + + /// The type used to (minimally) encode the data required to securely create + /// a new key pair. + type Seed; + + /// The type used to represent a signature. Can be created from a key pair and a message + /// and verified with the message and a public key. + type Signature; + + /// Error returned from the `derive` function. + type DeriveError; + + /// Generate new secure (random) key pair. + /// + /// This is only for ephemeral keys really, since you won't have access to the secret key + /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. + fn generate() -> Self; + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + /// + /// This is generally slower than `generate()`, so prefer that unless you need to persist + /// the key from the current session. + fn generate_with_phrase(password: Option<&str>) -> (Self, String); + + /// Returns the KeyPair from the English BIP39 seed `phrase`, or `None` if it's invalid. + fn from_phrase(phrase: &str, password: Option<&str>) -> Result; + + /// Derive a child key from a series of given junctions. + fn derive>(&self, path: Iter) -> Result; + + /// Generate new key pair from the provided `seed`. + /// + /// @WARNING: THIS WILL ONLY BE SECURE IF THE `seed` IS SECURE. If it can be guessed + /// by an attacker then they can also derive your key. + fn from_seed(seed: Self::Seed) -> Self; + + /// Make a new key pair from secret seed material. The slice must be the correct size or + /// it will return `None`. + /// + /// @WARNING: THIS WILL ONLY BE SECURE IF THE `seed` IS SECURE. If it can be guessed + /// by an attacker then they can also derive your key. + fn from_seed_slice(seed: &[u8]) -> Result; + + /// Construct a key from a phrase, password and path. + fn from_standard_components< + I: Iterator + >(phrase: &str, password: Option<&str>, path: I) -> Result; + + /// Sign a message. + fn sign(&self, message: &[u8]) -> Self::Signature; + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool; + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool; + + /// Get the public key. + fn public(&self) -> Self::Public; + + /// Interprets the string `s` in order to generate a key Pair. + /// + /// This takes a helper function to do the key generation from a phrase, password and + /// junction iterator. + /// + /// - If `s` is a possibly `0x` prefixed 64-digit hex string, then it will be interpreted + /// directly as a `MiniSecretKey` (aka "seed" in `subkey`). + /// - If `s` is a valid BIP-39 key phrase of 12, 15, 18, 21 or 24 words, then the key will + /// be derived from it. In this case: + /// - the phrase may be followed by one or more items delimited by `/` characters. + /// - the path may be followed by `///`, in which case everything after the `///` is treated + /// as a password. + /// - If `s` begins with a `/` character it is prefixed with the Substrate public `DEV_PHRASE` and + /// interpreted as above. + /// + /// In this case they are interpreted as HDKD junctions; purely numeric items are interpreted as + /// integers, non-numeric items as strings. Junctions prefixed with `/` are interpreted as soft + /// junctions, and with `//` as hard junctions. + /// + /// There is no correspondence mapping between SURI strings and the keys they represent. + /// Two different non-identical strings can actually lead to the same secret being derived. + /// Notably, integer junction indices may be legally prefixed with arbitrary number of zeros. + /// Similarly an empty password (ending the SURI with `///`) is perfectly valid and will generally + /// be equivalent to no password at all. + /// + /// `None` is returned if no matches are found. + fn from_string(s: &str, password_override: Option<&str>) -> Result { + let hex_seed = if s.starts_with("0x") { + &s[2..] + } else { + s + }; + + if let Ok(d) = hex::decode(hex_seed) { + if let Ok(r) = Self::from_seed_slice(&d) { + return Ok(r) + } + } + + let re = Regex::new(r"^(?P\w+( \w+)*)?(?P(//?[^/]+)*)(///(?P.*))?$") + .expect("constructed from known-good static value; qed"); + let cap = re.captures(s).ok_or(SecretStringError::InvalidFormat)?; + let re_junction = Regex::new(r"/(/?[^/]+)") + .expect("constructed from known-good static value; qed"); + let path = re_junction.captures_iter(&cap["path"]) + .map(|f| DeriveJunction::from(&f[1])); + Self::from_standard_components( + cap.name("phrase").map(|r| r.as_str()).unwrap_or(DEV_PHRASE), + password_override.or_else(|| cap.name("password").map(|m| m.as_str())), + path, + ) + } +} + +#[cfg(test)] +mod tests { + use crate::DeriveJunction; + use hex_literal::{hex, hex_impl}; + use super::*; + + #[derive(Eq, PartialEq, Debug)] + enum TestPair { + Generated, + GeneratedWithPhrase, + GeneratedFromPhrase{phrase: String, password: Option}, + Standard{phrase: String, password: Option, path: Vec}, + Seed(Vec), + } + + impl Pair for TestPair { + type Public = (); + type Seed = (); + type Signature = (); + type DeriveError = (); + + fn generate() -> Self { TestPair::Generated } + fn generate_with_phrase(_password: Option<&str>) -> (Self, String) { (TestPair::GeneratedWithPhrase, "".into()) } + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { + Ok(TestPair::GeneratedFromPhrase{ phrase: phrase.to_owned(), password: password.map(Into::into) }) + } + fn derive>(&self, _path: Iter) -> Result { + Err(()) + } + fn from_seed(_seed: ::Seed) -> Self { TestPair::Seed(vec![]) } + fn sign(&self, _message: &[u8]) -> Self::Signature { () } + fn verify, M: AsRef<[u8]>>(_sig: &Self::Signature, _message: M, _pubkey: P) -> bool { true } + fn verify_weak, M: AsRef<[u8]>>(_sig: &[u8], _message: M, _pubkey: P) -> bool { true } + fn public(&self) -> Self::Public { () } + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Ok(TestPair::Standard { phrase: phrase.to_owned(), password: password.map(ToOwned::to_owned), path: path.collect() }) + } + fn from_seed_slice(seed: &[u8]) -> Result { + Ok(TestPair::Seed(seed.to_owned())) + } + } + + #[test] + fn interpret_std_seed_should_work() { + assert_eq!( + TestPair::from_string("0x0123456789abcdef", None), + Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned())) + ); + assert_eq!( + TestPair::from_string("0123456789abcdef", None), + Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned())) + ); + } + + #[test] + fn password_override_should_work() { + assert_eq!( + TestPair::from_string("hello world///password", None), + TestPair::from_string("hello world", Some("password")), + ); + assert_eq!( + TestPair::from_string("hello world///password", None), + TestPair::from_string("hello world///other password", Some("password")), + ); + } + + #[test] + fn interpret_std_secret_string_should_work() { + assert_eq!( + TestPair::from_string("hello world", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![]}) + ); + assert_eq!( + TestPair::from_string("hello world/1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::soft(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world/DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world//DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//1/DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard(1), DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//DOT/1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard("DOT"), DeriveJunction::soft(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![]}) + ); + assert_eq!( + TestPair::from_string("hello world//1/DOT///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::hard(1), DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world/1//DOT///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::soft(1), DeriveJunction::hard("DOT")]}) + ); + } +} diff --git a/core/primitives/src/ed25519.rs b/core/primitives/src/ed25519.rs index dcf95b21e6501d86a95065cff971def0708c5e1d..937cc19a899c707635a7889cd8da61bc72a282bb 100644 --- a/core/primitives/src/ed25519.rs +++ b/core/primitives/src/ed25519.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,58 +18,251 @@ //! Simple Ed25519 API. // end::description[] + +use crate::{hash::H256, hash::H512}; +use parity_codec::{Encode, Decode}; + +#[cfg(feature = "std")] use untrusted; +#[cfg(feature = "std")] use blake2_rfc; -use ring::{rand, signature, signature::KeyPair}; -use crate::{hash::H512, Ed25519AuthorityId}; +#[cfg(feature = "std")] +use ring::{signature, signature::KeyPair, rand::{SecureRandom, SystemRandom}}; +#[cfg(feature = "std")] use base58::{ToBase58, FromBase58}; -use parity_codec::{Encode, Decode}; +#[cfg(feature = "std")] +use substrate_bip39::seed_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "std")] +use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError, Derive}; +#[cfg(feature = "std")] +use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; +use crate::crypto::UncheckedFrom; +/// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys +/// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we +/// will need it later (such as for HDKD). #[cfg(feature = "std")] -use serde::{de, Serializer, Deserializer, Deserialize}; +type Seed = [u8; 32]; -/// Alias to 512-bit hash when used in the context of a signature on the relay chain. -pub type Signature = H512; +/// A public key. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +pub struct Public(pub [u8; 32]); -/// Length of the PKCS#8 encoding of the key. -pub const PKCS_LEN: usize = 85; +/// A key pair. +#[cfg(feature = "std")] +pub struct Pair(signature::Ed25519KeyPair, Seed); -/// A localized signature also contains sender information. -#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] -pub struct LocalizedSignature { - /// The signer of the signature. - pub signer: Public, - /// The signature itself. - pub signature: Signature, +#[cfg(feature = "std")] +impl Clone for Pair { + fn clone(&self) -> Self { + Pair::from_seed(self.1.clone()) + } } -/// Verify a message without type checking the parameters' types for the right size. -/// Returns true if the signature is good. -pub fn verify>(sig: &[u8], message: &[u8], public: P) -> bool { - let public_key = untrusted::Input::from(public.as_ref()); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(sig); +impl AsRef<[u8; 32]> for Public { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + &self.0[..] } } -/// A public key. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -pub struct Public(pub [u8; 32]); +impl AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} -/// A key pair. -pub struct Pair(signature::Ed25519KeyPair); +impl From for [u8; 32] { + fn from(x: Public) -> Self { + x.0 + } +} + +#[cfg(feature = "std")] +impl From for Public { + fn from(x: Pair) -> Self { + x.public() + } +} + +impl AsRef for Public { + fn as_ref(&self) -> &Public { + &self + } +} + +impl From for H256 { + fn from(x: Public) -> Self { + x.0.into() + } +} +impl UncheckedFrom<[u8; 32]> for Public { + fn unchecked_from(x: [u8; 32]) -> Self { + Public::from_raw(x) + } +} + +impl UncheckedFrom for Public { + fn unchecked_from(x: H256) -> Self { + Public::from_h256(x) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Display for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } +} + +#[cfg(feature = "std")] +impl Serialize for Public { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +#[cfg(feature = "std")] impl ::std::hash::Hash for Public { fn hash(&self, state: &mut H) { self.0.hash(state); } } +/// A signature (a 512-bit value). +#[derive(Encode, Decode)] +pub struct Signature(pub [u8; 64]); + +impl Clone for Signature { + fn clone(&self) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&self.0[..]); + Signature(r) + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0u8; 64]) + } +} + +impl PartialEq for Signature { + fn eq(&self, b: &Self) -> bool { + &self.0[..] == &b.0[..] + } +} + +impl Eq for Signature {} + +impl From for H512 { + fn from(v: Signature) -> H512 { + H512::from(v.0) + } +} + +impl From for [u8; 64] { + fn from(v: Signature) -> [u8; 64] { + v.0 + } +} + +impl AsRef<[u8; 64]> for Signature { + fn as_ref(&self) -> &[u8; 64] { + &self.0 + } +} + +impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Signature { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + ::std::hash::Hash::hash(&self.0[..], state); + } +} + +impl Signature { + /// A new instance from the given 64-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_raw(data: [u8; 64]) -> Signature { + Signature(data) + } + + /// A new instance from the given slice that should be 64 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Signature(r) + } + + /// A new instance from an H512. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_h512(v: H512) -> Signature { + Signature(v.into()) + } +} + +/// A localized signature also contains sender information. +#[cfg(feature = "std")] +#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] +pub struct LocalizedSignature { + /// The signer of the signature. + pub signer: Public, + /// The signature itself. + pub signature: Signature, +} + /// An error type for SS58 decoding. +#[cfg(feature = "std")] #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum PublicError { /// Bad alphabet. @@ -84,36 +277,33 @@ pub enum PublicError { impl Public { /// A new instance from the given 32-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! pub fn from_raw(data: [u8; 32]) -> Self { Public(data) } /// A new instance from the given slice that should be 32 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! pub fn from_slice(data: &[u8]) -> Self { let mut r = [0u8; 32]; r.copy_from_slice(data); Public(r) } - /// Some if the string is a properly encoded SS58Check address. - pub fn from_ss58check(s: &str) -> Result { - let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. - if d.len() != 35 { - // Invalid length. - return Err(PublicError::BadLength); - } - if d[0] != 42 { - // Invalid version. - return Err(PublicError::UnknownVersion); - } - if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] { - // Invalid checksum. - return Err(PublicError::InvalidChecksum); - } - Ok(Self::from_slice(&d[1..33])) + /// A new instance from an H256. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + pub fn from_h256(x: H256) -> Self { + Public(x.into()) } /// Return a `Vec` filled with raw data. + #[cfg(feature = "std")] pub fn to_raw_vec(self) -> Vec { let r: &[u8; 32] = self.as_ref(); r.to_vec() @@ -129,6 +319,30 @@ impl Public { pub fn as_array_ref(&self) -> &[u8; 32] { self.as_ref() } +} + +#[cfg(feature = "std")] +impl Derive for Public {} + +#[cfg(feature = "std")] +impl Public { + /// Some if the string is a properly encoded SS58Check address. + pub fn from_ss58check(s: &str) -> Result { + let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. + if d.len() != 35 { + // Invalid length. + return Err(PublicError::BadLength); + } + if d[0] != 42 { + // Invalid version. + return Err(PublicError::UnknownVersion); + } + if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] { + // Invalid checksum. + return Err(PublicError::InvalidChecksum); + } + Ok(Self::from_slice(&d[1..33])) + } /// Return the ss58-check string for this key. pub fn to_ss58check(&self) -> String { @@ -140,178 +354,205 @@ impl Public { } } -impl AsRef<[u8; 32]> for Public { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl Into<[u8; 32]> for Public { - fn into(self) -> [u8; 32] { - self.0 - } -} - -impl AsRef for Public { - fn as_ref(&self) -> &Public { - &self - } -} - +#[cfg(feature = "std")] impl AsRef for Pair { fn as_ref(&self) -> &Pair { &self } } -impl Into for Public { - fn into(self) -> Ed25519AuthorityId { - Ed25519AuthorityId(self.0) - } -} - -impl From for Public { - fn from(id: Ed25519AuthorityId) -> Self { - Public(id.0) - } -} - -impl ::std::fmt::Display for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } +/// Derive a single hard junction. +#[cfg(feature = "std")] +fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + ("Ed25519HDKD", secret_seed, cc).using_encoded(|data| { + let mut res = [0u8; 32]; + res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); + res + }) } -impl ::std::fmt::Debug for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } +/// An error when deriving a key. +#[cfg(feature = "std")] +pub enum DeriveError { + /// A soft key was found in the path (and is unsupported). + SoftKeyInPath, } -impl Pair { - /// Generate new secure (random) key pair, yielding it and the corresponding pkcs#8 bytes. - pub fn generate_with_pkcs8() -> (Self, [u8; PKCS_LEN]) { - let rng = rand::SystemRandom::new(); - let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).expect("system randomness is available; qed"); - let pair = Self::from_pkcs8(&pkcs8_bytes.as_ref()).expect("just-generated pkcs#8 data is valid; qed"); - - let mut out = [0; PKCS_LEN]; - out.copy_from_slice(pkcs8_bytes.as_ref()); - (pair, out) - } +#[cfg(feature = "std")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = DeriveError; /// Generate new secure (random) key pair. - pub fn generate() -> Pair { - let (pair, _) = Self::generate_with_pkcs8(); - pair - } - - /// Generate from pkcs#8 bytes. - pub fn from_pkcs8(pkcs8_bytes: &[u8]) -> Result { - signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).map(Pair) - } - - /// Make a new key pair from a seed phrase. - /// NOTE: prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests. - pub fn from_seed(seed: &[u8; 32]) -> Pair { + /// + /// This is only for ephemeral keys really, since you won't have access to the secret key + /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. + fn generate() -> Pair { + let mut seed: Seed = Default::default(); + SystemRandom::new().fill(seed.as_mut()).expect("system random source should always work! qed"); + Self::from_seed(seed) + } + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + fn generate_with_phrase(password: Option<&str>) -> (Pair, String) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + ( + Self::from_phrase(phrase, password).expect("All phrases generated by Mnemonic are valid; qed"), + phrase.to_owned(), + ) + } + + /// Generate key pair from given recovery phrase and password. + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { + let big_seed = seed_from_entropy( + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(), + password.unwrap_or(""), + ).map_err(|_| SecretStringError::InvalidSeed)?; + Self::from_seed_slice(&big_seed[0..32]) + } + + /// Make a new key pair from secret seed material. + /// + /// You should never need to use this; generate(), generate_with_phrasee + fn from_seed(seed: Seed) -> Pair { let key = signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])) .expect("seed has valid length; qed"); + Pair(key, seed) + } + + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// You should never need to use this; generate(), generate_with_phrase + fn from_seed_slice(seed_slice: &[u8]) -> Result { + if seed_slice.len() != 32 { + Err(SecretStringError::InvalidSeedLength) + } else { + let mut seed = [0u8; 32]; + seed.copy_from_slice(&seed_slice); + Ok(Self::from_seed(seed)) + } + } - Pair(key) + /// Derive a child key from a series of given junctions. + fn derive>(&self, path: Iter) -> Result { + let mut acc = self.1.clone(); + for j in path { + match j { + DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), + DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), + } + } + Ok(Self::from_seed(acc)) } - /// Sign a message. - pub fn sign(&self, message: &[u8]) -> Signature { - let mut r = [0u8; 64]; - r.copy_from_slice(self.0.sign(message).as_ref()); - Signature::from(r) + /// Generate a key from the phrase, password and derivation path. + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Self::from_phrase(phrase, password)?.derive(path).map_err(|_| SecretStringError::InvalidPath) } /// Get the public key. - pub fn public(&self) -> Public { + fn public(&self) -> Public { let mut r = [0u8; 32]; let pk = self.0.public_key().as_ref(); r.copy_from_slice(pk); Public(r) } -} -/// Verify a signature on a message. Returns true if the signature is good. -pub fn verify_strong>(sig: &Signature, message: &[u8], pubkey: P) -> bool { - let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(&sig.as_bytes()); - - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, + /// Sign a message. + fn sign(&self, message: &[u8]) -> Signature { + let mut r = [0u8; 64]; + r.copy_from_slice(self.0.sign(message).as_ref()); + Signature::from_raw(r) } -} -/// Something that acts as a signature allowing a message to be verified. -pub trait Verifiable { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool; -} + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool { + let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]); + let msg = untrusted::Input::from(message.as_ref()); + let sig = untrusted::Input::from(&sig.0[..]); -impl Verifiable for Signature { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - verify_strong(&self, message, pubkey) + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } } -} -impl Verifiable for LocalizedSignature { - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - pubkey.as_ref() == &self.signer && self.signature.verify(message, pubkey) + /// Verify a signature on a message. Returns true if the signature is good. + /// + /// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct + /// size. Use it only if you're coming from byte buffers and need the speed. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { + let public_key = untrusted::Input::from(pubkey.as_ref()); + let msg = untrusted::Input::from(message.as_ref()); + let sig = untrusted::Input::from(sig); + + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } } } -/// Deserialize from `ss58` into something that can be constructed from `[u8; 32]`. #[cfg(feature = "std")] -pub fn deserialize<'de, D, T: From<[u8; 32]>>(deserializer: D) -> Result where - D: Deserializer<'de>, -{ - let ss58 = String::deserialize(deserializer)?; - Public::from_ss58check(&ss58) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - .map(|v| v.0.into()) -} +impl Pair { + /// Get the seed for this key. + pub fn seed(&self) -> &Seed { + &self.1 + } -/// Serializes something that implements `AsRef<[u8; 32]>` into `ss58`. -#[cfg(feature = "std")] -pub fn serialize>(data: &T, serializer: S) -> Result where - S: Serializer, -{ - serializer.serialize_str(&Public(*data.as_ref()).to_ss58check()) + /// Exactly as `from_string` except that if no matches are found then, the the first 32 + /// characters are taken (padded with spaces as necessary) and used as the MiniSecretKey. + pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair { + Self::from_string(s, password_override).unwrap_or_else(|_| { + let mut padded_seed: Seed = [' ' as u8; 32]; + let len = s.len().min(32); + padded_seed[..len].copy_from_slice(&s.as_bytes()[..len]); + Self::from_seed(padded_seed) + }) + } } #[cfg(test)] mod test { use super::*; use hex_literal::{hex, hex_impl}; + use crate::crypto::DEV_PHRASE; - fn _test_primitives_signature_and_local_the_same() { - fn takes_two(_: T, _: T) { } - takes_two(Signature::default(), crate::Signature::default()) + #[test] + fn default_phrase_should_be_used() { + assert_eq!( + Pair::from_string("//Alice///password", None).unwrap().public(), + Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), + ); } #[test] fn test_vector_should_work() { - let pair: Pair = Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")); + let pair: Pair = Pair::from_seed(hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")); + let public = pair.public(); + assert_eq!(public, Public::from_raw(hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"))); + let message = b""; + let signature = Signature::from_raw(hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b")); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn test_vector_by_string_should_work() { + let pair: Pair = Pair::from_string("0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", None).unwrap(); let public = pair.public(); assert_eq!(public, Public::from_raw(hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"))); let message = b""; - let signature: Signature = hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b").into(); + let signature = Signature::from_raw(hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b")); assert!(&pair.sign(&message[..]) == &signature); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] @@ -320,44 +561,51 @@ mod test { let public = pair.public(); let message = b"Something important"; let signature = pair.sign(&message[..]); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] fn seeded_pair_should_work() { - use crate::hexdisplay::HexDisplay; - - let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); let public = pair.public(); assert_eq!(public, Public::from_raw(hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee"))); let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); let signature = pair.sign(&message[..]); - println!("Correct signature: {}", HexDisplay::from(&signature.as_bytes())); - assert!(verify_strong(&signature, &message[..], &public)); + println!("Correct signature: {:?}", signature); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] - fn generate_with_pkcs8_recovery_possible() { - let (pair1, pkcs8) = Pair::generate_with_pkcs8(); - let pair2 = Pair::from_pkcs8(&pkcs8).unwrap(); + fn generate_with_phrase_recovery_possible() { + let (pair1, phrase) = Pair::generate_with_phrase(None); + let pair2 = Pair::from_phrase(&phrase, None).unwrap(); assert_eq!(pair1.public(), pair2.public()); } + #[test] + fn generate_with_password_phrase_recovery_possible() { + let (pair1, phrase) = Pair::generate_with_phrase(Some("password")); + let pair2 = Pair::from_phrase(&phrase, Some("password")).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); + } + + #[test] + fn password_does_something() { + let (pair1, phrase) = Pair::generate_with_phrase(Some("password")); + let pair2 = Pair::from_phrase(&phrase, None).unwrap(); + + assert_ne!(pair1.public(), pair2.public()); + } + #[test] fn ss58check_roundtrip_works() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); let public = pair.public(); let s = public.to_ss58check(); println!("Correct: {}", s); let cmp = Public::from_ss58check(&s).unwrap(); assert_eq!(cmp, public); } - - #[test] - fn ss58check_known_works() { - let k = "5CGavy93sZgPPjHyziRohwVumxiHXMGmQLyuqQP4ZFx5vRU9"; - let enc = hex!["090fa15cb5b1666222fff584b4cc2b1761fe1e238346b340491b37e25ea183ff"]; - assert_eq!(Public::from_ss58check(k).unwrap(), Public::from_raw(enc)); - } } diff --git a/core/primitives/src/hash.rs b/core/primitives/src/hash.rs index e4ebbe4b1e880e797136b7e16b336a4c5a313a49..f3e3583be5771b3d0569753393cf232ad9a68cf4 100644 --- a/core/primitives/src/hash.rs +++ b/core/primitives/src/hash.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/hasher.rs b/core/primitives/src/hasher.rs index 7c540039ec24cf7642867109add221d5d4d5673b..4562180a1a454c5ba0ebe5e1cb8faffde1744ee9 100644 --- a/core/primitives/src/hasher.rs +++ b/core/primitives/src/hasher.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/hashing.rs b/core/primitives/src/hashing.rs index 1a149529781633b3f6415e49ec8c46940ffa4daf..814048fea848da3bdc9732b6521ace0220708da1 100644 --- a/core/primitives/src/hashing.rs +++ b/core/primitives/src/hashing.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/hexdisplay.rs b/core/primitives/src/hexdisplay.rs index b202fdf2e3fa955dfff43c7e355a30cb1a007ca9..d748208d0e09ff911be9245a4588ece343191d59 100644 --- a/core/primitives/src/hexdisplay.rs +++ b/core/primitives/src/hexdisplay.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/lib.rs b/core/primitives/src/lib.rs index 3eff7059f41726d874c25551105ce8af55bf9e84..f078b5446f53b2275686722294460c446d4dbee9 100644 --- a/core/primitives/src/lib.rs +++ b/core/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] -/// Initalise a key-value collection from array. +/// Initialize a key-value collection from array. /// /// Creates a vector of given pairs and calls `collect` on the iterator from it. /// Can be used to create a `HashMap`. @@ -49,19 +49,17 @@ pub mod hashing; pub use hashing::{blake2_256, twox_128, twox_256}; #[cfg(feature = "std")] pub mod hexdisplay; -#[cfg(feature = "std")] -pub mod ed25519; -#[cfg(feature = "std")] -pub mod sr25519; +pub mod crypto; pub mod u32_trait; +pub mod ed25519; +pub mod sr25519; pub mod hash; mod hasher; pub mod sandbox; pub mod storage; pub mod uint; -mod authority_id; mod changes_trie; #[cfg(test)] @@ -69,18 +67,45 @@ mod tests; pub use self::hash::{H160, H256, H512, convert_hash}; pub use self::uint::U256; -pub use authority_id::Ed25519AuthorityId; pub use changes_trie::ChangesTrieConfiguration; +#[cfg(feature = "std")] +pub use crypto::{DeriveJunction, Pair}; pub use hash_db::Hasher; // Switch back to Blake after PoC-3 is out // pub use self::hasher::blake::BlakeHasher; pub use self::hasher::blake2::Blake2Hasher; -/// A 512-bit value interpreted as a signature. -pub type Signature = hash::H512; +/// Context for executing a call into the runtime. +#[repr(u8)] +pub enum ExecutionContext { + /// Context for general importing (including own blocks). + Importing, + /// Context used when syncing the blockchain. + Syncing, + /// Context used for block construction. + BlockConstruction, + /// Offchain worker context. + OffchainWorker(Box), + /// Context used for other calls. + Other, +} + +/// An extended externalities for offchain workers. +pub trait OffchainExt { + /// Submits an extrinsics. + /// + /// The extrinsic will either go to the pool (signed) + /// or to the next produced block (inherent). + fn submit_extrinsic(&mut self, extrinsic: Vec); +} +impl OffchainExt for Box { + fn submit_extrinsic(&mut self, ex: Vec) { + (&mut **self).submit_extrinsic(ex) + } +} -/// Hex-serialised shim for `Vec`. +/// Hex-serialized shim for `Vec`. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord))] pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); diff --git a/core/primitives/src/sandbox.rs b/core/primitives/src/sandbox.rs index 01bfd4143dc045eaa0c886e5e4b15592ff1e4ea4..773a6b489330986c2e60a91c182a6bdd2ab187a0 100644 --- a/core/primitives/src/sandbox.rs +++ b/core/primitives/src/sandbox.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -164,7 +164,7 @@ pub const MEM_UNLIMITED: u32 = -1i32 as u32; /// For FFI purposes. pub const ERR_OK: u32 = 0; -/// Validation or instantiation error occured when creating new +/// Validation or instantiation error occurred when creating new /// sandboxed module instance. /// /// For FFI purposes. diff --git a/core/primitives/src/sr25519.rs b/core/primitives/src/sr25519.rs index 729b8790f9d8bb0378c9191247489125cfaaa477..aa17447a24a29078b2ed2f9cb513cab891c4d04e 100644 --- a/core/primitives/src/sr25519.rs +++ b/core/primitives/src/sr25519.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,27 +16,210 @@ // tag::description[] //! Simple sr25519 (Schnorr-Ristretto) API. +//! +//! Note: `CHAIN_CODE_LENGTH` must be equal to `crate::crypto::JUNCTION_ID_LEN` +//! for this to work. // end::description[] -use base58::{FromBase58, ToBase58}; -use blake2_rfc; +#[cfg(feature = "std")] use rand::rngs::OsRng; -use schnorrkel::{signing_context, Keypair, MiniSecretKey, PublicKey}; -use sha2::Sha512; +#[cfg(feature = "std")] +use schnorrkel::{signing_context, Keypair, SecretKey, MiniSecretKey, PublicKey, + derive::{Derivation, ChainCode, CHAIN_CODE_LENGTH} +}; +#[cfg(feature = "std")] +use substrate_bip39::mini_secret_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "std")] +use crate::crypto::{Pair as TraitPair, DeriveJunction, Infallible, SecretStringError, Derive, Ss58Codec}; +use crate::{hash::{H256, H512}, crypto::UncheckedFrom}; use parity_codec::{Encode, Decode}; -use crate::hash::H512; #[cfg(feature = "std")] -use serde::{de, Deserialize, Deserializer, Serializer}; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "std")] +use schnorrkel::keys::MINI_SECRET_KEY_LENGTH; // signing context -const SIGNING_CTX: &'static [u8] = b"substrate transaction"; +#[cfg(feature = "std")] +const SIGNING_CTX: &[u8] = b"substrate"; + +/// An Schnorrkel/Ristretto x25519 ("sr25519") public key. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +pub struct Public(pub [u8; 32]); + +/// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. +#[cfg(feature = "std")] +pub struct Pair(Keypair); + +impl AsRef for Public { + fn as_ref(&self) -> &Public { + &self + } +} + +impl AsRef<[u8; 32]> for Public { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} + +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} +impl AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +impl From for [u8; 32] { + fn from(x: Public) -> [u8; 32] { + x.0 + } +} + +impl From for H256 { + fn from(x: Public) -> H256 { + x.0.into() + } +} + +impl UncheckedFrom<[u8; 32]> for Public { + fn unchecked_from(x: [u8; 32]) -> Self { + Public::from_raw(x) + } +} + +impl UncheckedFrom for Public { + fn unchecked_from(x: H256) -> Self { + Public::from_h256(x) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Display for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } +} + +#[cfg(feature = "std")] +impl Serialize for Public { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Public { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +/// An Schnorrkel/Ristretto x25519 ("sr25519") signature. +/// /// Instead of importing it for the local module, alias it to be available as a public type -pub type Signature = H512; +#[derive(Encode, Decode)] +pub struct Signature(pub [u8; 64]); + +impl Clone for Signature { + fn clone(&self) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&self.0[..]); + Signature(r) + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0u8; 64]) + } +} + +impl PartialEq for Signature { + fn eq(&self, b: &Self) -> bool { + &self.0[..] == &b.0[..] + } +} + +impl Eq for Signature {} + +impl From for [u8; 64] { + fn from(v: Signature) -> [u8; 64] { + v.0 + } +} + +impl From for H512 { + fn from(v: Signature) -> H512 { + H512::from(v.0) + } +} + +impl AsRef<[u8; 64]> for Signature { + fn as_ref(&self) -> &[u8; 64] { + &self.0 + } +} + +impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +#[cfg(feature = "std")] +impl From for Signature { + fn from(s: schnorrkel::Signature) -> Signature { + Signature(s.to_bytes()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Signature { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + ::std::hash::Hash::hash(&self.0[..], state); + } +} /// A localized signature also contains sender information. /// NOTE: Encode and Decode traits are supported in ed25519 but not possible for now here. +#[cfg(feature = "std")] #[derive(PartialEq, Eq, Clone, Debug)] pub struct LocalizedSignature { /// The signer of the signature. @@ -45,64 +228,80 @@ pub struct LocalizedSignature { pub signature: Signature, } -/// A public key. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -pub struct Public(pub [u8; 32]); +impl Signature { + /// A new instance from the given 64-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_raw(data: [u8; 64]) -> Signature { + Signature(data) + } -/// A schnorrkel key pair. -pub struct Pair(Keypair); + /// A new instance from the given slice that should be 64 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Signature(r) + } -impl ::std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.0.hash(state); + /// A new instance from an H512. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_h512(v: H512) -> Signature { + Signature(v.into()) } } -/// An error type for SS58 decoding. -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum PublicError { - /// Bad alphabet. - BadBase58, - /// Bad length. - BadLength, - /// Unknown version. - UnknownVersion, - /// Invalid checksum. - InvalidChecksum, +#[cfg(feature = "std")] +impl Derive for Public { + /// Derive a child key from a series of given junctions. + /// + /// `None` if there are any hard junctions in there. + fn derive>(&self, path: Iter) -> Option { + let mut acc = PublicKey::from_bytes(self.as_ref()).ok()?; + for j in path { + match j { + DeriveJunction::Soft(cc) => acc = acc.derived_key_simple(ChainCode(cc), &[]).0, + DeriveJunction::Hard(_cc) => return None, + } + } + Some(Self(acc.to_bytes())) + } } impl Public { /// A new instance from the given 32-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! pub fn from_raw(data: [u8; 32]) -> Self { Public(data) } /// A new instance from the given slice that should be 32 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! pub fn from_slice(data: &[u8]) -> Self { let mut r = [0u8; 32]; r.copy_from_slice(data); Public(r) } - /// Some if the string is a properly encoded SS58Check address. - pub fn from_ss58check(s: &str) -> Result { - let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. - if d.len() != 35 { - // Invalid length. - return Err(PublicError::BadLength); - } - if d[0] != 42 { - // Invalid version. - return Err(PublicError::UnknownVersion); - } - if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] { - // Invalid checksum. - return Err(PublicError::InvalidChecksum); - } - Ok(Self::from_slice(&d[1..33])) + /// A new instance from an H256. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + pub fn from_h256(x: H256) -> Self { + Public(x.into()) } /// Return a `Vec` filled with raw data. + #[cfg(feature = "std")] pub fn to_raw_vec(self) -> Vec { let r: &[u8; 32] = self.as_ref(); r.to_vec() @@ -118,165 +317,272 @@ impl Public { pub fn as_array_ref(&self) -> &[u8; 32] { self.as_ref() } - - /// Return the ss58-check string for this key. - pub fn to_ss58check(&self) -> String { - let mut v = vec![42u8]; - v.extend(self.as_slice()); - let r = blake2_rfc::blake2b::blake2b(64, &[], &v); - v.extend(&r.as_bytes()[0..2]); - v.to_base58() - } } -impl AsRef<[u8; 32]> for Public { - fn as_ref(&self) -> &[u8; 32] { - &self.0 +#[cfg(feature = "std")] +impl AsRef for Pair { + fn as_ref(&self) -> &Pair { + &self } } -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] +#[cfg(feature = "std")] +impl From for Pair { + fn from(sec: MiniSecretKey) -> Pair { + Pair(sec.expand_to_keypair()) } } -impl Into<[u8; 32]> for Public { - fn into(self) -> [u8; 32] { - self.0 +#[cfg(feature = "std")] +impl From for Pair { + fn from(sec: SecretKey) -> Pair { + Pair(Keypair::from(sec)) } } -impl AsRef for Public { - fn as_ref(&self) -> &Public { - &self +#[cfg(feature = "std")] +impl From for Pair { + fn from(p: schnorrkel::Keypair) -> Pair { + Pair(p) } } -impl AsRef for Pair { - fn as_ref(&self) -> &Pair { - &self +#[cfg(feature = "std")] +impl From for schnorrkel::Keypair { + fn from(p: Pair) -> schnorrkel::Keypair { + p.0 } } -impl ::std::fmt::Display for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", self.to_ss58check()) +#[cfg(feature = "std")] +impl AsRef for Pair { + fn as_ref(&self) -> &schnorrkel::Keypair { + &self.0 } } -impl ::std::fmt::Debug for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } +/// Derive a single hard junction. +#[cfg(feature = "std")] +fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> SecretKey { + secret.hard_derive_mini_secret_key(Some(ChainCode(cc.clone())), b"").0.expand() } -impl Pair { +#[cfg(feature = "std")] +type Seed = [u8; MINI_SECRET_KEY_LENGTH]; + +#[cfg(feature = "std")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = Infallible; + /// Generate new secure (random) key pair. - pub fn generate() -> Pair { + fn generate() -> Pair { let mut csprng: OsRng = OsRng::new().expect("os random generator works; qed"); - let keypair: Keypair = Keypair::generate(&mut csprng); - Pair(keypair) + let key_pair: Keypair = Keypair::generate(&mut csprng); + Pair(key_pair) } - /// Make a new key pair from a seed phrase. + /// Make a new key pair from raw secret seed material. + /// /// This is generated using schnorrkel's Mini-Secret-Keys. + /// /// A MiniSecretKey is literally what Ed25519 calls a SecretKey, which is just 32 random bytes. - pub fn from_seed(seed: &[u8; 32]) -> Pair { - let mini_key: MiniSecretKey = MiniSecretKey::from_bytes(seed) + fn from_seed(seed: Seed) -> Pair { + let mini_key: MiniSecretKey = MiniSecretKey::from_bytes(&seed[..]) .expect("32 bytes can always build a key; qed"); - let kp = mini_key.expand_to_keypair::(); + let kp = mini_key.expand_to_keypair(); Pair(kp) } - /// Sign a message. - pub fn sign(&self, message: &[u8]) -> Signature { - let context = signing_context(SIGNING_CTX); - Signature::from(self.0.sign(context.bytes(message)).to_bytes()) - } - /// Get the public key. - pub fn public(&self) -> Public { + fn public(&self) -> Public { let mut pk = [0u8; 32]; pk.copy_from_slice(&self.0.public.to_bytes()); Public(pk) } -} -/// Verify a signature on a message. Returns true if the signature is good. -pub fn verify_strong>(sig: &Signature, message: &[u8], pubkey: P) -> bool { - let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(&sig[..]) { - Ok(some_signature) => some_signature, - Err(_) => return false - }; - match PublicKey::from_bytes(pubkey.as_ref().as_slice()) { - Ok(pk) => pk.verify(signing_context(SIGNING_CTX).bytes(message), &signature), - Err(_) => false, + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// You should never need to use this; generate(), generate_with_phrase(), from_phrase() + fn from_seed_slice(seed: &[u8]) -> Result { + if seed.len() != MINI_SECRET_KEY_LENGTH { + Err(SecretStringError::InvalidSeedLength) + } else { + Ok(Pair( + MiniSecretKey::from_bytes(seed) + .map_err(|_| SecretStringError::InvalidSeed)? + .expand_to_keypair() + )) + } } -} -/// Verify a message without type checking the parameters' types for the right size. -/// Returns true if both the pubkey and the signature is good. -pub fn verify>(sig: &[u8], message: &[u8], pubkey: P) -> bool { - let signature = match schnorrkel::Signature::from_bytes(&sig[..]) { - Ok(sig) => sig, - Err(_) => return false, - }; - match PublicKey::from_bytes(pubkey.as_ref()) { - Ok(pk) => pk.verify_simple(SIGNING_CTX, message, &signature), - Err(_) => false, + /// Generate a key from the phrase, password and derivation path. + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Self::from_phrase(phrase, password)? + .derive(path) + .map_err(|_| SecretStringError::InvalidPath) } -} -/// Something that acts as a signature allowing a message to be verified. -pub trait Verifiable { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool; -} + fn generate_with_phrase(password: Option<&str>) -> (Pair, String) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + ( + Self::from_phrase(phrase, password).expect("All phrases generated by Mnemonic are valid; qed"), + phrase.to_owned(), + ) + } -impl Verifiable for Signature { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - verify_strong(&self, message, pubkey) + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase) + .map(|m| Self::from_entropy(m.entropy(), password)) } -} -impl Verifiable for LocalizedSignature { - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - pubkey.as_ref() == &self.signer && self.signature.verify(message, pubkey) + fn derive>(&self, path: Iter) -> Result { + let init = self.0.secret.clone(); + let result = path.fold(init, |acc, j| match j { + DeriveJunction::Soft(cc) => acc.derived_key_simple(ChainCode(cc), &[]).0, + DeriveJunction::Hard(cc) => derive_hard_junction(&acc, &cc), + }); + Ok(Self(result.into())) } -} -/// Deserialize from `ss58` into something that can be constructed from `[u8; 32]`. -#[cfg(feature = "std")] -pub fn deserialize<'de, D, T: From<[u8; 32]>>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let ss58 = String::deserialize(deserializer)?; - Public::from_ss58check(&ss58) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - .map(|v| v.0.into()) + fn sign(&self, message: &[u8]) -> Signature { + let context = signing_context(SIGNING_CTX); + self.0.sign(context.bytes(message)).into() + } + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool { + let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(&sig.as_ref()) { + Ok(some_signature) => some_signature, + Err(_) => return false + }; + match PublicKey::from_bytes(pubkey.as_ref().as_slice()) { + Ok(pk) => pk.verify( + signing_context(SIGNING_CTX).bytes(message.as_ref()), &signature + ), + Err(_) => false, + } + } + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { + let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(sig) { + Ok(some_signature) => some_signature, + Err(_) => return false + }; + match PublicKey::from_bytes(pubkey.as_ref()) { + Ok(pk) => pk.verify( + signing_context(SIGNING_CTX).bytes(message.as_ref()), &signature + ), + Err(_) => false, + } + } } -/// Serializes something that implements `AsRef<[u8; 32]>` into `ss58`. #[cfg(feature = "std")] -pub fn serialize>(data: &T, serializer: S) -> Result -where - S: Serializer, -{ - serializer.serialize_str(&Public(*data.as_ref()).to_ss58check()) +impl Pair { + /// Make a new key pair from binary data derived from a valid seed phrase. + /// + /// This uses a key derivation function to convert the entropy into a seed, then returns + /// the pair generated from it. + pub fn from_entropy(entropy: &[u8], password: Option<&str>) -> Pair { + let mini_key: MiniSecretKey = mini_secret_from_entropy(entropy, password.unwrap_or("")) + .expect("32 bytes can always build a key; qed"); + let kp = mini_key.expand_to_keypair(); + Pair(kp) + } } #[cfg(test)] mod test { use super::*; + use crate::crypto::{Ss58Codec, DEV_PHRASE, DEV_ADDRESS}; use hex_literal::{hex, hex_impl}; + #[test] + fn default_phrase_should_be_used() { + assert_eq!( + Pair::from_string("//Alice///password", None).unwrap().public(), + Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), + ); + assert_eq!( + Pair::from_string(&format!("{}/Alice", DEV_PHRASE), None).as_ref().map(Pair::public), + Pair::from_string("/Alice", None).as_ref().map(Pair::public) + ); + } + + #[test] + fn default_address_should_be_used() { + assert_eq!( + Public::from_string(&format!("{}/Alice", DEV_ADDRESS)), + Public::from_string("/Alice") + ); + } + + #[test] + fn default_phrase_should_correspond_to_default_address() { + assert_eq!( + Pair::from_string(&format!("{}/Alice", DEV_PHRASE), None).unwrap().public(), + Public::from_string(&format!("{}/Alice", DEV_ADDRESS)).unwrap(), + ); + assert_eq!( + Pair::from_string("/Alice", None).unwrap().public(), + Public::from_string("/Alice").unwrap() + ); + } + + #[test] + fn derive_soft_should_work() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let derive_1 = pair.derive(Some(DeriveJunction::soft(1)).into_iter()).unwrap(); + let derive_1b = pair.derive(Some(DeriveJunction::soft(1)).into_iter()).unwrap(); + let derive_2 = pair.derive(Some(DeriveJunction::soft(2)).into_iter()).unwrap(); + assert_eq!(derive_1.public(), derive_1b.public()); + assert_ne!(derive_1.public(), derive_2.public()); + } + + #[test] + fn derive_hard_should_work() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let derive_1 = pair.derive(Some(DeriveJunction::hard(1)).into_iter()).unwrap(); + let derive_1b = pair.derive(Some(DeriveJunction::hard(1)).into_iter()).unwrap(); + let derive_2 = pair.derive(Some(DeriveJunction::hard(2)).into_iter()).unwrap(); + assert_eq!(derive_1.public(), derive_1b.public()); + assert_ne!(derive_1.public(), derive_2.public()); + } + + #[test] + fn derive_soft_public_should_work() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let path = Some(DeriveJunction::soft(1)); + let pair_1 = pair.derive(path.clone().into_iter()).unwrap(); + let public_1 = pair.public().derive(path.into_iter()).unwrap(); + assert_eq!(pair_1.public(), public_1); + } + + #[test] + fn derive_hard_public_should_fail() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let path = Some(DeriveJunction::hard(1)); + assert!(pair.public().derive(path.into_iter()).is_none()); + } + #[test] fn sr_test_vector_should_work() { - let pair: Pair = Pair::from_seed(&hex!( + let pair: Pair = Pair::from_seed(hex!( "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); let public = pair.public(); @@ -288,8 +594,7 @@ mod test { ); let message = b""; let signature = pair.sign(message); - assert!(verify(&signature[..], message, &public.0)); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] @@ -298,13 +603,13 @@ mod test { let public = pair.public(); let message = b"Something important"; let signature = pair.sign(&message[..]); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] fn seeded_pair_should_work() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); let public = pair.public(); assert_eq!( public, @@ -314,7 +619,7 @@ mod test { ); let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); let signature = pair.sign(&message[..]); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] @@ -328,9 +633,13 @@ mod test { } #[test] - fn ss58check_known_works() { - let k = "5CGavy93sZgPPjHyziRohwVumxiHXMGmQLyuqQP4ZFx5vRU9"; - let enc = hex!["090fa15cb5b1666222fff584b4cc2b1761fe1e238346b340491b37e25ea183ff"]; - assert_eq!(Public::from_ss58check(k).unwrap(), Public::from_raw(enc)); + fn verify_from_wasm_works() { + // The values in this test case are compared to the output of `node-test.js` in schnorrkel-js. + // + // This is to make sure that the wasm library is compatible. + let pk = Pair::from_seed(hex!("0000000000000000000000000000000000000000000000000000000000000000")); + let public = pk.public(); + let js_signature = Signature::from_raw(hex!("28a854d54903e056f89581c691c1f7d2ff39f8f896c9e9c22475e60902cc2b3547199e0e91fa32902028f2ca2355e8cdd16cfe19ba5e8b658c94aa80f3b81a00")); + assert!(Pair::verify(&js_signature, b"SUBSTRATE", public)); } } diff --git a/core/primitives/src/storage.rs b/core/primitives/src/storage.rs index 36639fd88214fad32cace166c8e67f5ad30d14b3..79652a8d4ce3a211ac3490e57ebe4fa27164aabf 100644 --- a/core/primitives/src/storage.rs +++ b/core/primitives/src/storage.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/tests.rs b/core/primitives/src/tests.rs index 2205e4ac7ac808ee1226f3cd040966068e42ec49..2dbaed2b0faabdf2910f4b91f8b626dc5220c542 100644 --- a/core/primitives/src/tests.rs +++ b/core/primitives/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/u32_trait.rs b/core/primitives/src/u32_trait.rs index 88ee6bf29b277a88c264871dbeb1bad8ce85970d..3fcdceac4cbbfacea532c498648ccee980a0e36c 100644 --- a/core/primitives/src/u32_trait.rs +++ b/core/primitives/src/u32_trait.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/uint.rs b/core/primitives/src/uint.rs index 866d21c8a30c0056af874b199b480a3b773c18d8..dfea51921dc331ef5936fac83746da014fa0b5b1 100644 --- a/core/primitives/src/uint.rs +++ b/core/primitives/src/uint.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc-servers/src/lib.rs b/core/rpc-servers/src/lib.rs index 7497fa39060bdc45ba31e573dcf31e936cc917e4..939b2b93aa58abd511d665a50162b252d76cad0e 100644 --- a/core/rpc-servers/src/lib.rs +++ b/core/rpc-servers/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/Cargo.toml b/core/rpc/Cargo.toml index 47edca65dc439ba808e2d25a66c8463b81fb2ba4..8998ebe81f5e4b08217838a3e090f0c0e040a1ae 100644 --- a/core/rpc/Cargo.toml +++ b/core/rpc/Cargo.toml @@ -11,7 +11,7 @@ jsonrpc-pubsub = "10.0.1" jsonrpc-derive = "10.0.2" log = "0.4" parking_lot = "0.7.1" -parity-codec = "3.1" +parity-codec = "3.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" @@ -28,7 +28,9 @@ tokio = "0.1.7" [dev-dependencies] assert_matches = "1.1" futures = "0.1.17" +sr-io = { path = "../sr-io" } test_client = { package = "substrate-test-client", path = "../test-client" } +test_runtime = { package = "substrate-test-runtime", path = "../test-runtime" } consensus = { package = "substrate-consensus-common", path = "../consensus/common" } rustc-hex = "2.0" hex-literal = "0.1" diff --git a/core/rpc/src/author/error.rs b/core/rpc/src/author/error.rs index 5024aba5fff8ef6dcc9b3884c6b433a732bc4221..9c1ec232252001e10640e655f091cd970417559b 100644 --- a/core/rpc/src/author/error.rs +++ b/core/rpc/src/author/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -47,22 +47,77 @@ error_chain! { } } -const ERROR: i64 = 1000; +/// Base code for all authorship errors. +const BASE_ERROR: i64 = 1000; +/// Extrinsic has an invalid format. +const BAD_FORMAT: i64 = BASE_ERROR + 1; +/// Error during transaction verification in runtime. +const VERIFICATION_ERROR: i64 = BASE_ERROR + 2; + +/// Pool rejected the transaction as invalid +const POOL_INVALID_TX: i64 = BASE_ERROR + 10; +/// Cannot determine transaction validity. +const POOL_UNKNOWN_VALIDITY: i64 = POOL_INVALID_TX + 1; +/// The transaction is temporarily banned. +const POOL_TEMPORARILY_BANNED: i64 = POOL_INVALID_TX + 2; +/// The transaction is already in the pool +const POOL_ALREADY_IMPORTED: i64 = POOL_INVALID_TX + 3; +/// Transaction has too low priority to replace existing one in the pool. +const POOL_TOO_LOW_PRIORITY: i64 = POOL_INVALID_TX + 4; +/// Including this transaction would cause a dependency cycle. +const POOL_CYCLE_DETECTED: i64 = POOL_INVALID_TX + 5; +/// The transaction was not included to the pool because of the limits. +const POOL_IMMEDIATELY_DROPPED: i64 = POOL_INVALID_TX + 6; impl From for rpc::Error { fn from(e: Error) -> Self { match e { Error(ErrorKind::Unimplemented, _) => errors::unimplemented(), Error(ErrorKind::BadFormat, _) => rpc::Error { - code: rpc::ErrorCode::ServerError(ERROR + 1), + code: rpc::ErrorCode::ServerError(BAD_FORMAT), message: "Extrinsic has invalid format.".into(), data: None, }, Error(ErrorKind::Verification(e), _) => rpc::Error { - code: rpc::ErrorCode::ServerError(ERROR + 2), + code: rpc::ErrorCode::ServerError(VERIFICATION_ERROR), message: e.description().into(), data: Some(format!("{:?}", e).into()), }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::InvalidTransaction(code)), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), + message: "Invalid Transaction".into(), + data: Some(code.into()), + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::UnknownTransactionValidity(code)), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), + message: "Unknown Transaction Validity".into(), + data: Some(code.into()), + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::TemporarilyBanned), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_TEMPORARILY_BANNED), + message: "Transaction is temporarily banned".into(), + data: None, + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::AlreadyImported(hash)), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_ALREADY_IMPORTED), + message: "Transaction Already Imported".into(), + data: Some(format!("{:?}", hash).into()), + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::TooLowPriority(old, new)), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_TOO_LOW_PRIORITY), + message: format!("Priority is too low: ({} vs {})", old, new), + data: Some("The transaction has too low priority to replace another transaction already in the pool.".into()), + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::CycleDetected), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_CYCLE_DETECTED), + message: "Cycle Detected".into(), + data: None, + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::ImmediatelyDropped), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_IMMEDIATELY_DROPPED), + message: "Immediately Dropped" .into(), + data: Some("The transaction couldn't enter the pool because of the limit".into()), + }, e => errors::internal(e), } } diff --git a/core/rpc/src/author/mod.rs b/core/rpc/src/author/mod.rs index e9e527f9cbef1fde2fd57d9dd3e9df75cc28c9e0..acd500ba0bfe309ddec5c36c698f0cb5a71473e0 100644 --- a/core/rpc/src/author/mod.rs +++ b/core/rpc/src/author/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/author/tests.rs b/core/rpc/src/author/tests.rs index b71a20f38de9a856d98c778027b203584599af1c..53166e76f82ea01f48395472b47e48c5d49c79a0 100644 --- a/core/rpc/src/author/tests.rs +++ b/core/rpc/src/author/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,27 +17,24 @@ use super::*; use std::sync::Arc; -use hex_literal::{hex, hex_impl}; use assert_matches::assert_matches; use parity_codec::Encode; use transaction_pool::{ txpool::Pool, ChainApi, }; -use primitives::H256; -use test_client::keyring::Keyring; -use test_client::runtime::{Extrinsic, Transfer}; -use test_client; +use primitives::{H256, blake2_256, hexdisplay::HexDisplay}; +use test_client::{self, AccountKeyring, runtime::{Extrinsic, Transfer}}; use tokio::runtime; -fn uxt(sender: Keyring, nonce: u64) -> Extrinsic { +fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { let tx = Transfer { amount: Default::default(), nonce, - from: sender.to_raw_public().into(), + from: sender.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) } @@ -50,14 +47,15 @@ fn submit_transaction_should_not_cause_error() { pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client))), subscriptions: Subscriptions::new(runtime.executor()), }; - let h: H256 = hex!("81897a4890fb7554e7f77c533a865846a11583a56a8ad5e307543188d55e64f1").into(); + let xt = uxt(AccountKeyring::Alice, 1).encode(); + let h: H256 = blake2_256(&xt).into(); assert_matches!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 1).encode().into()), + AuthorApi::submit_extrinsic(&p, xt.clone().into()), Ok(h2) if h == h2 ); assert!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 1).encode().into()).is_err() + AuthorApi::submit_extrinsic(&p, xt.into()).is_err() ); } @@ -70,14 +68,15 @@ fn submit_rich_transaction_should_not_cause_error() { pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client.clone()))), subscriptions: Subscriptions::new(runtime.executor()), }; - let h: H256 = hex!("9ec8469b5dcfe29cc274ac1d07ad73d80be57566ace0fcdbe51ebcf4b51e925b").into(); + let xt = uxt(AccountKeyring::Alice, 0).encode(); + let h: H256 = blake2_256(&xt).into(); assert_matches!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 0).encode().into()), + AuthorApi::submit_extrinsic(&p, xt.clone().into()), Ok(h2) if h == h2 ); assert!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 0).encode().into()).is_err() + AuthorApi::submit_extrinsic(&p, xt.into()).is_err() ); } @@ -95,7 +94,7 @@ fn should_watch_extrinsic() { let (subscriber, id_rx, data) = ::jsonrpc_pubsub::typed::Subscriber::new_test("test"); // when - p.watch_extrinsic(Default::default(), subscriber, uxt(Keyring::Alice, 0).encode().into()); + p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 0).encode().into()); // then assert_eq!(runtime.block_on(id_rx), Ok(Ok(1.into()))); @@ -104,10 +103,10 @@ fn should_watch_extrinsic() { let tx = Transfer { amount: 5, nonce: 0, - from: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) }; AuthorApi::submit_extrinsic(&p, replacement.encode().into()).unwrap(); @@ -116,9 +115,10 @@ fn should_watch_extrinsic() { res, Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":"ready","subscription":1}}"#.into()) ); + let h = blake2_256(&replacement.encode()); assert_eq!( runtime.block_on(data.into_future()).unwrap().0, - Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"usurped":"0x53daed816610aa6b22dedbcee43aba44a7ca7155cc71f2919c5e79ebbc7de58c"},"subscription":1}}"#.into()) + Some(format!(r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":1}}}}"#, HexDisplay::from(&h))) ); } @@ -132,7 +132,7 @@ fn should_return_pending_extrinsics() { pool: pool.clone(), subscriptions: Subscriptions::new(runtime.executor()), }; - let ex = uxt(Keyring::Alice, 0); + let ex = uxt(AccountKeyring::Alice, 0); AuthorApi::submit_extrinsic(&p, ex.encode().into()).unwrap(); assert_matches!( p.pending_extrinsics(), diff --git a/core/rpc/src/chain/error.rs b/core/rpc/src/chain/error.rs index 4fd098ca7214b494007215eab98fb6eb3366cb4e..c52d44eddc3392d6a35fa4ec2dc292cb677b2a58 100644 --- a/core/rpc/src/chain/error.rs +++ b/core/rpc/src/chain/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/chain/mod.rs b/core/rpc/src/chain/mod.rs index 885159231b40352c9bea44c73aabf6361edeaa02..de7ad3faad8d8bb779d26ce87207d42d0e5c074b 100644 --- a/core/rpc/src/chain/mod.rs +++ b/core/rpc/src/chain/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -57,9 +57,9 @@ pub trait ChainApi { #[rpc(name = "chain_getBlockHash", alias("chain_getHead"))] fn block_hash(&self, hash: Option>) -> Result>; - /// Get hash of the last finalised block in the canon chain. - #[rpc(name = "chain_getFinalisedHead")] - fn finalised_head(&self) -> Result; + /// Get hash of the last finalized block in the canon chain. + #[rpc(name = "chain_getFinalizedHead", alias("chain_getFinalisedHead"))] + fn finalized_head(&self) -> Result; /// New head subscription #[pubsub( @@ -81,19 +81,21 @@ pub trait ChainApi { /// New head subscription #[pubsub( - subscription = "chain_finalisedHead", + subscription = "chain_finalizedHead", subscribe, - name = "chain_subscribeFinalisedHeads" + name = "chain_subscribeFinalizedHeads", + alias("chain_subscribeFinalisedHeads") )] - fn subscribe_finalised_heads(&self, metadata: Self::Metadata, subscriber: Subscriber

); + fn subscribe_finalized_heads(&self, metadata: Self::Metadata, subscriber: Subscriber
); /// Unsubscribe from new head subscription. #[pubsub( - subscription = "chain_finalisedHead", + subscription = "chain_finalizedHead", unsubscribe, - name = "chain_unsubscribeFinalisedHeads" + name = "chain_unsubscribeFinalizedHeads", + alias("chain_unsubscribeFinalisedHeads") )] - fn unsubscribe_finalised_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + fn unsubscribe_finalized_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult; } /// Chain API with subscriptions support. @@ -192,7 +194,7 @@ impl ChainApi, Block::Hash, Block::Header, Sig }) } - fn finalised_head(&self) -> Result { + fn finalized_head(&self) -> Result { Ok(self.client.info()?.chain.finalized_hash) } @@ -210,7 +212,7 @@ impl ChainApi, Block::Hash, Block::Header, Sig Ok(self.subscriptions.cancel(id)) } - fn subscribe_finalised_heads(&self, _meta: Self::Metadata, subscriber: Subscriber) { + fn subscribe_finalized_heads(&self, _meta: Self::Metadata, subscriber: Subscriber) { self.subscribe_headers( subscriber, || Ok(Some(self.client.info()?.chain.finalized_hash)), @@ -219,7 +221,7 @@ impl ChainApi, Block::Hash, Block::Header, Sig ) } - fn unsubscribe_finalised_heads(&self, _metadata: Option, id: SubscriptionId) -> RpcResult { + fn unsubscribe_finalized_heads(&self, _metadata: Option, id: SubscriptionId) -> RpcResult { Ok(self.subscriptions.cancel(id)) } } diff --git a/core/rpc/src/chain/tests.rs b/core/rpc/src/chain/tests.rs index becc57f2a9e1c4378e43ad9b327b5cf958e5e0e2..26b7202305b16745ba0d516cb442765085e97ac5 100644 --- a/core/rpc/src/chain/tests.rs +++ b/core/rpc/src/chain/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -157,7 +157,7 @@ fn should_return_block_hash() { #[test] -fn should_return_finalised_hash() { +fn should_return_finalized_hash() { let core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); @@ -167,23 +167,23 @@ fn should_return_finalised_hash() { }; assert_matches!( - client.finalised_head(), + client.finalized_head(), Ok(ref x) if x == &client.client.genesis_hash() ); // import new block let builder = client.client.new_block().unwrap(); client.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - // no finalisation yet + // no finalization yet assert_matches!( - client.finalised_head(), + client.finalized_head(), Ok(ref x) if x == &client.client.genesis_hash() ); - // finalise + // finalize client.client.finalize_block(BlockId::number(1), None, true).unwrap(); assert_matches!( - client.finalised_head(), + client.finalized_head(), Ok(ref x) if x == &client.client.block_hash(1).unwrap().unwrap() ); } @@ -220,7 +220,7 @@ fn should_notify_about_latest_block() { } #[test] -fn should_notify_about_finalised_block() { +fn should_notify_about_finalized_block() { let mut core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); @@ -231,7 +231,7 @@ fn should_notify_about_finalised_block() { subscriptions: Subscriptions::new(remote), }; - api.subscribe_finalised_heads(Default::default(), subscriber); + api.subscribe_finalized_heads(Default::default(), subscriber); // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); diff --git a/core/rpc/src/errors.rs b/core/rpc/src/errors.rs index 9a4928440d64a0f53641e9487ddac79effc8094e..a709013ad26801a471f7dd99d94c6ed10390b78b 100644 --- a/core/rpc/src/errors.rs +++ b/core/rpc/src/errors.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/helpers.rs b/core/rpc/src/helpers.rs index b9c665191d92833c71e42c7c160a13e964510e30..e579c743acdad202caedfd39e760559129c6109f 100644 --- a/core/rpc/src/helpers.rs +++ b/core/rpc/src/helpers.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/lib.rs b/core/rpc/src/lib.rs index d9e9b18146260c73004bcbf528b0d9beaebb9c9f..6488ea5f49c54120f5a77dbd1c23e8e16004b3d9 100644 --- a/core/rpc/src/lib.rs +++ b/core/rpc/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/metadata.rs b/core/rpc/src/metadata.rs index 728abe1de7269302eee29aeda233f006f6c94128..e6af4ef94bc1adf6fee90eb520630da09ed18942 100644 --- a/core/rpc/src/metadata.rs +++ b/core/rpc/src/metadata.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/state/error.rs b/core/rpc/src/state/error.rs index 6cbe7eba9664bbbd2df1af4317df7d3fbab1e31b..bd85664099a5bbed55a79884c764b7e37e255c2a 100644 --- a/core/rpc/src/state/error.rs +++ b/core/rpc/src/state/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/state/mod.rs b/core/rpc/src/state/mod.rs index 4e51151e509107fe5fe0b135145ba231b85e69ba..168c0bd692732dbc564f04a511f11d0f288da3ec 100644 --- a/core/rpc/src/state/mod.rs +++ b/core/rpc/src/state/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -35,7 +35,7 @@ use crate::rpc::futures::{stream, Future, Sink, Stream}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Block as BlockT, Header, ProvideRuntimeApi, As, NumberFor}; use runtime_version::RuntimeVersion; -use state_machine::ExecutionStrategy; +use state_machine::{self, ExecutionStrategy}; use crate::subscriptions::Subscriptions; @@ -298,7 +298,7 @@ impl StateApi for State where .executor() .call( &BlockId::Hash(block), - &method, &data.0, ExecutionStrategy::NativeElseWasm + &method, &data.0, ExecutionStrategy::NativeElseWasm, state_machine::NeverOffchainExt::new(), )?; Ok(Bytes(return_data)) } diff --git a/core/rpc/src/state/tests.rs b/core/rpc/src/state/tests.rs index 354ef0ed2825ac834543c32dbaac6377763873d1..6746685d368ff14f9e6f3583578b54ca8e176af8 100644 --- a/core/rpc/src/state/tests.rs +++ b/core/rpc/src/state/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,10 +17,10 @@ use super::*; use self::error::{Error, ErrorKind}; +use sr_io::twox_128; use assert_matches::assert_matches; use consensus::BlockOrigin; -use rustc_hex::FromHex; -use test_client::{self, runtime, keyring::Keyring, TestClient, BlockBuilderExt}; +use test_client::{self, runtime, AccountKeyring, TestClient, BlockBuilderExt}; #[test] fn should_return_storage() { @@ -64,8 +64,8 @@ fn should_notify_about_storage_changes() { let mut builder = api.client.new_block().unwrap(); builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -88,8 +88,10 @@ fn should_send_initial_storage_changes_and_notifications() { { let api = State::new(Arc::new(test_client::new()), Subscriptions::new(remote)); + let alice_balance_key = twox_128(&test_runtime::system::balance_of_key(AccountKeyring::Alice.into())); + api.subscribe_storage(Default::default(), subscriber, Some(vec![ - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), ]).into()); // assert id assigned @@ -97,8 +99,8 @@ fn should_send_initial_storage_changes_and_notifications() { let mut builder = api.client.new_block().unwrap(); builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -131,8 +133,8 @@ fn should_query_storage() { let add_block = |nonce| { let mut builder = client.new_block().unwrap(); builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce, }).unwrap(); @@ -145,13 +147,14 @@ fn should_query_storage() { let block2_hash = add_block(1); let genesis_hash = client.genesis_hash(); + let alice_balance_key = twox_128(&test_runtime::system::balance_of_key(AccountKeyring::Alice.into())); let mut expected = vec![ StorageChangeSet { block: genesis_hash, changes: vec![ ( - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), Some(StorageData(vec![232, 3, 0, 0, 0, 0, 0, 0])) ), ], @@ -160,7 +163,7 @@ fn should_query_storage() { block: block1_hash, changes: vec![ ( - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), Some(StorageData(vec![190, 3, 0, 0, 0, 0, 0, 0])) ), ], @@ -169,7 +172,7 @@ fn should_query_storage() { // Query changes only up to block1 let result = api.query_storage( - vec![StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap())], + vec![StorageKey(alice_balance_key.to_vec())], genesis_hash, Some(block1_hash).into(), ); @@ -178,7 +181,7 @@ fn should_query_storage() { // Query all changes let result = api.query_storage( - vec![StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap())], + vec![StorageKey(alice_balance_key.to_vec())], genesis_hash, None.into(), ); @@ -187,7 +190,7 @@ fn should_query_storage() { block: block2_hash, changes: vec![ ( - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), Some(StorageData(vec![148, 3, 0, 0, 0, 0, 0, 0])) ), ], @@ -218,7 +221,7 @@ fn should_return_runtime_version() { assert_eq!( ::serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(), - r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",1],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",2],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1]]}"# + r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",1],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",2],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1],["0xf78b278be53f454c",1],["0x7801759919ee83e5",1]]}"# ); } diff --git a/core/rpc/src/subscriptions.rs b/core/rpc/src/subscriptions.rs index 5e9f6c5caccfd5587661acac69e9dcab7a19b179..500f3dac4545ccf966cf558f0dc94ccbb6f192de 100644 --- a/core/rpc/src/subscriptions.rs +++ b/core/rpc/src/subscriptions.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/system/error.rs b/core/rpc/src/system/error.rs index 04890b05871f8e7b68c27e4c1ee1bf5d764378a8..d3c7e8b33387048385abcad3e620a615646f0dc5 100644 --- a/core/rpc/src/system/error.rs +++ b/core/rpc/src/system/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/rpc/src/system/helpers.rs b/core/rpc/src/system/helpers.rs index ba4d9c8f1671d2ab55da0c262899fd5817278134..9f64318d5db114b94c0dda4ed4e713c528502bfc 100644 --- a/core/rpc/src/system/helpers.rs +++ b/core/rpc/src/system/helpers.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -54,8 +54,6 @@ pub struct Health { #[derive(Debug, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct PeerInfo { - /// Peer Node Index - pub index: usize, /// Peer ID pub peer_id: String, /// Roles @@ -96,14 +94,13 @@ mod tests { fn should_serialize_peer_info() { assert_eq!( ::serde_json::to_string(&PeerInfo { - index: 1, peer_id: "2".into(), roles: "a".into(), protocol_version: 2, best_hash: 5u32, best_number: 6u32, }).unwrap(), - r#"{"index":1,"peerId":"2","roles":"a","protocolVersion":2,"bestHash":5,"bestNumber":6}"#, + r#"{"peerId":"2","roles":"a","protocolVersion":2,"bestHash":5,"bestNumber":6}"#, ); } } diff --git a/core/rpc/src/system/mod.rs b/core/rpc/src/system/mod.rs index 6819d23593c237573022a5a02abd0c8bbf632a13..331d9cd85ba61739c3833c5ec2497f2cf2331988 100644 --- a/core/rpc/src/system/mod.rs +++ b/core/rpc/src/system/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -117,9 +117,8 @@ impl SystemApi::Number> for Sy } fn system_peers(&self) -> Result::Number>>> { - Ok(self.sync.peers().into_iter().map(|(index, p)| PeerInfo { - index, - peer_id: p.peer_id.to_base58(), + Ok(self.sync.peers().into_iter().map(|(peer_id, p)| PeerInfo { + peer_id: peer_id.to_base58(), roles: format!("{:?}", p.roles), protocol_version: p.protocol_version, best_hash: p.best_hash, diff --git a/core/rpc/src/system/tests.rs b/core/rpc/src/system/tests.rs index 319b5bb85a77c23b30fffe6d1450b24c064a5594..b4b71a7937af16e988e6e156a1bdecde1b05ecca 100644 --- a/core/rpc/src/system/tests.rs +++ b/core/rpc/src/system/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ use super::*; -use network::{self, ProtocolStatus, NodeIndex, PeerId, PeerInfo as NetworkPeerInfo}; +use network::{self, ProtocolStatus, PeerId, PeerInfo as NetworkPeerInfo}; use network::config::Roles; use test_client::runtime::Block; use assert_matches::assert_matches; @@ -50,22 +50,20 @@ impl network::SyncProvider for Status { network::NetworkState { peer_id: String::new(), listened_addresses: Default::default(), - is_reserved_only: false, - reserved_peers: Default::default(), - banned_peers: Default::default(), + external_addresses: Default::default(), connected_peers: Default::default(), not_connected_peers: Default::default(), average_download_per_sec: 0, average_upload_per_sec: 0, + peerset: serde_json::Value::Null, } } - fn peers(&self) -> Vec<(NodeIndex, NetworkPeerInfo)> { + fn peers(&self) -> Vec<(PeerId, NetworkPeerInfo)> { let mut peers = vec![]; for _peer in 0..self.peers { peers.push( - (1, NetworkPeerInfo { - peer_id: self.peer_id.clone(), + (self.peer_id.clone(), NetworkPeerInfo { roles: Roles::FULL, protocol_version: 1, best_hash: Default::default(), @@ -190,7 +188,6 @@ fn system_peers() { is_dev: true, }).system_peers().unwrap(), vec![PeerInfo { - index: 1, peer_id: peer_id.to_base58(), roles: "FULL".into(), protocol_version: 1, @@ -207,13 +204,12 @@ fn system_network_state() { network::NetworkState { peer_id: String::new(), listened_addresses: Default::default(), - is_reserved_only: false, - reserved_peers: Default::default(), - banned_peers: Default::default(), + external_addresses: Default::default(), connected_peers: Default::default(), not_connected_peers: Default::default(), average_download_per_sec: 0, average_upload_per_sec: 0, + peerset: serde_json::Value::Null, } ); } diff --git a/core/serializer/Cargo.toml b/core/serializer/Cargo.toml index d25c8ce0742d2e78ee56f17908cd63b138a2694c..8788f776e5a2842abfb375f3d9023b84a9abbba0 100644 --- a/core/serializer/Cargo.toml +++ b/core/serializer/Cargo.toml @@ -5,5 +5,5 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } +serde = "1.0" serde_json = "1.0" diff --git a/core/serializer/src/lib.rs b/core/serializer/src/lib.rs index a357d5ad2b31999106a9632b0158b4fb03ca79e2..2586d49f00599ea919ce635092048a9c0f039dd7 100644 --- a/core/serializer/src/lib.rs +++ b/core/serializer/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/service/Cargo.toml b/core/service/Cargo.toml index 59fd77a219622e58e54dd442c6488b2cc8a79643..b2f431a5db3361d76b2b68e43945132d7e2e3928 100644 --- a/core/service/Cargo.toml +++ b/core/service/Cargo.toml @@ -17,6 +17,7 @@ serde = "1.0" serde_json = "1.0" serde_derive = "1.0" target_info = "0.1" +inherents = { package = "substrate-inherents", path = "../../core/inherents" } keystore = { package = "substrate-keystore", path = "../../core/keystore" } sr-io = { path = "../../core/sr-io" } runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } @@ -25,11 +26,12 @@ consensus_common = { package = "substrate-consensus-common", path = "../../core/ network = { package = "substrate-network", path = "../../core/network" } client = { package = "substrate-client", path = "../../core/client" } client_db = { package = "substrate-client-db", path = "../../core/client/db" } -parity-codec = "3.1" +parity-codec = "3.2" substrate-executor = { path = "../../core/executor" } transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } rpc = { package = "substrate-rpc-servers", path = "../../core/rpc-servers" } tel = { package = "substrate-telemetry", path = "../../core/telemetry" } +offchain = { package = "substrate-offchain", path = "../../core/offchain" } [dev-dependencies] substrate-test-client = { path = "../test-client" } diff --git a/core/service/src/chain_ops.rs b/core/service/src/chain_ops.rs index 487c7ac0a614656f85ece36163eb648945ccde5f..36cbee9039395737edb62df50fa0d54d4a80fac3 100644 --- a/core/service/src/chain_ops.rs +++ b/core/service/src/chain_ops.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/service/src/chain_spec.rs b/core/service/src/chain_spec.rs index 8e231f40294f74495ed9ad45c3c8bf33740ee4d5..78aad64dd0730a708dffe83a619d65c953fc4529 100644 --- a/core/service/src/chain_spec.rs +++ b/core/service/src/chain_spec.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -72,6 +72,9 @@ impl<'a, G: RuntimeGenesis> BuildStorage for &'a ChainSpec { Genesis::Raw(map) => Ok((map.into_iter().map(|(k, v)| (k.0, v.0)).collect(), Default::default())), } } + fn assimilate_storage(self, _: &mut StorageOverlay, _: &mut ChildrenStorageOverlay) -> Result<(), String> { + Err("`assimilate_storage` not implemented for `ChainSpec`.".into()) + } } #[derive(Serialize, Deserialize)] @@ -113,35 +116,43 @@ impl Clone for ChainSpec { } impl ChainSpec { + /// A list of bootnode addresses. pub fn boot_nodes(&self) -> &[String] { &self.spec.boot_nodes } + /// Spec name. pub fn name(&self) -> &str { &self.spec.name } + /// Spec id. pub fn id(&self) -> &str { &self.spec.id } + /// Telemetry endpoints (if any) pub fn telemetry_endpoints(&self) -> &Option { &self.spec.telemetry_endpoints } + /// Network protocol id. pub fn protocol_id(&self) -> Option<&str> { self.spec.protocol_id.as_ref().map(String::as_str) } + /// Name of the consensus engine. pub fn consensus_engine(&self) -> Option<&str> { self.spec.consensus_engine.as_ref().map(String::as_str) } + /// Additional loosly-typed properties of the chain. pub fn properties(&self) -> Properties { // Return an empty JSON object if 'properties' not defined in config self.spec.properties.as_ref().unwrap_or(&json::map::Map::new()).clone() } + /// Add a bootnode to the list. pub fn add_boot_node(&mut self, addr: Multiaddr) { self.spec.boot_nodes.push(addr.to_string()) } diff --git a/core/service/src/components.rs b/core/service/src/components.rs index 44793c69f26b996620830145836b82b373a30f07..eb37a69a14ca2dc9c161a785d02029b31979b0d8 100644 --- a/core/service/src/components.rs +++ b/core/service/src/components.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ use serde::{Serialize, de::DeserializeOwned}; use tokio::runtime::TaskExecutor; use crate::chain_spec::ChainSpec; use client_db; -use client::{self, Client, runtime_api::{Metadata, TaggedTransactionQueue}}; +use client::{self, Client, runtime_api}; use crate::{error, Service, maybe_start_server}; use consensus_common::import_queue::ImportQueue; use network::{self, OnDemand}; @@ -150,7 +150,7 @@ pub trait StartRPC { impl StartRPC for C where ComponentClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: Metadata>, + as ProvideRuntimeApi>::Api: runtime_api::Metadata>, { type ServersHandle = (Option, Option>); @@ -192,14 +192,14 @@ impl StartRPC for C where /// Something that can maintain transaction pool on every imported block. pub trait MaintainTransactionPool { - fn on_block_imported( + fn maintain_transaction_pool( id: &BlockId>, client: &ComponentClient, transaction_pool: &TransactionPool, ) -> error::Result<()>; } -fn on_block_imported( +fn maintain_transaction_pool( id: &BlockId, client: &Client, transaction_pool: &TransactionPool, @@ -207,7 +207,7 @@ fn on_block_imported( Block: BlockT::Out>, Backend: client::backend::Backend, Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: TaggedTransactionQueue, + as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, Executor: client::CallExecutor, PoolApi: txpool::ChainApi, { @@ -227,14 +227,35 @@ fn on_block_imported( impl MaintainTransactionPool for C where ComponentClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: TaggedTransactionQueue>, + as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue>, { - fn on_block_imported( + fn maintain_transaction_pool( id: &BlockId>, client: &ComponentClient, transaction_pool: &TransactionPool, ) -> error::Result<()> { - on_block_imported(id, client, transaction_pool) + maintain_transaction_pool(id, client, transaction_pool) + } +} + +pub trait OffchainWorker { + fn offchain_workers( + number: &FactoryBlockNumber, + offchain: &offchain::OffchainWorkers, ComponentBlock>, + pool: &Arc>, + ) -> error::Result<()>; +} + +impl OffchainWorker for C where + ComponentClient: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: offchain::OffchainWorkerApi>, +{ + fn offchain_workers( + number: &FactoryBlockNumber, + offchain: &offchain::OffchainWorkers, ComponentBlock>, + pool: &Arc>, + ) -> error::Result<()> { + Ok(offchain.on_block_imported(number, pool)) } } @@ -246,9 +267,16 @@ pub trait ServiceTrait: + 'static + StartRPC + MaintainTransactionPool + + OffchainWorker {} impl ServiceTrait for T where - T: Deref> + Send + Sync + 'static + StartRPC + MaintainTransactionPool + T: Deref> + + Send + + Sync + + 'static + + StartRPC + + MaintainTransactionPool + + OffchainWorker {} /// A collection of types and methods to build a service on top of the substrate service. @@ -328,7 +356,7 @@ pub trait ServiceFactory: 'static + Sized { } } -/// A collection of types and function to generalise over full / light client type. +/// A collection of types and function to generalize over full / light client type. pub trait Components: Sized + 'static { /// Associated service factory. type Factory: ServiceFactory; @@ -338,17 +366,14 @@ pub trait Components: Sized + 'static { type Executor: 'static + client::CallExecutor, Blake2Hasher> + Send + Sync + Clone; /// The type that implements the runtime API. type RuntimeApi: Send + Sync; - /// A type that can start the RPC. - type RPC: StartRPC; + /// A type that can start all runtime-dependent services. + type RuntimeServices: ServiceTrait; // TODO: Traitify transaction pool and allow people to implement their own. (#1242) - /// A type that can maintain transaction pool. - type TransactionPool: MaintainTransactionPool; /// Extrinsic pool type. type TransactionPoolApi: 'static + txpool::ChainApi< Hash = as BlockT>::Hash, Block = FactoryBlock >; - /// Our Import Queue type ImportQueue: ImportQueue> + 'static; @@ -382,6 +407,7 @@ pub struct FullComponents { } impl FullComponents { + /// Create new `FullComponents` pub fn new( config: FactoryFullConfiguration, task_executor: TaskExecutor @@ -416,8 +442,7 @@ impl Components for FullComponents { type TransactionPoolApi = ::FullTransactionPoolApi; type ImportQueue = Factory::FullImportQueue; type RuntimeApi = Factory::RuntimeApi; - type RPC = Factory::FullService; - type TransactionPool = Factory::FullService; + type RuntimeServices = Factory::FullService; fn build_client( config: &FactoryFullConfiguration, @@ -462,6 +487,7 @@ pub struct LightComponents { } impl LightComponents { + /// Create new `LightComponents` pub fn new( config: FactoryFullConfiguration, task_executor: TaskExecutor @@ -490,8 +516,7 @@ impl Components for LightComponents { type TransactionPoolApi = ::LightTransactionPoolApi; type ImportQueue = ::LightImportQueue; type RuntimeApi = Factory::RuntimeApi; - type RPC = Factory::LightService; - type TransactionPool = Factory::LightService; + type RuntimeServices = Factory::LightService; fn build_client( config: &FactoryFullConfiguration, @@ -536,12 +561,7 @@ mod tests { use super::*; use parity_codec::Encode; use consensus_common::BlockOrigin; - use substrate_test_client::{ - self, - TestClient, - keyring::Keyring, - runtime::{Extrinsic, Transfer}, - }; + use substrate_test_client::{self, TestClient, AccountKeyring, runtime::{Extrinsic, Transfer}}; #[test] fn should_remove_transactions_from_the_pool() { @@ -551,10 +571,10 @@ mod tests { let transfer = Transfer { amount: 5, nonce: 0, - from: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(transfer.from.to_fixed_bytes()).unwrap().sign(&transfer.encode()).into(); + let signature = AccountKeyring::from_public(&transfer.from).unwrap().sign(&transfer.encode()).into(); Extrinsic::Transfer(transfer, signature) }; // store the transaction in the pool @@ -569,7 +589,7 @@ mod tests { // fire notification - this should clean up the queue assert_eq!(pool.status().ready, 1); - on_block_imported( + maintain_transaction_pool( &id, &client, &pool, diff --git a/core/service/src/config.rs b/core/service/src/config.rs index 9883996eacf62ac5655afa7ee941b775ac08a917..b7a3b8ba141a547f13321e0cc453532a067494df 100644 --- a/core/service/src/config.rs +++ b/core/service/src/config.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -68,6 +68,12 @@ pub struct Configuration { pub telemetry_endpoints: Option, /// The default number of 64KB pages to allocate for Wasm execution pub default_heap_pages: Option, + /// Should offchain workers be executed. + pub offchain_worker: bool, + /// Enable authoring even when offline. + pub force_authoring: bool, + /// Disable GRANDPA when running in validator mode + pub disable_grandpa: bool, } impl Configuration { @@ -93,6 +99,9 @@ impl Configuration { client: Arc>, network: Option>>, transaction_pool: Arc>, + inherents_pool: Arc>>, keystore: Keystore, exit: ::exit_future::Exit, signal: Option, @@ -76,6 +81,7 @@ pub struct Service { pub config: FactoryFullConfiguration, _rpc: Box<::std::any::Any + Send + Sync>, _telemetry: Option>, + _offchain_workers: Option, ComponentBlock>>>, } /// Creates bare client without any networking. @@ -95,9 +101,7 @@ impl Service { pub fn new( mut config: FactoryFullConfiguration, task_executor: TaskExecutor, - ) - -> Result - { + ) -> Result { let (signal, exit) = ::exit_future::signal(); // Create client @@ -168,24 +172,48 @@ impl Service { )?; on_demand.map(|on_demand| on_demand.set_network_sender(network_chan)); + let inherents_pool = Arc::new(InherentsPool::default()); + let offchain_workers = if config.offchain_worker { + Some(Arc::new(offchain::OffchainWorkers::new( + client.clone(), + inherents_pool.clone(), + task_executor.clone(), + ))) + } else { + None + }; + { // block notifications let network = Arc::downgrade(&network); let txpool = Arc::downgrade(&transaction_pool); let wclient = Arc::downgrade(&client); + let offchain = offchain_workers.as_ref().map(Arc::downgrade); let events = client.import_notification_stream() .for_each(move |notification| { + let number = *notification.header.number(); + if let Some(network) = network.upgrade() { network.on_block_imported(notification.hash, notification.header); } + if let (Some(txpool), Some(client)) = (txpool.upgrade(), wclient.upgrade()) { - Components::TransactionPool::on_block_imported( + Components::RuntimeServices::maintain_transaction_pool( &BlockId::hash(notification.hash), &*client, &*txpool, ).map_err(|e| warn!("Pool error processing new block: {:?}", e))?; } + + if let (Some(txpool), Some(offchain)) = (txpool.upgrade(), offchain.as_ref().and_then(|o| o.upgrade())) { + Components::RuntimeServices::offchain_workers( + &number, + &offchain, + &txpool, + ).map_err(|e| warn!("Offchain workers error processing new block: {:?}", e))?; + } + Ok(()) }) .select(exit.clone()) @@ -200,9 +228,9 @@ impl Service { // A utility stream that drops all ready items and only returns the last one. // This is used to only keep the last finality notification and avoid // overloading the sync module with notifications. - struct MostRecentNotification(futures::stream::Fuse>); + struct MostRecentNotification(futures::stream::Fuse>); - impl Stream for MostRecentNotification { + impl Stream for MostRecentNotification { type Item = as Stream>::Item; type Error = as Stream>::Error; @@ -263,7 +291,7 @@ impl Service { impl_version: config.impl_version.into(), properties: config.chain_spec.properties(), }; - let rpc = Components::RPC::start_rpc( + let rpc = Components::RuntimeServices::start_rpc( client.clone(), network.clone(), has_bootnodes, system_info, config.rpc_http, config.rpc_ws, task_executor.clone(), transaction_pool.clone(), )?; @@ -298,12 +326,14 @@ impl Service { client, network: Some(network), transaction_pool, + inherents_pool, signal: Some(signal), keystore, config, exit, _rpc: Box::new(rpc), _telemetry: telemetry, + _offchain_workers: offchain_workers, }) } @@ -320,6 +350,7 @@ impl Service { } } + /// return a shared instance of Telemtry (if enabled) pub fn telemetry(&self) -> Option> { self._telemetry.as_ref().map(|t| t.clone()) } @@ -336,11 +367,16 @@ impl Service where Components: components::Components { self.network.as_ref().expect("self.network always Some").clone() } - /// Get shared extrinsic pool instance. + /// Get shared transaction pool instance. pub fn transaction_pool(&self) -> Arc> { self.transaction_pool.clone() } + /// Get shared inherents pool instance. + pub fn inherents_pool(&self) -> Arc>> { + self.inherents_pool.clone() + } + /// Get shared keystore. pub fn keystore(&self) -> &Keystore { &self.keystore diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs index 26ba01697cfc5dff269dbbd48844872939cf8026..dcdae582fab3652b4c68f1085c88c73a377cee6c 100644 --- a/core/service/test/src/lib.rs +++ b/core/service/test/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,12 +20,12 @@ use std::iter; use std::sync::Arc; use std::net::Ipv4Addr; use std::time::Duration; +use std::collections::HashMap; use log::info; use futures::{Future, Stream}; use tempdir::TempDir; use tokio::runtime::Runtime; use tokio::timer::Interval; -use primitives::blake2_256; use service::{ ServiceFactory, Configuration, @@ -34,8 +34,8 @@ use service::{ Roles, FactoryExtrinsic, }; -use network::{Protocol, SyncProvider, ManageNetwork}; -use network::config::{NetworkConfiguration, NonReservedPeerMode}; +use network::{multiaddr, SyncProvider, ManageNetwork}; +use network::config::{NetworkConfiguration, NodeKeyConfig, Secret, NonReservedPeerMode}; use sr_primitives::traits::As; use sr_primitives::generic::BlockId; use consensus::{ImportBlock, BlockImport}; @@ -64,10 +64,6 @@ impl TestNet { } } -fn node_private_key_string(index: u32) -> String { - format!("N{}", index) -} - fn node_config ( index: u32, spec: &FactoryChainSpec, @@ -83,23 +79,27 @@ fn node_config ( keys.push(seed); } + let config_path = Some(String::from(root.join("network").to_str().unwrap())); + let net_config_path = config_path.clone(); + let network_config = NetworkConfiguration { - config_path: Some(root.join("network").to_str().unwrap().into()), - net_config_path: Some(root.join("network").to_str().unwrap().into()), + config_path, + net_config_path, listen_addresses: vec! [ - iter::once(Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) - .chain(iter::once(Protocol::Tcp(base_port + index as u16))) + iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) + .chain(iter::once(multiaddr::Protocol::Tcp(base_port + index as u16))) .collect() ], public_addresses: vec![], boot_nodes: vec![], - use_secret: Some(blake2_256(node_private_key_string(index).as_bytes())), + node_key: NodeKeyConfig::Ed25519(Secret::New), in_peers: 50, out_peers: 450, reserved_nodes: vec![], non_reserved_mode: NonReservedPeerMode::Accept, client_version: "network/test/0.1".to_owned(), node_name: "unknown".to_owned(), + enable_mdns: false, }; Configuration { @@ -122,6 +122,9 @@ fn node_config ( rpc_ws: None, telemetry_endpoints: None, default_heap_pages: None, + offchain_worker: false, + force_authoring: false, + disable_grandpa: false, } } @@ -226,7 +229,7 @@ where info!("Generating #{}", i); } let import_data = block_factory(&first_service); - first_service.client().import_block(import_data, None).expect("Error importing test block"); + first_service.client().import_block(import_data, HashMap::new()).expect("Error importing test block"); } first_service.network().node_id().unwrap() }; diff --git a/core/sr-api-macros/benches/bench.rs b/core/sr-api-macros/benches/bench.rs index 85ea3d6f88dd3046893617570eba761be89b6724..f4677217897924ef532adca0f2bac520f569c2ee 100644 --- a/core/sr-api-macros/benches/bench.rs +++ b/core/sr-api-macros/benches/bench.rs @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use criterion::Criterion; +use criterion::{Criterion, criterion_group, criterion_main}; use test_client::runtime::TestAPI; use runtime_primitives::{generic::BlockId, traits::ProvideRuntimeApi}; +use state_machine::ExecutionStrategy; fn sr_api_benchmark(c: &mut Criterion) { c.bench_function("add one with same runtime api", |b| { @@ -50,6 +51,18 @@ fn sr_api_benchmark(c: &mut Criterion) { b.iter_with_large_drop(|| client.runtime_api().benchmark_vector_add_one(&block_id, &data)) }); + + c.bench_function("calling function by function pointer in wasm", |b| { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::AlwaysWasm); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + b.iter(|| client.runtime_api().benchmark_indirect_call(&block_id).unwrap()) + }); + + c.bench_function("calling function in wasm", |b| { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::AlwaysWasm); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + b.iter(|| client.runtime_api().benchmark_direct_call(&block_id).unwrap()) + }); } criterion_group!(benches, sr_api_benchmark); diff --git a/core/sr-api-macros/src/compile_fail_tests.rs b/core/sr-api-macros/src/compile_fail_tests.rs index 4f92e541285f72a9092a2a6dfbc2d2ccb8380c98..e562f8b2fe598a7e7a994b3c46748ec0952a0ad6 100644 --- a/core/sr-api-macros/src/compile_fail_tests.rs +++ b/core/sr-api-macros/src/compile_fail_tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-api-macros/src/decl_runtime_apis.rs b/core/sr-api-macros/src/decl_runtime_apis.rs index b320f4e06d7f9c411291205567e7ad053808d708..9e4c38f0878e5dad195db76d5a121448c9cb830b 100644 --- a/core/sr-api-macros/src/decl_runtime_apis.rs +++ b/core/sr-api-macros/src/decl_runtime_apis.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,7 +21,6 @@ use crate::utils::{ generate_method_runtime_api_impl_name }; -use proc_macro; use proc_macro2::{TokenStream, Span}; use quote::quote; @@ -52,7 +51,7 @@ const API_VERSION_ATTRIBUTE: &str = "api_version"; /// Is used when the function signature changed between different versions of a trait. /// This attribute should be placed on the old signature of the function. const CHANGED_IN_ATTRIBUTE: &str = "changed_in"; -/// All attributes that we support in the declaratio of a runtime api trait. +/// All attributes that we support in the declaration of a runtime api trait. const SUPPORTED_ATTRIBUTE_NAMES: &[&str] = &[ CORE_TRAIT_ATTRIBUTE, API_VERSION_ATTRIBUTE, CHANGED_IN_ATTRIBUTE ]; @@ -128,7 +127,7 @@ fn return_type_is_using_block(ty: &ReturnType) -> bool { visitor.result } -/// Replace all occurences of `Block` with `NodeBlock` +/// Replace all occurrences of `Block` with `NodeBlock` struct ReplaceBlockWithNodeBlock {} impl Fold for ReplaceBlockWithNodeBlock { @@ -141,13 +140,13 @@ impl Fold for ReplaceBlockWithNodeBlock { } } -/// Replace all occurences of `Block` with `NodeBlock` +/// Replace all occurrences of `Block` with `NodeBlock` fn fn_arg_replace_block_with_node_block(fn_arg: FnArg) -> FnArg { let mut replace = ReplaceBlockWithNodeBlock {}; fold::fold_fn_arg(&mut replace, fn_arg) } -/// Replace all occurences of `Block` with `NodeBlock` +/// Replace all occurrences of `Block` with `NodeBlock` fn return_type_replace_block_with_node_block(return_type: ReturnType) -> ReturnType { let mut replace = ReplaceBlockWithNodeBlock {}; fold::fold_return_type(&mut replace, return_type) @@ -163,7 +162,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { let trait_ = &decl.ident; let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); - // Auxilariy function that is used to convert between types that use different block types. + // Auxiliary function that is used to convert between types that use different block types. // The function expects that both a convertable by encoding the one and decoding the other. result.push(quote!( #[cfg(any(feature = "std", test))] diff --git a/core/sr-api-macros/src/impl_runtime_apis.rs b/core/sr-api-macros/src/impl_runtime_apis.rs index c6fb28b8020e89b50e8fd36228932afc9947f880..b5dd3f21c5c468c5b5e7e91d3bc43f2c4472ba52 100644 --- a/core/sr-api-macros/src/impl_runtime_apis.rs +++ b/core/sr-api-macros/src/impl_runtime_apis.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,7 +21,6 @@ use crate::utils::{ return_type_extract_type }; -use proc_macro; use proc_macro2::{Span, TokenStream}; use quote::quote; @@ -272,7 +271,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result + 'static> { call: &'static C, commit_on_success: ::std::cell::RefCell, - initialised_block: ::std::cell::RefCell>, + initialized_block: ::std::cell::RefCell>, changes: ::std::cell::RefCell<#crate_::runtime_api::OverlayedChanges>, } @@ -321,7 +320,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result Result Result { } -/// Auxilariy data structure that is used to convert `impl Api for Runtime` to +/// Auxiliary data structure that is used to convert `impl Api for Runtime` to /// `impl Api for RuntimeApi`. /// This requires us to replace the runtime `Block` with the node `Block`, /// `impl Api for Runtime` with `impl Api for RuntimeApi` and replace the method implementations @@ -470,7 +469,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { }; let context_arg: syn::FnArg = parse_quote!( context: #crate_::runtime_api::ExecutionContext ); - + // Rewrite the input parameters. input.sig.decl.inputs = parse_quote! { &self, at: &#block_id, #context_arg, params: Option<( #( #param_types ),* )>, params_encoded: Vec @@ -484,7 +483,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>> ); - // Generate the new method implementation that calls into the runime. + // Generate the new method implementation that calls into the runtime. parse_quote!( { // Get the error to the user (if we have one). @@ -616,7 +615,7 @@ fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result { pub fn impl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream { // Parse all impl blocks let RuntimeApiImpls { impls: api_impls } = parse_macro_input!(input as RuntimeApiImpls); - + let dispatch_impl = unwrap_or_error(generate_dispatch_function(&api_impls)); let api_impls_for_runtime = unwrap_or_error(generate_api_impl_for_runtime(&api_impls)); let base_runtime_api = unwrap_or_error(generate_runtime_api_base_structures(&api_impls)); diff --git a/core/sr-api-macros/src/lib.rs b/core/sr-api-macros/src/lib.rs index 7c042eef250340ce9089a422ae66f77f2b1ded9b..72e143eb1a0088a2e16dcae9ae955b6c4a3faf43 100644 --- a/core/sr-api-macros/src/lib.rs +++ b/core/sr-api-macros/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -155,7 +155,7 @@ pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { /// /// To support versioning of the traits, the macro supports the attribute `#[api_version(1)]`. /// The attribute supports any `u32` as version. By default, each trait is at version `1`, if no -/// version is provided. We also support chaning the signature of a method. This signature +/// version is provided. We also support changing the signature of a method. This signature /// change is highlighted with the `#[changed_in(2)]` attribute above a method. A method that is /// tagged with this attribute is callable by the name `METHOD_before_version_VERSION`. This /// method will only support calling into wasm, trying to call into native will fail (change the diff --git a/core/sr-api-macros/src/utils.rs b/core/sr-api-macros/src/utils.rs index fd9964b59f39c11c1a75a305445111d08d723631..e593e41ebedd4519f4bc2773d20bcd34df8a914b 100644 --- a/core/sr-api-macros/src/utils.rs +++ b/core/sr-api-macros/src/utils.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -54,7 +54,7 @@ pub fn generate_hidden_includes(unique_id: &'static str) -> TokenStream { }.into() } -/// Generates the access to the `subtrate_client` crate. +/// Generates the access to the `substrate_client` crate. pub fn generate_crate_access(unique_id: &'static str) -> TokenStream { if env::var("CARGO_PKG_NAME").unwrap() == "substrate-client" { quote!( crate ) diff --git a/core/sr-api-macros/tests/decl_and_impl.rs b/core/sr-api-macros/tests/decl_and_impl.rs index c7226065591edc8fef6b41c66bb4497cf2eea6be..a8b31561238ae53c54731aed4fa3c1c9ab7472a3 100644 --- a/core/sr-api-macros/tests/decl_and_impl.rs +++ b/core/sr-api-macros/tests/decl_and_impl.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use runtime_primitives::traits::{GetNodeBlockType, Block as BlockT, AuthorityIdFor}; +use runtime_primitives::traits::{GetNodeBlockType, Block as BlockT}; use runtime_primitives::generic::BlockId; use client::runtime_api::{self, RuntimeApiInfo}; use client::{error::Result, decl_runtime_apis, impl_runtime_apis}; @@ -68,13 +68,10 @@ impl_runtime_apis! { fn version() -> runtime_api::RuntimeVersion { unimplemented!() } - fn authorities() -> Vec> { - unimplemented!() - } fn execute_block(_: Block) { unimplemented!() } - fn initialise_block(_: &::Header) { + fn initialize_block(_: &::Header) { unimplemented!() } } diff --git a/core/sr-io/Cargo.toml b/core/sr-io/Cargo.toml index 01907832f8a25f632b908e63ef7decbe3a4c3317..01555a6f473c3e9cf04178c0a46bec42134c8779 100644 --- a/core/sr-io/Cargo.toml +++ b/core/sr-io/Cargo.toml @@ -11,11 +11,11 @@ rustc_version = "0.2" [dependencies] rstd = { package = "sr-std", path = "../sr-std", default-features = false } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } -parity-codec = { version = "3.1", default-features = false } -hash-db = { version = "0.11", default-features = false } +parity-codec = { version = "3.2", default-features = false } +hash-db = { version = "0.12", default-features = false } libsecp256k1 = { version = "0.2.1", optional = true } tiny-keccak = { version = "1.4.2", optional = true } -environmental = { version = "~1.0", optional = true } +environmental = { version = "1.0.1", optional = true } substrate-state-machine = { path = "../state-machine", optional = true } trie = { package = "substrate-trie", path = "../trie", optional = true } @@ -35,3 +35,4 @@ std = [ ] nightly = [] strict = [] +wasm-nice-panic-message = [] diff --git a/core/sr-io/build.rs b/core/sr-io/build.rs index 62ddacbbf4f993f3d58b036391e0ae0e94dc1b5a..5b5d06b65a2531b59ef0180a3761904885a5db2c 100644 --- a/core/sr-io/build.rs +++ b/core/sr-io/build.rs @@ -3,7 +3,7 @@ use rustc_version::{version, version_meta, Channel}; fn main() { - // Assert we haven't travelled back in time + // Assert we haven't traveled back in time assert!(version().unwrap().major >= 1); // Set cfg flags depending on release channel diff --git a/core/sr-io/src/lib.rs b/core/sr-io/src/lib.rs index aa446f74a5f0d2af3aca110a130227e30037845e..6a00e6ca2734d1b73fe7ec6e7063b9bf2e03b3f2 100644 --- a/core/sr-io/src/lib.rs +++ b/core/sr-io/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-io/with_std.rs b/core/sr-io/with_std.rs index 562e349ceda79b6464a96f7df6ee87d771b702a9..1f4ce56fc9b0ed5cda73c6c7513ce34e978cf6fe 100644 --- a/core/sr-io/with_std.rs +++ b/core/sr-io/with_std.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,19 +17,30 @@ #[doc(hidden)] pub use parity_codec as codec; // re-export hashing functions. -pub use primitives::{blake2_256, twox_128, twox_256, ed25519, Blake2Hasher, sr25519}; +pub use primitives::{ + blake2_256, twox_128, twox_256, ed25519, Blake2Hasher, sr25519, + Pair +}; pub use tiny_keccak::keccak256 as keccak_256; // Switch to this after PoC-3 // pub use primitives::BlakeHasher; -pub use substrate_state_machine::{Externalities, TestExternalities}; +pub use substrate_state_machine::{Externalities, BasicExternalities, TestExternalities}; -use environmental::{environmental, thread_local_impl}; -use primitives::hexdisplay::HexDisplay; -use primitives::H256; +use environmental::environmental; +use primitives::{hexdisplay::HexDisplay, H256}; use hash_db::Hasher; +#[cfg(feature = "std")] +use std::collections::HashMap; + environmental!(ext: trait Externalities); +/// A set of key value pairs for storage. +pub type StorageOverlay = HashMap, Vec>; + +/// A set of key value pairs for children storage; +pub type ChildrenStorageOverlay = HashMap, StorageOverlay>; + /// Get `key` from storage and return a `Vec`, empty if there's a problem. pub fn storage(key: &[u8]) -> Option> { ext::with(|ext| ext.storage(key).map(|s| s.to_vec())) @@ -153,6 +164,7 @@ pub fn storage_changes_root(parent_hash: [u8; 32], parent_num: u64) -> Option

(input: &[&[u8]]) -> H::Out where H: Hasher, @@ -186,17 +198,17 @@ where /// Verify a ed25519 signature. pub fn ed25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { - ed25519::verify(sig, msg, pubkey) + ed25519::Pair::verify_weak(sig, msg, pubkey) } /// Verify an sr25519 signature. pub fn sr25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { - sr25519::verify(sig, msg, pubkey) + sr25519::Pair::verify_weak(sig, msg, pubkey) } /// Verify and recover a SECP256k1 ECDSA signature. /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. -/// - returns `Err` if the signatue is bad, otherwise the 64-byte pubkey (doesn't include the 0x04 prefix). +/// - returns `Err` if the signature is bad, otherwise the 64-byte pubkey (doesn't include the 0x04 prefix). pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> { let rs = secp256k1::Signature::parse_slice(&sig[0..64]).map_err(|_| EcdsaVerifyError::BadRS)?; let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8).map_err(|_| EcdsaVerifyError::BadV)?; @@ -206,6 +218,14 @@ pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64 Ok(res) } +/// Submit extrinsic. +pub fn submit_extrinsic(data: &T) { + ext::with(|ext| ext + .submit_extrinsic(codec::Encode::encode(data)) + .expect("submit_extrinsic can be called only in offchain worker context") + ).expect("submit_extrinsic cannot be called outside of an Externalities-provided environment.") +} + /// Execute the given closure with global function available whose functionality routes into the /// externalities `ext`. Forwards the value that the closure returns. // NOTE: need a concrete hasher here due to limitations of the `environmental!` macro, otherwise a type param would have been fine I think. @@ -213,6 +233,17 @@ pub fn with_externalities R>(ext: &mut Externalities R>(storage: &mut StorageOverlay, f: F) -> R { + let mut alt_storage = Default::default(); + rstd::mem::swap(&mut alt_storage, storage); + let mut ext: BasicExternalities = alt_storage.into(); + let r = ext::using(&mut ext, f); + *storage = ext.into(); + r +} + /// Trait for things which can be printed. pub trait Printable { fn print(self); @@ -248,7 +279,7 @@ mod std_tests { #[test] fn storage_works() { - let mut t = TestExternalities::::default(); + let mut t = BasicExternalities::default(); assert!(with_externalities(&mut t, || { assert_eq!(storage(b"hello"), None); set_storage(b"hello", b"world"); @@ -258,7 +289,7 @@ mod std_tests { true })); - t = TestExternalities::new(map![b"foo".to_vec() => b"bar".to_vec()]); + t = BasicExternalities::new(map![b"foo".to_vec() => b"bar".to_vec()]); assert!(!with_externalities(&mut t, || { assert_eq!(storage(b"hello"), None); @@ -269,7 +300,7 @@ mod std_tests { #[test] fn read_storage_works() { - let mut t = TestExternalities::::new(map![ + let mut t = BasicExternalities::new(map![ b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec() ]); @@ -285,7 +316,7 @@ mod std_tests { #[test] fn clear_prefix_works() { - let mut t = TestExternalities::::new(map![ + let mut t = BasicExternalities::new(map![ b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), diff --git a/core/sr-io/without_std.rs b/core/sr-io/without_std.rs index 5687812830bb486146cf2cd26431ca8ed9096c89..e4e32bd17d5811d6c98aa4e14ce39f1196a81c17 100644 --- a/core/sr-io/without_std.rs +++ b/core/sr-io/without_std.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,19 +20,27 @@ pub use parity_codec as codec; pub use rstd; pub use rstd::{mem, slice}; -use core::intrinsics; -use rstd::vec::Vec; +use core::{intrinsics, panic::PanicInfo}; +use rstd::{vec::Vec, cell::Cell}; use hash_db::Hasher; use primitives::Blake2Hasher; #[panic_handler] #[no_mangle] -pub fn panic(info: &::core::panic::PanicInfo) -> ! { +pub fn panic(info: &PanicInfo) -> ! { unsafe { - if let Some(loc) = info.location() { - ext_print_utf8(loc.file().as_ptr() as *const u8, loc.file().len() as u32); - ext_print_num(loc.line() as u64); - ext_print_num(loc.column() as u64); + #[cfg(feature = "wasm-nice-panic-message")] + { + let message = rstd::alloc::format!("{}", info); + extern_functions_host_impl::ext_print_utf8(message.as_ptr() as *const u8, message.len() as u32); + } + #[cfg(not(feature = "wasm-nice-panic-message"))] + { + if let Some(loc) = info.location() { + extern_functions_host_impl::ext_print_utf8(loc.file().as_ptr() as *const u8, loc.file().len() as u32); + extern_functions_host_impl::ext_print_num(loc.line() as u64); + extern_functions_host_impl::ext_print_num(loc.column() as u64); + } } intrinsics::abort() } @@ -43,41 +51,223 @@ pub extern fn oom(_: ::core::alloc::Layout) -> ! { static OOM_MSG: &str = "Runtime memory exhausted. Aborting"; unsafe { - ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32); + extern_functions_host_impl::ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32); intrinsics::abort(); } } +/// The state of an exchangeable function. +#[derive(Clone, Copy)] +enum ExchangeableFunctionState { + Original, + Replaced, +} + +/// A function which implementation can be exchanged. +/// +/// Internally this works by swapping function pointers. +pub struct ExchangeableFunction(Cell<(T, ExchangeableFunctionState)>); + +impl ExchangeableFunction { + /// Create a new instance of `ExchangeableFunction`. + pub const fn new(impl_: T) -> Self { + Self(Cell::new((impl_, ExchangeableFunctionState::Original))) + } +} + +impl ExchangeableFunction { + /// Replace the implementation with `new_impl`. + /// + /// # Panics + /// + /// Panics when trying to replace an already replaced implementation. + /// + /// # Returns + /// + /// Returns the original implementation wrapped in [`RestoreImplementation`]. + pub fn replace_implementation(&'static self, new_impl: T) -> RestoreImplementation { + if let ExchangeableFunctionState::Replaced = self.0.get().1 { + panic!("Trying to replace an already replaced implementation!") + } + + let old = self.0.replace((new_impl, ExchangeableFunctionState::Replaced)); + + RestoreImplementation(self, Some(old.0)) + } + + /// Restore the original implementation. + fn restore_orig_implementation(&self, orig: T) { + self.0.set((orig, ExchangeableFunctionState::Original)); + } + + /// Returns the internal function pointer. + pub fn get(&self) -> T { + self.0.get().0 + } +} + +// WASM does not support threads, so this is safe; qed. +unsafe impl Sync for ExchangeableFunction {} + +/// Restores a function implementation on drop. +/// +/// Stores a static reference to the function object and the original implementation. +pub struct RestoreImplementation(&'static ExchangeableFunction, Option); + +impl Drop for RestoreImplementation { + fn drop(&mut self) { + self.0.restore_orig_implementation(self.1.take().expect("Value is only taken on drop; qed")); + } +} + +/// Declare extern functions +macro_rules! extern_functions { + ( + $( + $( #[$attr:meta] )* + fn $name:ident ( $( $arg:ident : $arg_ty:ty ),* ) $( -> $ret:ty )?; + )* + ) => { + $( + $( #[$attr] )* + #[allow(non_upper_case_globals)] + pub static $name: ExchangeableFunction $ret )?> = + ExchangeableFunction::new(extern_functions_host_impl::$name); + )* + + /// The exchangeable extern functions host implementations. + mod extern_functions_host_impl { + $( + pub unsafe fn $name ( $( $arg : $arg_ty ),* ) $( -> $ret )? { + implementation::$name ( $( $arg ),* ) + } + )* + + mod implementation { + extern "C" { + $( + pub fn $name ( $( $arg : $arg_ty ),* ) $( -> $ret )?; + )* + } + } + } + }; +} + /// Host functions, provided by the executor. /// A WebAssembly runtime module would "import" these to access the execution environment /// (most importantly, storage) or perform heavy hash calculations. /// See also "ext_" functions in sr-sandbox and sr-std -extern "C" { - /// Printing, useful for debugging +extern_functions! { + /// Host functions for printing, useful for debugging. fn ext_print_utf8(utf8_data: *const u8, utf8_len: u32); fn ext_print_hex(data: *const u8, len: u32); fn ext_print_num(value: u64); - /// Host storage access and verification + /// Set value for key in storage. fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); - fn ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); + /// Remove key and value from storage. fn ext_clear_storage(key_data: *const u8, key_len: u32); - fn ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32); + /// Checks if the given key exists in the storage. + /// + /// # Returns + /// + /// - `1` if the value exists. + /// - `0` if the value does not exists. fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32; - fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32; + /// Remove storage entries which key starts with given prefix. fn ext_clear_prefix(prefix_data: *const u8, prefix_len: u32); - fn ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32); - /// Host-side result allocation + /// Gets the value of the given key from storage. + /// + /// The host allocates the memory for storing the value. + /// + /// # Returns + /// + /// - `0` if no value exists to the given key. `written_out` is set to `u32::max_value()`. + /// + /// - Otherwise, pointer to the value in memory. `written_out` contains the length of the value. fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; - /// Host-side result allocation - fn ext_get_allocated_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; + /// Gets the value of the given key from storage. + /// + /// The value is written into `value` starting at `value_offset`. + /// + /// If the value length is greater than `value_len - value_offset`, the value is written partially. + /// + /// # Returns + /// + /// - `u32::max_value()` if the value does not exists. + /// + /// - Otherwise, the number of bytes written for value. fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32; - fn ext_get_child_storage_into(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32; + /// Gets the trie root of the storage. fn ext_storage_root(result: *mut u8); - /// Host-side result allocation - fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8; + /// Get the change trie root of the current storage overlay at a block with given parent. + /// + /// # Returns + /// + /// - `1` if the change trie root was found. + /// - `0` if the change trie root was not found. fn ext_storage_changes_root(parent_hash_data: *const u8, parent_hash_len: u32, parent_num: u64, result: *mut u8) -> u32; + /// A child storage function. + /// + /// See [`ext_set_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); + /// A child storage function. + /// + /// See [`ext_clear_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32); + /// A child storage function. + /// + /// See [`ext_exists_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32; + /// A child storage function. + /// + /// See [`ext_kill_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32); + /// A child storage function. + /// + /// See [`ext_get_allocated_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_get_allocated_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32, + written_out: *mut u32 + ) -> *mut u8; + /// A child storage function. + /// + /// See [`ext_get_storage_into`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_get_child_storage_into( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32, + value_data: *mut u8, + value_len: u32, + value_offset: u32 + ) -> u32; + /// Commits all changes and calculates the child-storage root. + /// + /// A child storage is used e.g. by a contract. + /// + /// # Returns + /// + /// - The pointer to the result vector and `written_out` contains its length. + fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8; + /// The current relay chain identifier. fn ext_chain_id() -> u64; @@ -93,6 +283,13 @@ extern "C" { fn ext_sr25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; /// Note: ext_secp256k1_ecdsa_recover returns 0 if the signature is correct, nonzero otherwise. fn ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32; + + //================================ + // Offchain-worker Context + //================================ + + /// Submit extrinsic. + fn ext_submit_extrinsic(data: *const u8, len: u32); } /// Ensures we use the right crypto when calling into native @@ -100,14 +297,14 @@ pub trait ExternTrieCrypto { fn enumerated_trie_root(values: &[&[u8]]) -> [u8; 32]; } -// Ensures we use a Blake2_256-flavoured Hasher when calling into native +// Ensures we use a Blake2_256-flavored Hasher when calling into native impl ExternTrieCrypto for Blake2Hasher { fn enumerated_trie_root(values: &[&[u8]]) -> [u8; 32] { let lengths = values.iter().map(|v| (v.len() as u32).to_le()).collect::>(); let values = values.iter().fold(Vec::new(), |mut acc, sl| { acc.extend_from_slice(sl); acc }); let mut result: [u8; 32] = Default::default(); unsafe { - ext_blake2_256_enumerated_trie_root( + ext_blake2_256_enumerated_trie_root.get()( values.as_ptr(), lengths.as_ptr(), lengths.len() as u32, @@ -122,7 +319,7 @@ impl ExternTrieCrypto for Blake2Hasher { pub fn storage(key: &[u8]) -> Option> { let mut length: u32 = 0; unsafe { - let ptr = ext_get_allocated_storage(key.as_ptr(), key.len() as u32, &mut length); + let ptr = ext_get_allocated_storage.get()(key.as_ptr(), key.len() as u32, &mut length); if length == u32::max_value() { None } else { @@ -138,7 +335,13 @@ pub fn storage(key: &[u8]) -> Option> { pub fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { let mut length: u32 = 0; unsafe { - let ptr = ext_get_allocated_child_storage(storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32, &mut length); + let ptr = ext_get_allocated_child_storage.get()( + storage_key.as_ptr(), + storage_key.len() as u32, + key.as_ptr(), + key.len() as u32, + &mut length + ); if length == u32::max_value() { None } else { @@ -153,7 +356,7 @@ pub fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { /// Set the storage of some particular key to Some value. pub fn set_storage(key: &[u8], value: &[u8]) { unsafe { - ext_set_storage( + ext_set_storage.get()( key.as_ptr(), key.len() as u32, value.as_ptr(), value.len() as u32 ); @@ -163,7 +366,7 @@ pub fn set_storage(key: &[u8], value: &[u8]) { /// Set the child storage of some particular key to Some value. pub fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { unsafe { - ext_set_child_storage( + ext_set_child_storage.get()( storage_key.as_ptr(), key.len() as u32, key.as_ptr(), key.len() as u32, value.as_ptr(), value.len() as u32 @@ -174,7 +377,7 @@ pub fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { /// Clear the storage of some particular key. pub fn clear_storage(key: &[u8]) { unsafe { - ext_clear_storage( + ext_clear_storage.get()( key.as_ptr(), key.len() as u32 ); } @@ -183,7 +386,7 @@ pub fn clear_storage(key: &[u8]) { /// Clear the storage of some particular key. pub fn clear_child_storage(storage_key: &[u8], key: &[u8]) { unsafe { - ext_clear_child_storage( + ext_clear_child_storage.get()( storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32 ); @@ -193,7 +396,7 @@ pub fn clear_child_storage(storage_key: &[u8], key: &[u8]) { /// Determine whether a particular key exists in storage. pub fn exists_storage(key: &[u8]) -> bool { unsafe { - ext_exists_storage( + ext_exists_storage.get()( key.as_ptr(), key.len() as u32 ) != 0 } @@ -202,7 +405,7 @@ pub fn exists_storage(key: &[u8]) -> bool { /// Determine whether a particular key exists in storage. pub fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { unsafe { - ext_exists_child_storage( + ext_exists_child_storage.get()( storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32 ) != 0 @@ -212,7 +415,7 @@ pub fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { /// Clear the storage entries key of which starts with the given prefix. pub fn clear_prefix(prefix: &[u8]) { unsafe { - ext_clear_prefix( + ext_clear_prefix.get()( prefix.as_ptr(), prefix.len() as u32 ); @@ -222,7 +425,7 @@ pub fn clear_prefix(prefix: &[u8]) { /// Clear an entire child storage. pub fn kill_child_storage(storage_key: &[u8]) { unsafe { - ext_kill_child_storage( + ext_kill_child_storage.get()( storage_key.as_ptr(), storage_key.len() as u32 ); @@ -233,10 +436,12 @@ pub fn kill_child_storage(storage_key: &[u8]) { /// the number of bytes that the key in storage was beyond the offset. pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { unsafe { - match ext_get_storage_into( - key.as_ptr(), key.len() as u32, - value_out.as_mut_ptr(), value_out.len() as u32, - value_offset as u32 + match ext_get_storage_into.get()( + key.as_ptr(), + key.len() as u32, + value_out.as_mut_ptr(), + value_out.len() as u32, + value_offset as u32, ) { none if none == u32::max_value() => None, length => Some(length as usize), @@ -248,7 +453,7 @@ pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Op /// the number of bytes that the key in storage was beyond the offset. pub fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { unsafe { - match ext_get_child_storage_into( + match ext_get_child_storage_into.get()( storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32, value_out.as_mut_ptr(), value_out.len() as u32, @@ -264,7 +469,7 @@ pub fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], pub fn storage_root() -> [u8; 32] { let mut result: [u8; 32] = Default::default(); unsafe { - ext_storage_root(result.as_mut_ptr()); + ext_storage_root.get()(result.as_mut_ptr()); } result } @@ -273,7 +478,7 @@ pub fn storage_root() -> [u8; 32] { pub fn child_storage_root(storage_key: &[u8]) -> Option> { let mut length: u32 = 0; unsafe { - let ptr = ext_child_storage_root(storage_key.as_ptr(), storage_key.len() as u32, &mut length); + let ptr = ext_child_storage_root.get()(storage_key.as_ptr(), storage_key.len() as u32, &mut length); if length == u32::max_value() { None } else { @@ -289,7 +494,7 @@ pub fn child_storage_root(storage_key: &[u8]) -> Option> { pub fn storage_changes_root(parent_hash: [u8; 32], parent_num: u64) -> Option<[u8; 32]> { let mut result: [u8; 32] = Default::default(); let is_set = unsafe { - ext_storage_changes_root(parent_hash.as_ptr(), parent_hash.len() as u32, parent_num, result.as_mut_ptr()) + ext_storage_changes_root.get()(parent_hash.as_ptr(), parent_hash.len() as u32, parent_num, result.as_mut_ptr()) }; if is_set != 0 { @@ -326,7 +531,7 @@ pub fn ordered_trie_root< /// The current relay chain identifier. pub fn chain_id() -> u64 { unsafe { - ext_chain_id() + ext_chain_id.get()() } } @@ -334,7 +539,7 @@ pub fn chain_id() -> u64 { pub fn blake2_256(data: &[u8]) -> [u8; 32] { let mut result: [u8; 32] = Default::default(); unsafe { - ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + ext_blake2_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } result } @@ -343,7 +548,7 @@ pub fn blake2_256(data: &[u8]) -> [u8; 32] { pub fn keccak_256(data: &[u8]) -> [u8; 32] { let mut result: [u8; 32] = Default::default(); unsafe { - ext_keccak_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + ext_keccak_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } result } @@ -352,7 +557,7 @@ pub fn keccak_256(data: &[u8]) -> [u8; 32] { pub fn twox_256(data: &[u8]) -> [u8; 32] { let mut result: [u8; 32] = Default::default(); unsafe { - ext_twox_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + ext_twox_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } result } @@ -361,7 +566,7 @@ pub fn twox_256(data: &[u8]) -> [u8; 32] { pub fn twox_128(data: &[u8]) -> [u8; 16] { let mut result: [u8; 16] = Default::default(); unsafe { - ext_twox_128(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + ext_twox_128.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } result } @@ -369,24 +574,24 @@ pub fn twox_128(data: &[u8]) -> [u8; 16] { /// Verify a ed25519 signature. pub fn ed25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { unsafe { - ext_ed25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0 + ext_ed25519_verify.get()(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0 } } /// Verify a sr25519 signature. pub fn sr25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { unsafe { - ext_sr25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0 + ext_sr25519_verify.get()(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0 } } /// Verify and recover a SECP256k1 ECDSA signature. /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. -/// - returns `None` if the signatue is bad, the 64-byte pubkey (doesn't include the 0x04 prefix). +/// - returns `None` if the signature is bad, the 64-byte pubkey (doesn't include the 0x04 prefix). pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> { let mut pubkey = [0u8; 64]; match unsafe { - ext_secp256k1_ecdsa_recover(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr()) + ext_secp256k1_ecdsa_recover.get()(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr()) } { 0 => Ok(pubkey), 1 => Err(EcdsaVerifyError::BadRS), @@ -396,6 +601,18 @@ pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64 } } +/// Submit extrinsic from the runtime. +/// +/// Depending on the kind of extrinsic it will either be: +/// 1. scheduled to be included in the next produced block (inherent) +/// 2. added to the pool and propagated (transaction) +pub fn submit_extrinsic(data: &T) { + let encoded_data = codec::Encode::encode(data); + unsafe { + ext_submit_extrinsic.get()(encoded_data.as_ptr(), encoded_data.len() as u32) + } +} + /// Trait for things which can be printed. pub trait Printable { fn print(self); @@ -404,7 +621,7 @@ pub trait Printable { impl<'a> Printable for &'a [u8] { fn print(self) { unsafe { - ext_print_hex(self.as_ptr(), self.len() as u32); + ext_print_hex.get()(self.as_ptr(), self.len() as u32); } } } @@ -412,14 +629,14 @@ impl<'a> Printable for &'a [u8] { impl<'a> Printable for &'a str { fn print(self) { unsafe { - ext_print_utf8(self.as_ptr() as *const u8, self.len() as u32); + ext_print_utf8.get()(self.as_ptr() as *const u8, self.len() as u32); } } } impl Printable for u64 { fn print(self) { - unsafe { ext_print_num(self); } + unsafe { ext_print_num.get()(self); } } } diff --git a/core/sr-primitives/Cargo.toml b/core/sr-primitives/Cargo.toml index 2a971c39416b1b4b8e905b3679d883ea7edbc5ab..565b9fb1e400aa1c533a2175e1bfe87a5fbd4ac7 100644 --- a/core/sr-primitives/Cargo.toml +++ b/core/sr-primitives/Cargo.toml @@ -9,11 +9,11 @@ num-traits = { version = "0.2", default-features = false } integer-sqrt = { version = "0.1.2" } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../primitives", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false } runtime_io = { package = "sr-io", path = "../sr-io", default-features = false } -log = {version = "0.4", optional = true } +log = { version = "0.4", optional = true } [dev-dependencies] serde_json = "1.0" diff --git a/core/sr-primitives/src/generic/block.rs b/core/sr-primitives/src/generic/block.rs index 1e6255c681597d5c02d22eeb7c10fb72d43383d2..5fb83a2a4f766251ca7908196148e89ade4a075e 100644 --- a/core/sr-primitives/src/generic/block.rs +++ b/core/sr-primitives/src/generic/block.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs index 4cf61e37e4cb2ffe6cb59f52bef069b4ecf3109e..c0548c26e598ea51ce692fe4402e2fdb74cb86da 100644 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-primitives/src/generic/digest.rs b/core/sr-primitives/src/generic/digest.rs index 243cf05164db569930fcb392a034ec20018ca9e6..8eed63900ffe89662e6c69fdafc5655a61e07c37 100644 --- a/core/sr-primitives/src/generic/digest.rs +++ b/core/sr-primitives/src/generic/digest.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,11 +21,10 @@ use serde_derive::Serialize; use rstd::prelude::*; +use crate::ConsensusEngineId; use crate::codec::{Decode, Encode, Codec, Input}; use crate::traits::{self, Member, DigestItem as DigestItemT, MaybeHash}; -use substrate_primitives::hash::H512 as Signature; - /// Generic header digest. #[derive(PartialEq, Eq, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] @@ -63,7 +62,8 @@ impl traits::Digest for Digest where /// provide opaque access to other items. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] -pub enum DigestItem { +#[allow(deprecated)] +pub enum DigestItem { /// System digest item announcing that authorities set has been changed /// in the block. Contains the new set of authorities. AuthoritiesChange(Vec), @@ -71,14 +71,17 @@ pub enum DigestItem { /// block. It is created for every block iff runtime supports changes /// trie creation. ChangesTrieRoot(Hash), + /// The old way to put a Seal on it. Deprecated. + #[deprecated] + Seal(u64, SealSignature), /// Put a Seal on it - Seal(u64, Signature), + Consensus(ConsensusEngineId, Vec), /// Any 'non-system' digest item, opaque to the native code. Other(Vec), } #[cfg(feature = "std")] -impl ::serde::Serialize for DigestItem { +impl ::serde::Serialize for DigestItem { fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { self.using_encoded(|bytes| { ::substrate_primitives::bytes::serialize(bytes, seq) @@ -91,16 +94,20 @@ impl ::serde::Serialize for DigestItem { +#[allow(deprecated)] +pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> { /// Reference to `DigestItem::AuthoritiesChange`. AuthoritiesChange(&'a [AuthorityId]), /// Reference to `DigestItem::ChangesTrieRoot`. ChangesTrieRoot(&'a Hash), + /// A deprecated sealed signature for testing + #[deprecated] + Seal(&'a u64, &'a SealSignature), /// A sealed signature for testing - Seal(&'a u64, &'a Signature), + Consensus(&'a ConsensusEngineId, &'a [u8]), /// Any 'non-system' digest item, opaque to the native code. /// Reference to `DigestItem::Other`. - Other(&'a Vec), + Other(&'a [u8]), } /// Type of the digest item. Used to gain explicit control over `DigestItem` encoding @@ -111,12 +118,13 @@ pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a> { #[derive(Encode, Decode)] enum DigestItemType { Other = 0, - AuthoritiesChange, - ChangesTrieRoot, - Seal, + AuthoritiesChange = 1, + ChangesTrieRoot = 2, + Seal = 3, + Consensus = 4, } -impl DigestItem { +impl DigestItem { /// Returns Some if `self` is a `DigestItem::Other`. pub fn as_other(&self) -> Option<&Vec> { match *self { @@ -126,11 +134,13 @@ impl DigestItem { } /// Returns a 'referencing view' for this digest item. - fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash, AuthorityId> { + #[allow(deprecated)] + fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { match *self { DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v), DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s), + DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s), DigestItem::Other(ref v) => DigestItemRef::Other(v), } } @@ -139,7 +149,8 @@ impl DigestItem { impl< Hash: Codec + Member, AuthorityId: Codec + Member + MaybeHash, -> traits::DigestItem for DigestItem { + SealSignature: Codec + Member, +> traits::DigestItem for DigestItem { type Hash = Hash; type AuthorityId = AuthorityId; @@ -152,13 +163,14 @@ impl< } } -impl Encode for DigestItem { +impl Encode for DigestItem { fn encode(&self) -> Vec { self.dref().encode() } } -impl Decode for DigestItem { +impl Decode for DigestItem { + #[allow(deprecated)] fn decode(input: &mut I) -> Option { let item_type: DigestItemType = Decode::decode(input)?; match item_type { @@ -169,9 +181,13 @@ impl Decode for DigestItem Decode::decode(input)?, )), DigestItemType::Seal => { - let vals: (u64, Signature) = Decode::decode(input)?; + let vals: (u64, SealSignature) = Decode::decode(input)?; Some(DigestItem::Seal(vals.0, vals.1)) }, + DigestItemType::Consensus => { + let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; + Some(DigestItem::Consensus(vals.0, vals.1)) + } DigestItemType::Other => Some(DigestItem::Other( Decode::decode(input)?, )), @@ -179,7 +195,7 @@ impl Decode for DigestItem } } -impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member> DigestItemRef<'a, Hash, AuthorityId> { +impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member, SealSignature: Codec + Member> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { /// Cast this digest item into `AuthoritiesChange`. pub fn as_authorities_change(&self) -> Option<&'a [AuthorityId]> { match *self { @@ -197,7 +213,8 @@ impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member> DigestItemRef<'a, Ha } } -impl<'a, Hash: Encode, AuthorityId: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId> { +#[allow(deprecated)] +impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId, SealSignature> { fn encode(&self) -> Vec { let mut v = Vec::new(); @@ -214,6 +231,10 @@ impl<'a, Hash: Encode, AuthorityId: Encode> Encode for DigestItemRef<'a, Hash, A DigestItemType::Seal.encode_to(&mut v); (val, sig).encode_to(&mut v); }, + DigestItemRef::Consensus(val, sig) => { + DigestItemType::Consensus.encode_to(&mut v); + (val, sig).encode_to(&mut v); + }, DigestItemRef::Other(val) => { DigestItemType::Other.encode_to(&mut v); val.encode_to(&mut v); @@ -227,8 +248,10 @@ impl<'a, Hash: Encode, AuthorityId: Encode> Encode for DigestItemRef<'a, Hash, A #[cfg(test)] mod tests { use super::*; + use substrate_primitives::hash::H512 as Signature; #[test] + #[allow(deprecated)] fn should_serialize_digest() { let digest = Digest { logs: vec![ diff --git a/core/sr-primitives/src/generic/era.rs b/core/sr-primitives/src/generic/era.rs index 9d2fe13793648cdba469a0dc1b3e115a6cf3aefb..e5a7b24f0cc5f3f975c6aaf80ec086456ed21e97 100644 --- a/core/sr-primitives/src/generic/era.rs +++ b/core/sr-primitives/src/generic/era.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -166,7 +166,7 @@ mod tests { } #[test] - fn era_initialisation_works() { + fn era_initialization_works() { assert_eq!(Era::mortal(64, 42), Era::Mortal(64, 42)); assert_eq!(Era::mortal(32768, 20000), Era::Mortal(32768, 20000)); assert_eq!(Era::mortal(200, 513), Era::Mortal(256, 1)); @@ -175,8 +175,8 @@ mod tests { } #[test] - fn quantised_clamped_era_initialisation_works() { - // clamp 1000000 to 65536, quantise 1000001 % 65536 to the nearest 4 + fn quantized_clamped_era_initialization_works() { + // clamp 1000000 to 65536, quantize 1000001 % 65536 to the nearest 4 assert_eq!(Era::mortal(1000000, 1000001), Era::Mortal(65536, 1000001 % 65536 / 4 * 4)); } diff --git a/core/sr-primitives/src/generic/header.rs b/core/sr-primitives/src/generic/header.rs index 91646e32a48692e27154619e8717e86a92ae4dd9..60ccd93b3ded8ccebeb7f8770d1ca649c4ff5354 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/core/sr-primitives/src/generic/header.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-primitives/src/generic/mod.rs b/core/sr-primitives/src/generic/mod.rs index 3c21a8232ccf60fbee95060d3d3e3cee24bcdd30..47ce3cb25184f7b2c44d4cb1d4837247d981027f 100644 --- a/core/sr-primitives/src/generic/mod.rs +++ b/core/sr-primitives/src/generic/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-primitives/src/generic/tests.rs b/core/sr-primitives/src/generic/tests.rs index 781f3f6329fc14db91483316a7353967aa806280..91fc8f3faf90486b67174463e2993a73caa10ac9 100644 --- a/core/sr-primitives/src/generic/tests.rs +++ b/core/sr-primitives/src/generic/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,12 +17,12 @@ //! Tests for the generic implementations of Extrinsic/Header/Block. use crate::codec::{Decode, Encode}; -use substrate_primitives::H256; +use substrate_primitives::{H256, H512}; use super::DigestItem; #[test] fn system_digest_item_encoding() { - let item = DigestItem::AuthoritiesChange::(vec![10, 20, 30]); + let item = DigestItem::AuthoritiesChange::(vec![10, 20, 30]); let encoded = item.encode(); assert_eq!(encoded, vec![ // type = DigestItemType::AuthoritiesChange @@ -35,13 +35,13 @@ fn system_digest_item_encoding() { 30, 0, 0, 0, ]); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } #[test] fn non_system_digest_item_encoding() { - let item = DigestItem::Other::(vec![10, 20, 30]); + let item = DigestItem::Other::(vec![10, 20, 30]); let encoded = item.encode(); assert_eq!(encoded, vec![ // type = DigestItemType::Other @@ -52,6 +52,6 @@ fn non_system_digest_item_encoding() { 10, 20, 30, ]); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index a0800fe502c93560df5c9089b1bdaed20c8ecd92..d6e0d60e2c218c255e5da9af987ce08e46b0d1e3 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs index 9c74995d0aba957e08e53a4e20714b43c8bb7471..243747092c49ca8100b6aa9a8490cb72c3cf775d 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index e7d104a1da83817353bcc13c4fbb7d8880cb4942..93eeb55884479281a77071953602553e576e012f 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 7a5739d8f122edce4ca5be892cad4dbc100508c1..5167e57072a2b2e93373a04f2dc8d3d8fbc787aa 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -27,10 +27,10 @@ pub use parity_codec as codec; pub use serde_derive; #[cfg(feature = "std")] -use std::collections::HashMap; +pub use runtime_io::{StorageOverlay, ChildrenStorageOverlay}; use rstd::prelude::*; -use substrate_primitives::hash::{H256, H512}; +use substrate_primitives::{ed25519, sr25519, hash::H512}; use codec::{Encode, Decode}; #[cfg(feature = "std")] @@ -85,19 +85,11 @@ macro_rules! create_runtime_str { #[cfg(feature = "std")] pub use serde::{Serialize, de::DeserializeOwned}; #[cfg(feature = "std")] -use serde_derive::{Serialize, Deserialize}; - -/// A set of key value pairs for storage. -#[cfg(feature = "std")] -pub type StorageOverlay = HashMap, Vec>; - -/// A set of key value pairs for children storage; -#[cfg(feature = "std")] -pub type ChildrenStorageOverlay = HashMap, StorageOverlay>; +pub use serde_derive::{Serialize, Deserialize}; /// Complex storage builder stuff. #[cfg(feature = "std")] -pub trait BuildStorage { +pub trait BuildStorage: Sized { /// Hash given slice. /// /// Default to xx128 hashing. @@ -107,7 +99,14 @@ pub trait BuildStorage { r } /// Build the storage out of this builder. - fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String>; + fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { + let mut storage = Default::default(); + let mut child_storage = Default::default(); + self.assimilate_storage(&mut storage, &mut child_storage)?; + Ok((storage, child_storage)) + } + /// Assimilate the storage for this module into pre-existing overlays. + fn assimilate_storage(self, storage: &mut StorageOverlay, child_storage: &mut ChildrenStorageOverlay) -> Result<(), String>; } #[cfg(feature = "std")] @@ -115,8 +114,15 @@ impl BuildStorage for StorageOverlay { fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { Ok((self, Default::default())) } + fn assimilate_storage(self, storage: &mut StorageOverlay, _child_storage: &mut ChildrenStorageOverlay) -> Result<(), String> { + storage.extend(self); + Ok(()) + } } +/// Consensus engine unique ID. +pub type ConsensusEngineId = [u8; 4]; + /// Permill is parts-per-million (i.e. after multiplying by this, divide by 1000000). #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] @@ -248,55 +254,112 @@ impl From> for Perbill { } } -/// Ed25519 signature verify. -#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -pub struct Ed25519Signature(pub H512); +/// PerU128 is parts-per-u128-max-value. It stores a value between 0 and 1 in fixed point and +/// provides a means to multiply some other value by that. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] +pub struct PerU128(u128); + +const U128: u128 = u128::max_value(); -impl Verify for Ed25519Signature { - type Signer = H256; - fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { - runtime_io::ed25519_verify((self.0).as_fixed_bytes(), msg.get(), &signer.as_bytes()) +impl PerU128 { + /// Nothing. + pub fn zero() -> Self { Self(0) } + + /// Everything. + pub fn one() -> Self { Self(U128) } + + /// Construct new instance where `x` is parts in u128::max_value. Equal to x/U128::max_value. + pub fn from_max_value(x: u128) -> Self { Self(x) } + + /// Construct new instance where `x` is denominator and the nominator is 1. + pub fn from_xth(x: u128) -> Self { Self(U128/x.max(1)) } +} + +impl ::rstd::ops::Deref for PerU128 { + type Target = u128; + + fn deref(&self) -> &u128 { + &self.0 + } +} + +impl codec::CompactAs for PerU128 { + type As = u128; + fn encode_as(&self) -> &u128 { + &self.0 + } + fn decode_from(x: u128) -> PerU128 { + Self(x) } } -impl From for Ed25519Signature { - fn from(h: H512) -> Ed25519Signature { - Ed25519Signature(h) +impl From> for PerU128 { + fn from(x: codec::Compact) -> PerU128 { + x.0 } } -/// Sr25519 signature verify. -#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] +/// Signature verify that can work with any known signature types.. +#[derive(Eq, PartialEq, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub enum MultiSignature { + /// An Ed25519 signature. + Ed25519(ed25519::Signature), + /// An Sr25519 signature. + Sr25519(sr25519::Signature), +} + +impl Default for MultiSignature { + fn default() -> Self { + MultiSignature::Ed25519(Default::default()) + } +} + +/// Public key for any known crypto algorithm. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -pub struct Sr25519Signature(pub H512); +pub enum MultiSigner { + /// An Ed25519 identity. + Ed25519(ed25519::Public), + /// An Sr25519 identity. + Sr25519(sr25519::Public), +} -impl Verify for Sr25519Signature { - type Signer = H256; - fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { - runtime_io::sr25519_verify((self.0).as_fixed_bytes(), msg.get(), &signer.as_bytes()) +impl Default for MultiSigner { + fn default() -> Self { + MultiSigner::Ed25519(Default::default()) } } -impl From for Sr25519Signature { - fn from(h: H512) -> Sr25519Signature { - Sr25519Signature(h) +impl Verify for MultiSignature { + type Signer = MultiSigner; + fn verify>(&self, msg: L, signer: &Self::Signer) -> bool { + match (self, signer) { + (MultiSignature::Ed25519(ref sig), &MultiSigner::Ed25519(ref who)) => sig.verify(msg, who), + (MultiSignature::Sr25519(ref sig), &MultiSigner::Sr25519(ref who)) => sig.verify(msg, who), + _ => false, + } } } -/// Context for executing a call into the runtime. -#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -#[repr(u8)] -pub enum ExecutionContext { - /// Context for general importing (including own blocks). - Importing, - /// Context used when syncing the blockchain. - Syncing, - /// Context used for block construction. - BlockConstruction, - /// Context used for other calls. - Other, +/// Signature verify that can work with any known signature types.. +#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub struct AnySignature(H512); + +impl Verify for AnySignature { + type Signer = sr25519::Public; + fn verify>(&self, mut msg: L, signer: &sr25519::Public) -> bool { + runtime_io::sr25519_verify(self.0.as_fixed_bytes(), msg.get(), &signer.0) || + runtime_io::ed25519_verify(self.0.as_fixed_bytes(), msg.get(), &signer.0) + } +} + +impl From for AnySignature { + fn from(s: sr25519::Signature) -> AnySignature { + AnySignature(s.0.into()) + } } #[derive(Eq, PartialEq, Clone, Copy, Decode)] @@ -369,6 +432,13 @@ pub fn verify_encoded_lazy(sig: &V, item: &T, signe /// Helper macro for `impl_outer_config` #[macro_export] macro_rules! __impl_outer_config_types { + ( + $concrete:ident $config:ident $snake:ident < $ignore:ident, $instance:path > $( $rest:tt )* + ) => { + #[cfg(any(feature = "std", test))] + pub type $config = $snake::GenesisConfig<$concrete, $instance>; + $crate::__impl_outer_config_types! {$concrete $($rest)*} + }; ( $concrete:ident $config:ident $snake:ident < $ignore:ident > $( $rest:tt )* ) => { @@ -396,12 +466,12 @@ macro_rules! __impl_outer_config_types { macro_rules! impl_outer_config { ( pub struct $main:ident for $concrete:ident { - $( $config:ident => $snake:ident $( < $generic:ident > )*, )* + $( $config:ident => $snake:ident $( < $generic:ident $(, $instance:path)? > )*, )* } ) => { - $crate::__impl_outer_config_types! { $concrete $( $config $snake $( < $generic > )* )* } + $crate::__impl_outer_config_types! { $concrete $( $config $snake $( < $generic $(, $instance)? > )* )* } #[cfg(any(feature = "std", test))] - #[derive(Serialize, Deserialize)] + #[derive($crate::serde_derive::Serialize, $crate::serde_derive::Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct $main { @@ -411,19 +481,13 @@ macro_rules! impl_outer_config { } #[cfg(any(feature = "std", test))] impl $crate::BuildStorage for $main { - fn build_storage(self) -> ::std::result::Result<($crate::StorageOverlay, $crate::ChildrenStorageOverlay), String> { - let mut top = $crate::StorageOverlay::new(); - let mut children = $crate::ChildrenStorageOverlay::new(); + fn assimilate_storage(self, top: &mut $crate::StorageOverlay, children: &mut $crate::ChildrenStorageOverlay) -> ::std::result::Result<(), String> { $( if let Some(extra) = self.$snake { - let (other_top, other_children) = extra.build_storage()?; - top.extend(other_top); - for (other_child_key, other_child_map) in other_children { - children.entry(other_child_key).or_default().extend(other_child_map); - } + extra.assimilate_storage(top, children)?; } )* - Ok((top, children)) + Ok(()) } } } @@ -449,7 +513,7 @@ macro_rules! impl_outer_log { ( $(#[$attr:meta])* pub enum $name:ident ($internal:ident: DigestItem<$( $genarg:ty ),*>) for $trait:ident { - $( $module:ident( $( $sitem:ident ),* ) ),* + $( $module:ident $(<$instance:path>)? ( $( $sitem:ident ),* ) ),* } ) => { /// Wrapper for all possible log entries for the `$trait` runtime. Provides binary-compatible @@ -462,13 +526,13 @@ macro_rules! impl_outer_log { /// All possible log entries for the `$trait` runtime. `Encode`/`Decode` implementations /// are auto-generated => it is not binary-compatible with `generic::DigestItem`. - #[derive(Clone, PartialEq, Eq, Encode, Decode)] + #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] #[cfg_attr(feature = "std", derive(Debug, $crate::serde_derive::Serialize))] $(#[$attr])* #[allow(non_camel_case_types)] pub enum InternalLog { $( - $module($module::Log<$trait>), + $module($module::Log<$trait $(, $instance)? >), )* } @@ -523,7 +587,7 @@ macro_rules! impl_outer_log { } impl $crate::codec::Decode for $name { - /// `generic::DigestItem` binray compatible decode. + /// `generic::DigestItem` binary compatible decode. fn decode(input: &mut I) -> Option { let gen: $crate::generic::DigestItem<$($genarg),*> = $crate::codec::Decode::decode(input)?; @@ -532,7 +596,7 @@ macro_rules! impl_outer_log { } impl $crate::codec::Encode for $name { - /// `generic::DigestItem` binray compatible encode. + /// `generic::DigestItem` binary compatible encode. fn encode(&self) -> Vec { match self.dref() { Some(dref) => dref.encode(), @@ -546,16 +610,16 @@ macro_rules! impl_outer_log { } $( - impl From<$module::Log<$trait>> for $name { + impl From<$module::Log<$trait $(, $instance)? >> for $name { /// Converts single module log item into `$name`. - fn from(x: $module::Log<$trait>) -> Self { + fn from(x: $module::Log<$trait $(, $instance)? >) -> Self { $name(x.into()) } } - impl From<$module::Log<$trait>> for InternalLog { + impl From<$module::Log<$trait $(, $instance)? >> for InternalLog { /// Converts single module log item into `$internal`. - fn from(x: $module::Log<$trait>) -> Self { + fn from(x: $module::Log<$trait $(, $instance)? >) -> Self { InternalLog::$module(x) } } @@ -563,12 +627,18 @@ macro_rules! impl_outer_log { }; } -/// Simple blob to hold an extrinsic without commiting to its format and ensure it is serialized +/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized /// correctly. #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] pub struct OpaqueExtrinsic(pub Vec); +#[cfg(feature = "std")] +impl std::fmt::Debug for OpaqueExtrinsic { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "{}", substrate_primitives::hexdisplay::HexDisplay::from(&self.0)) + } +} + #[cfg(feature = "std")] impl ::serde::Serialize for OpaqueExtrinsic { fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { @@ -584,7 +654,7 @@ impl traits::Extrinsic for OpaqueExtrinsic { #[cfg(test)] mod tests { - use substrate_primitives::hash::H256; + use substrate_primitives::hash::{H256, H512}; use crate::codec::{Encode, Decode}; use crate::traits::DigestItem; @@ -619,7 +689,7 @@ mod tests { } impl_outer_log! { - pub enum Log(InternalLog: DigestItem) for Runtime { + pub enum Log(InternalLog: DigestItem) for Runtime { a(AuthoritiesChange), b() } } @@ -639,16 +709,16 @@ mod tests { assert_eq!(auth_change, decoded_auth_change); // interpret regular item using `generic::DigestItem` - let generic_b1: super::generic::DigestItem = Decode::decode(&mut &encoded_b1[..]).unwrap(); + let generic_b1: super::generic::DigestItem = Decode::decode(&mut &encoded_b1[..]).unwrap(); match generic_b1 { super::generic::DigestItem::Other(_) => (), _ => panic!("unexpected generic_b1: {:?}", generic_b1), } // interpret system item using `generic::DigestItem` - let generic_auth_change: super::generic::DigestItem = Decode::decode(&mut &encoded_auth_change[..]).unwrap(); + let generic_auth_change: super::generic::DigestItem = Decode::decode(&mut &encoded_auth_change[..]).unwrap(); match generic_auth_change { - super::generic::DigestItem::AuthoritiesChange::(authorities) => assert_eq!(authorities, vec![100, 200, 300]), + super::generic::DigestItem::AuthoritiesChange::(authorities) => assert_eq!(authorities, vec![100, 200, 300]), _ => panic!("unexpected generic_auth_change: {:?}", generic_auth_change), } diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index a1c05aa7d763d773111aceec3cdb7c2ccfe46cd7..2711c0e623d62a171f249ab8adbe9bb998a77e07 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,30 +24,30 @@ use std::{fmt::Debug, ops::Deref, fmt}; use crate::codec::{Codec, Encode, Decode}; use crate::traits::{self, Checkable, Applyable, BlakeTwo256, Convert}; use crate::generic::DigestItem as GenDigestItem; - -pub use substrate_primitives::{H256, Ed25519AuthorityId}; +pub use substrate_primitives::H256; use substrate_primitives::U256; +use substrate_primitives::ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; /// Authority Id #[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct UintAuthorityId(pub u64); -impl Into for UintAuthorityId { - fn into(self) -> Ed25519AuthorityId { +impl Into for UintAuthorityId { + fn into(self) -> AuthorityId { let bytes: [u8; 32] = U256::from(self.0).into(); - Ed25519AuthorityId(bytes) + AuthorityId(bytes) } } /// Converter between u64 and the AuthorityId wrapper type. pub struct ConvertUintAuthorityId; -impl Convert for ConvertUintAuthorityId { - fn convert(a: u64) -> UintAuthorityId { - UintAuthorityId(a) +impl Convert> for ConvertUintAuthorityId { + fn convert(a: u64) -> Option { + Some(UintAuthorityId(a)) } } /// Digest item -pub type DigestItem = GenDigestItem; +pub type DigestItem = GenDigestItem; /// Header Digest #[derive(Default, PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 8050451b382cdaa30c074d259532cb00f7ca4fad..b62bc067b6b84c8e5374ae0af5aefdcacc9a9ffb 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,8 +23,7 @@ use runtime_io; #[cfg(feature = "std")] use serde::{Serialize, de::DeserializeOwned}; #[cfg(feature = "std")] use serde_derive::{Serialize, Deserialize}; -use substrate_primitives; -use substrate_primitives::Blake2Hasher; +use substrate_primitives::{self, Hasher, Blake2Hasher}; use crate::codec::{Codec, Encode, HasCompact}; pub use integer_sqrt::IntegerSquareRoot; pub use num_traits::{ @@ -56,6 +55,20 @@ pub trait Verify { fn verify>(&self, msg: L, signer: &Self::Signer) -> bool; } +impl Verify for substrate_primitives::ed25519::Signature { + type Signer = substrate_primitives::ed25519::Public; + fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + runtime_io::ed25519_verify(self.as_ref(), msg.get(), signer) + } +} + +impl Verify for substrate_primitives::sr25519::Signature { + type Signer = substrate_primitives::sr25519::Public; + fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + runtime_io::sr25519_verify(self.as_ref(), msg.get(), signer) + } +} + /// Some sort of check on the origin is performed by this object. pub trait EnsureOrigin { /// A return type. @@ -84,6 +97,8 @@ pub trait StaticLookup { type Target; /// Attempt a lookup. fn lookup(s: Self::Source) -> result::Result; + /// Convert from Target back to Source. + fn unlookup(t: Self::Target) -> Self::Source; } /// A lookup implementation returning the input value. @@ -93,6 +108,7 @@ impl StaticLookup for IdentityLookup< type Source = T; type Target = T; fn lookup(x: T) -> result::Result { Ok(x) } + fn unlookup(x: T) -> T { x } } impl Lookup for IdentityLookup { type Source = T; @@ -132,6 +148,45 @@ pub trait Convert { fn convert(a: A) -> B; } +impl Convert for () { + fn convert(_: A) -> B { Default::default() } +} + +/// A structure that converts the currency type into a lossy u64 +/// And back from u128 +pub struct CurrencyToVoteHandler; + +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { + if x >> 96 == 0 { + // Remove dust; divide by 2^32 + (x >> 32) as u64 + } else { + u64::max_value() + } + } +} + +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u128 { + // if it practically fits in u64 + if x >> 64 == 0 { + // Add zero dust; multiply by 2^32 + x << 32 + } + else { + // 0000_0000_FFFF_FFFF_FFFF_FFFF_0000_0000 + (u64::max_value() << 32) as u128 + } + } +} + +/// A structure that performs identity conversion. +pub struct Identity; +impl Convert for Identity { + fn convert(a: T) -> T { a } +} + /// Simple trait similar to `Into`, except that it can be used to convert numerics between each /// other. pub trait As { @@ -159,15 +214,6 @@ macro_rules! impl_numerics { impl_numerics!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); -/// A structure that performs identity conversion. -pub struct Identity; -impl Convert for Identity { - fn convert(a: T) -> T { a } -} -impl Convert for () { - fn convert(_: T) -> () { () } -} - /// A meta trait for arithmetic. pub trait SimpleArithmetic: Zero + One + IntegerSquareRoot + As + @@ -184,7 +230,7 @@ pub trait SimpleArithmetic: CheckedMul + CheckedDiv + Saturating + - PartialOrd + Ord + + PartialOrd + Ord + Bounded + HasCompact {} impl + Ord + + PartialOrd + Ord + Bounded + HasCompact > SimpleArithmetic for T {} @@ -235,56 +281,89 @@ impl > SimpleBitOps for T {} -/// The block finalisation trait. Implementing this lets you express what should happen +/// The block finalization trait. Implementing this lets you express what should happen /// for your module when the block is ending. -pub trait OnFinalise { - /// The block is being finalised. Implement to have something happen. - fn on_finalise(_n: BlockNumber) {} +pub trait OnFinalize { + /// The block is being finalized. Implement to have something happen. + fn on_finalize(_n: BlockNumber) {} } -impl OnFinalise for () {} +impl OnFinalize for () {} -/// The block initialisation trait. Implementing this lets you express what should happen +/// The block initialization trait. Implementing this lets you express what should happen /// for your module when the block is beginning (right before the first extrinsic is executed). -pub trait OnInitialise { - /// The block is being initialised. Implement to have something happen. - fn on_initialise(_n: BlockNumber) {} +pub trait OnInitialize { + /// The block is being initialized. Implement to have something happen. + fn on_initialize(_n: BlockNumber) {} +} + +impl OnInitialize for () {} + +/// Off-chain computation trait. +/// +/// Implementing this trait on a module allows you to perform a long-running tasks +/// that make validators generate extrinsics (either transactions or inherents) +/// with results of those long-running computations. +/// +/// NOTE: This function runs off-chain, so it can access the block state, +/// but cannot preform any alterations. +pub trait OffchainWorker { + /// This function is being called on every block. + /// + /// Implement this and use special `extern`s to generate transactions or inherents. + /// Any state alterations are lost and are not persisted. + fn generate_extrinsics(_n: BlockNumber) {} } -impl OnInitialise for () {} +impl OffchainWorker for () {} macro_rules! tuple_impl { ($one:ident,) => { - impl> OnFinalise for ($one,) { - fn on_finalise(n: Number) { - $one::on_finalise(n); + impl> OnFinalize for ($one,) { + fn on_finalize(n: Number) { + $one::on_finalize(n); } } - impl> OnInitialise for ($one,) { - fn on_initialise(n: Number) { - $one::on_initialise(n); + impl> OnInitialize for ($one,) { + fn on_initialize(n: Number) { + $one::on_initialize(n); + } + } + impl> OffchainWorker for ($one,) { + fn generate_extrinsics(n: Number) { + $one::generate_extrinsics(n); } } }; ($first:ident, $($rest:ident,)+) => { impl< Number: Copy, - $first: OnFinalise, - $($rest: OnFinalise),+ - > OnFinalise for ($first, $($rest),+) { - fn on_finalise(n: Number) { - $first::on_finalise(n); - $($rest::on_finalise(n);)+ + $first: OnFinalize, + $($rest: OnFinalize),+ + > OnFinalize for ($first, $($rest),+) { + fn on_finalize(n: Number) { + $first::on_finalize(n); + $($rest::on_finalize(n);)+ } } impl< Number: Copy, - $first: OnInitialise, - $($rest: OnInitialise),+ - > OnInitialise for ($first, $($rest),+) { - fn on_initialise(n: Number) { - $first::on_initialise(n); - $($rest::on_initialise(n);)+ + $first: OnInitialize, + $($rest: OnInitialize),+ + > OnInitialize for ($first, $($rest),+) { + fn on_initialize(n: Number) { + $first::on_initialize(n); + $($rest::on_initialize(n);)+ + } + } + impl< + Number: Copy, + $first: OffchainWorker, + $($rest: OffchainWorker),+ + > OffchainWorker for ($first, $($rest),+) { + fn generate_extrinsics(n: Number) { + $first::generate_extrinsics(n); + $($rest::generate_extrinsics(n);)+ } } tuple_impl!($($rest,)+); @@ -298,7 +377,10 @@ tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stupid bug in the Rust compiler believes derived // traits must be fulfilled by all type parameters. /// The hash type produced. - type Output: Member + MaybeSerializeDebug + AsRef<[u8]> + AsMut<[u8]>; + type Output: Member + MaybeSerializeDebug + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy + Default; + + /// The associated hash_db Hasher type. + type Hasher: Hasher; /// Produce the hash of some byte-slice. fn hash(s: &[u8]) -> Self::Output; @@ -338,6 +420,7 @@ pub struct BlakeTwo256; impl Hash for BlakeTwo256 { type Output = substrate_primitives::H256; + type Hasher = Blake2Hasher; fn hash(s: &[u8]) -> Self::Output { runtime_io::blake2_256(s).into() } @@ -480,6 +563,7 @@ pub trait MaybeHash {} #[cfg(not(feature = "std"))] impl MaybeHash for T {} + /// A type that can be used in runtime structures. pub trait Member: Send + Sync + Sized + MaybeDebug + Eq + PartialEq + Clone + 'static {} impl Member for T {} diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 8cdd419278269b055c938d9ad275e1d291d58705..7cf3aa1d6d6a1bb62f1f94a90ff523c48bdb4a28 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-sandbox/Cargo.toml b/core/sr-sandbox/Cargo.toml index b48744240e6cae4e98f60e647270669d8fb6fad2..599e66d6638b1b899619c3b9a175d2343544a5b9 100755 --- a/core/sr-sandbox/Cargo.toml +++ b/core/sr-sandbox/Cargo.toml @@ -12,7 +12,7 @@ rustc_version = "0.2" wasmi = { version = "0.4.3", optional = true } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false } -codec = { package = "parity-codec", version = "3.0", default-features = false } +codec = { package = "parity-codec", version = "3.2", default-features = false } [dev-dependencies] wabt = "~0.7.4" diff --git a/core/sr-sandbox/build.rs b/core/sr-sandbox/build.rs index 62ddacbbf4f993f3d58b036391e0ae0e94dc1b5a..5b5d06b65a2531b59ef0180a3761904885a5db2c 100755 --- a/core/sr-sandbox/build.rs +++ b/core/sr-sandbox/build.rs @@ -3,7 +3,7 @@ use rustc_version::{version, version_meta, Channel}; fn main() { - // Assert we haven't travelled back in time + // Assert we haven't traveled back in time assert!(version().unwrap().major >= 1); // Set cfg flags depending on release channel diff --git a/core/sr-sandbox/src/lib.rs b/core/sr-sandbox/src/lib.rs index 8054e44ba94e437279452c6900e614a71d1d79da..e8bdd5727ea8795ea16efeae71426aecc014e73f 100755 --- a/core/sr-sandbox/src/lib.rs +++ b/core/sr-sandbox/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -140,7 +140,7 @@ impl EnvironmentDefinitionBuilder { } } - /// Register a host function in this environment defintion. + /// Register a host function in this environment definition. /// /// NOTE that there is no constraints on type of this function. An instance /// can import function passed here with any signature it wants. It can even import diff --git a/core/sr-sandbox/with_std.rs b/core/sr-sandbox/with_std.rs index 038ecc023c98a3951ec566c823e696c0d7f84301..ea7ce818350d082030c3660ef8408a73cfa1db2c 100755 --- a/core/sr-sandbox/with_std.rs +++ b/core/sr-sandbox/with_std.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-sandbox/without_std.rs b/core/sr-sandbox/without_std.rs index d75168f1b06e3496af1f51ad2be2c714e359fc7e..070ca1ddf15cfd9f08e9275f57cea6567c8b3e11 100755 --- a/core/sr-sandbox/without_std.rs +++ b/core/sr-sandbox/without_std.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-std/build.rs b/core/sr-std/build.rs index 3cac76831607babfcdf6ccc7bea25b92c25daf98..af9c91db877ddbaa54bafadc254c366e064623a1 100644 --- a/core/sr-std/build.rs +++ b/core/sr-std/build.rs @@ -3,7 +3,7 @@ use rustc_version::{version, version_meta, Channel}; fn main() { - // Assert we haven't travelled back in time + // Assert we haven't traveled back in time assert!(version().unwrap().major >= 1); // Set cfg flags depending on release channel diff --git a/core/sr-std/src/lib.rs b/core/sr-std/src/lib.rs index c00f26703825deecb68fcfcc58d31804096d4d81..45857b33eda784a3107bc162a3c12c1b610d0342 100644 --- a/core/sr-std/src/lib.rs +++ b/core/sr-std/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-std/with_std.rs b/core/sr-std/with_std.rs index 7a718dfd2718308757834ec375258f93ed1123bd..27df71c4092f570cfb63fae62d27de0960c4ec3c 100644 --- a/core/sr-std/with_std.rs +++ b/core/sr-std/with_std.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-std/without_std.rs b/core/sr-std/without_std.rs index d5065648e9c7780ae1299f709762da00730afe53..c5178854848d6a09eef4bacfe1bc3f1ce51da02f 100644 --- a/core/sr-std/without_std.rs +++ b/core/sr-std/without_std.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-version/Cargo.toml b/core/sr-version/Cargo.toml index 3ad1ac299e58d498310f6e9dfc933bb9c79ee54e..cf3062faac01b7ffd0316e81324b1f39c926b1c3 100644 --- a/core/sr-version/Cargo.toml +++ b/core/sr-version/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] impl-serde = { version = "0.1", optional = true } -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../sr-std", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } @@ -16,7 +16,7 @@ runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", def default = ["std"] std = [ "impl-serde", - "serde/std", + "serde", "serde_derive", "parity-codec/std", "rstd/std", diff --git a/core/sr-version/src/lib.rs b/core/sr-version/src/lib.rs index 67c151cbeb531503f8d2975ff01b3355c03678cc..3d1dfb43136386c4c4e1b2e88c4ed22145419c84 100644 --- a/core/sr-version/src/lib.rs +++ b/core/sr-version/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -91,7 +91,7 @@ pub struct RuntimeVersion { /// serves only as an indication that the code is different; as long as the other two versions /// are the same then while the actual code may be different, it is nonetheless required to /// do the same thing. - /// Non-consensus-breaking optimisations are about the only changes that could be made which + /// Non-consensus-breaking optimizations are about the only changes that could be made which /// would result in only the `impl_version` changing. pub impl_version: u32, diff --git a/core/state-db/Cargo.toml b/core/state-db/Cargo.toml index 17cd6335188ec8f42ccee7872096d990db8353c5..28d5696928ef5bf99bc353e86111b0221a1ac2c8 100644 --- a/core/state-db/Cargo.toml +++ b/core/state-db/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" parking_lot = "0.7.1" log = "0.4" primitives = { package = "substrate-primitives", path = "../../core/primitives" } -parity-codec = { version = "3.1", features = ["derive"] } +parity-codec = { version = "3.2", features = ["derive"] } [dev-dependencies] env_logger = "0.6" diff --git a/core/state-db/src/lib.rs b/core/state-db/src/lib.rs index a9df4e80cac5e9ac1bab2ba220a6f497b6ff90b7..8d9cf9c965f5a21d1a9b0064de4c5ce1dc846055 100644 --- a/core/state-db/src/lib.rs +++ b/core/state-db/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -58,12 +58,12 @@ pub trait MetaDb { } /// Backend database trait. Read-only. -pub trait HashDb { - type Hash: Hash; +pub trait NodeDb { + type Key: ?Sized; type Error: fmt::Debug; /// Get state trie node. - fn get(&self, key: &Self::Hash) -> Result, Self::Error>; + fn get(&self, key: &Self::Key) -> Result, Self::Error>; } /// Error type. @@ -285,11 +285,13 @@ impl StateDbSync { self.pinned.remove(hash); } - pub fn get>(&self, key: &Key, db: &D) -> Result, Error> { + pub fn get(&self, key: &Key, db: &D) -> Result, Error> + where Key: AsRef + { if let Some(value) = self.non_canonical.get(key) { return Ok(Some(value)); } - db.get(key).map_err(|e| Error::Db(e)) + db.get(key.as_ref()).map_err(|e| Error::Db(e)) } pub fn apply_pending(&mut self) { @@ -349,7 +351,9 @@ impl StateDb { } /// Get a value from non-canonical/pruning overlay or the backing DB. - pub fn get>(&self, key: &Key, db: &D) -> Result, Error> { + pub fn get(&self, key: &Key, db: &D) -> Result, Error> + where Key: AsRef + { self.db.read().get(key, db) } diff --git a/core/state-db/src/noncanonical.rs b/core/state-db/src/noncanonical.rs index c11fcd74c33d4f4ded1d1e6c05a7fdc60dd5f8df..da957335ba30f4e7d59e5fe7f5eda6613b9943d7 100644 --- a/core/state-db/src/noncanonical.rs +++ b/core/state-db/src/noncanonical.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/state-db/src/pruning.rs b/core/state-db/src/pruning.rs index 95af8c553f1b6613086791315ed31a6219402941..078745c7a264464b4ed58fb3ac3c90224602a9bd 100644 --- a/core/state-db/src/pruning.rs +++ b/core/state-db/src/pruning.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,7 +23,6 @@ //! The changes are journaled in the DB. use std::collections::{HashMap, HashSet, VecDeque}; -use std::mem; use crate::codec::{Encode, Decode}; use crate::{CommitSet, Error, MetaDb, to_meta_key, Hash}; use log::{trace, warn}; @@ -33,10 +32,17 @@ const PRUNING_JOURNAL: &[u8] = b"pruning_journal"; /// See module documentation. pub struct RefWindow { + /// A queue of keys that should be deleted for each block in the pruning window. death_rows: VecDeque>, + /// An index that maps each key from `death_rows` to block number. death_index: HashMap, + /// Block number that corresponts to the front of `death_rows` pending_number: u64, - pending_records: Vec<(u64, JournalRecord)>, + /// Number of call of `note_canonical` after + /// last call `apply_pending` or `revert_pending` + pending_canonicalizations: usize, + /// Number of calls of `prune_one` after + /// last call `apply_pending` or `revert_pending` pending_prunings: usize, } @@ -71,7 +77,7 @@ impl RefWindow { death_rows: Default::default(), death_index: Default::default(), pending_number: pending_number, - pending_records: Default::default(), + pending_canonicalizations: 0, pending_prunings: 0, }; // read the journal @@ -114,7 +120,7 @@ impl RefWindow { } pub fn window_size(&self) -> u64 { - (self.death_rows.len() + self.pending_records.len() - self.pending_prunings) as u64 + (self.death_rows.len() - self.pending_prunings) as u64 } pub fn next_hash(&self) -> Option { @@ -130,8 +136,7 @@ impl RefWindow { } pub fn have_block(&self, hash: &BlockHash) -> bool { - self.death_rows.iter().skip(self.pending_prunings).any(|r| r.hash == *hash) || - self.pending_records.iter().any(|(_, record)| record.hash == *hash) + self.death_rows.iter().skip(self.pending_prunings).any(|r| r.hash == *hash) } /// Prune next block. Expects at least one block in the window. Adds changes to `commit`. @@ -143,13 +148,6 @@ impl RefWindow { commit.meta.inserted.push((to_meta_key(LAST_PRUNED, &()), index.encode())); commit.meta.deleted.push(pruned.journal_key.clone()); self.pending_prunings += 1; - } else if let Some((block, pruned)) = self.pending_records.get(self.pending_prunings - self.death_rows.len()) { - trace!(target: "state-db", "Pruning pending{:?} ({} deleted)", pruned.hash, pruned.deleted.len()); - commit.data.deleted.extend(pruned.deleted.iter().cloned()); - commit.meta.inserted.push((to_meta_key(LAST_PRUNED, &()), block.encode())); - let journal_key = to_journal_key(*block); - commit.meta.deleted.push(journal_key); - self.pending_prunings += 1; } else { warn!(target: "state-db", "Trying to prune when there's nothing to prune"); } @@ -165,21 +163,16 @@ impl RefWindow { inserted, deleted, }; - // Calculate pending block number taking pending canonicalizations into account, but not pending prunings - // as these are always applied last. - let block = self.pending_number + (self.death_rows.len() + self.pending_records.len()) as u64; + let block = self.pending_number + self.death_rows.len() as u64; let journal_key = to_journal_key(block); commit.meta.inserted.push((journal_key.clone(), journal_record.encode())); - self.pending_records.push((block, journal_record)); + self.import(&journal_record.hash, journal_key, journal_record.inserted.into_iter(), journal_record.deleted); + self.pending_canonicalizations += 1; } /// Apply all pending changes pub fn apply_pending(&mut self) { - for (block, journal_record) in mem::replace(&mut self.pending_records, Default::default()).into_iter() { - trace!(target: "state-db", "Applying pruning window record: {}: {:?}", block, journal_record.hash); - let journal_key = to_journal_key(block); - self.import(&journal_record.hash, journal_key, journal_record.inserted.into_iter(), journal_record.deleted); - } + self.pending_canonicalizations = 0; for _ in 0 .. self.pending_prunings { let pruned = self.death_rows.pop_front().expect("pending_prunings is always < death_rows.len()"); trace!(target: "state-db", "Applying pruning {:?} ({} deleted)", pruned.hash, pruned.deleted.len()); @@ -193,7 +186,14 @@ impl RefWindow { /// Revert all pending changes pub fn revert_pending(&mut self) { - self.pending_records.clear(); + // Revert pending deletions. + // Note that pending insertions might cause some existing deletions to be removed from `death_index` + // We don't bother to track and revert that for now. This means that a few nodes might end up no being + // deleted in case transaction fails and `revert_pending` is called. + self.death_rows.truncate(self.death_rows.len() - self.pending_canonicalizations); + let new_max_block = self.death_rows.len() as u64 + self.pending_number; + self.death_index.retain(|_, block| *block < new_max_block); + self.pending_canonicalizations = 0; self.pending_prunings = 0; } } @@ -231,7 +231,7 @@ mod tests { assert!(pruning.death_rows.is_empty()); assert!(pruning.death_index.is_empty()); assert!(pruning.pending_prunings == 0); - assert!(pruning.pending_records.is_empty()); + assert!(pruning.pending_canonicalizations == 0); } #[test] @@ -346,4 +346,34 @@ mod tests { pruning.apply_pending(); assert_eq!(pruning.pending_number, 3); } + + #[test] + fn reinserted_survivew_pending() { + let mut db = make_db(&[1, 2, 3]); + let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut commit = make_commit(&[], &[2]); + pruning.note_canonical(&H256::random(), &mut commit); + db.commit(&commit); + let mut commit = make_commit(&[2], &[]); + pruning.note_canonical(&H256::random(), &mut commit); + db.commit(&commit); + let mut commit = make_commit(&[], &[2]); + pruning.note_canonical(&H256::random(), &mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3]))); + + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3]))); + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3]))); + pruning.prune_one(&mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 3]))); + pruning.apply_pending(); + assert_eq!(pruning.pending_number, 3); + } } diff --git a/core/state-db/src/test.rs b/core/state-db/src/test.rs index 871750d0c8b75d3f64b8e7f0c2d6b4d3079e6b2d..d90c36990612ed8ec059fafc4e5475510784f901 100644 --- a/core/state-db/src/test.rs +++ b/core/state-db/src/test.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ use std::collections::HashMap; use primitives::H256; -use crate::{DBValue, ChangeSet, CommitSet, MetaDb, HashDb}; +use crate::{DBValue, ChangeSet, CommitSet, MetaDb, NodeDb}; #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct TestDb { @@ -34,9 +34,9 @@ impl MetaDb for TestDb { } } -impl HashDb for TestDb { +impl NodeDb for TestDb { type Error = (); - type Hash = H256; + type Key = H256; fn get(&self, key: &H256) -> Result, ()> { Ok(self.data.get(key).cloned()) diff --git a/core/state-machine/Cargo.toml b/core/state-machine/Cargo.toml index 9a5c42abf24c8a8734c6289b44f4872dbd6a1940..d81079b5f9c39a00055ac4e671587588f59c5622 100644 --- a/core/state-machine/Cargo.toml +++ b/core/state-machine/Cargo.toml @@ -10,10 +10,10 @@ hex-literal = "0.1.0" log = "0.4" parking_lot = "0.7.1" heapsize = "0.4" -hash-db = "0.11" -trie-db = "0.11" -trie-root = "0.11" +hash-db = "0.12" +trie-db = "0.12" +trie-root = "0.12" trie = { package = "substrate-trie", path = "../trie" } primitives = { package = "substrate-primitives", path = "../primitives" } panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } -parity-codec = "3.1" +parity-codec = "3.2" diff --git a/core/state-machine/src/backend.rs b/core/state-machine/src/backend.rs index 29562f1d26dc35c7aea0a4a0ee6abcda2861b193..14e60b140a0e8a0ea8224f15c0371b70608c84f4 100644 --- a/core/state-machine/src/backend.rs +++ b/core/state-machine/src/backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -112,9 +112,9 @@ impl Consolidate for Vec<(Option>, Vec, Option>)> { } } -impl Consolidate for MemoryDB { +impl> Consolidate for trie::GenericMemoryDB { fn consolidate(&mut self, other: Self) { - MemoryDB::consolidate(self, other) + trie::GenericMemoryDB::consolidate(self, other) } } diff --git a/core/state-machine/src/basic.rs b/core/state-machine/src/basic.rs new file mode 100644 index 0000000000000000000000000000000000000000..7b2a95464e653e61cd8f010748b127ee92e6bd83 --- /dev/null +++ b/core/state-machine/src/basic.rs @@ -0,0 +1,189 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Basic implementation for Externalities. + +use std::collections::HashMap; +use std::iter::FromIterator; +use hash_db::Hasher; +use heapsize::HeapSizeOf; +use trie::trie_root; +use primitives::storage::well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES}; +use parity_codec::Encode; +use super::{Externalities, OverlayedChanges}; +use log::warn; + +/// Simple HashMap-based Externalities impl. +pub struct BasicExternalities { + inner: HashMap, Vec>, + changes: OverlayedChanges, + code: Option>, +} + +impl BasicExternalities { + /// Create a new instance of `BasicExternalities` + pub fn new(inner: HashMap, Vec>) -> Self { + Self::new_with_code(&[], inner) + } + + /// Create a new instance of `BasicExternalities` + pub fn new_with_code(code: &[u8], mut inner: HashMap, Vec>) -> Self { + let mut overlay = OverlayedChanges::default(); + super::set_changes_trie_config( + &mut overlay, + inner.get(&CHANGES_TRIE_CONFIG.to_vec()).cloned(), + false, + ).expect("changes trie configuration is correct in test env; qed"); + + inner.insert(HEAP_PAGES.to_vec(), 8u64.encode()); + + BasicExternalities { + inner, + changes: overlay, + code: Some(code.to_vec()), + } + } + + /// Insert key/value + pub fn insert(&mut self, k: Vec, v: Vec) -> Option> { + self.inner.insert(k, v) + } +} + +impl ::std::fmt::Debug for BasicExternalities { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{:?}", self.inner) + } +} + +impl PartialEq for BasicExternalities { + fn eq(&self, other: &BasicExternalities) -> bool { + self.inner.eq(&other.inner) + } +} + +impl FromIterator<(Vec, Vec)> for BasicExternalities { + fn from_iter, Vec)>>(iter: I) -> Self { + let mut t = Self::new(Default::default()); + t.inner.extend(iter); + t + } +} + +impl Default for BasicExternalities { + fn default() -> Self { Self::new(Default::default()) } +} + +impl From for HashMap, Vec> { + fn from(tex: BasicExternalities) -> Self { + tex.inner.into() + } +} + +impl From< HashMap, Vec> > for BasicExternalities { + fn from(hashmap: HashMap, Vec>) -> Self { + BasicExternalities { + inner: hashmap, + changes: Default::default(), + code: None, + } + } +} + +impl Externalities for BasicExternalities where H::Out: Ord + HeapSizeOf { + fn storage(&self, key: &[u8]) -> Option> { + match key { + CODE => self.code.clone(), + _ => self.inner.get(key).cloned(), + } + } + + fn child_storage(&self, _storage_key: &[u8], _key: &[u8]) -> Option> { + None + } + + fn place_storage(&mut self, key: Vec, maybe_value: Option>) { + self.changes.set_storage(key.clone(), maybe_value.clone()); + match key.as_ref() { + CODE => self.code = maybe_value, + _ => { + match maybe_value { + Some(value) => { self.inner.insert(key, value); } + None => { self.inner.remove(&key); } + } + } + } + } + + fn place_child_storage(&mut self, _storage_key: Vec, _key: Vec, _value: Option>) -> bool { + false + } + + fn kill_child_storage(&mut self, _storage_key: &[u8]) { } + + fn clear_prefix(&mut self, prefix: &[u8]) { + self.changes.clear_prefix(prefix); + self.inner.retain(|key, _| !key.starts_with(prefix)); + } + + fn chain_id(&self) -> u64 { 42 } + + fn storage_root(&mut self) -> H::Out { + trie_root::(self.inner.clone()) + } + + fn child_storage_root(&mut self, _storage_key: &[u8]) -> Option> { + None + } + + fn storage_changes_root(&mut self, _parent: H::Out, _parent_num: u64) -> Option { + None + } + + fn submit_extrinsic(&mut self, _extrinsic: Vec) -> Result<(), ()> { + warn!("Call to submit_extrinsic without offchain externalities set."); + Err(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use primitives::{Blake2Hasher, H256}; + use hex_literal::{hex, hex_impl}; + + #[test] + fn commit_should_work() { + let mut ext = BasicExternalities::default(); + let ext = &mut ext as &mut Externalities; + ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); + ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); + ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); + const ROOT: [u8; 32] = hex!("0b33ed94e74e0f8e92a55923bece1ed02d16cf424e124613ddebc53ac3eeeabe"); + assert_eq!(ext.storage_root(), H256::from(ROOT)); + } + + #[test] + fn set_and_retrieve_code() { + let mut ext = BasicExternalities::default(); + let ext = &mut ext as &mut Externalities; + + let code = vec![1, 2, 3]; + ext.set_storage(CODE.to_vec(), code.clone()); + + assert_eq!(&ext.storage(CODE).unwrap(), &code); + } +} diff --git a/core/state-machine/src/changes_trie/build.rs b/core/state-machine/src/changes_trie/build.rs index 548ffa42995d6e1d57bc27edb8733ae5f42415bf..9cb766874d8f847136093f334199c92046181d83 100644 --- a/core/state-machine/src/changes_trie/build.rs +++ b/core/state-machine/src/changes_trie/build.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/state-machine/src/changes_trie/build_iterator.rs b/core/state-machine/src/changes_trie/build_iterator.rs index 4097da3a549be2525b399369ed335c63a936c5fb..f9c6ba6e7b397021ca0c856499de012217815867 100644 --- a/core/state-machine/src/changes_trie/build_iterator.rs +++ b/core/state-machine/src/changes_trie/build_iterator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/state-machine/src/changes_trie/changes_iterator.rs b/core/state-machine/src/changes_trie/changes_iterator.rs index 5805427870c86fa1372ec33bd815ea2c619e4018..ad70117984989bb9d022855b29f7cea87927c368 100644 --- a/core/state-machine/src/changes_trie/changes_iterator.rs +++ b/core/state-machine/src/changes_trie/changes_iterator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -115,7 +115,7 @@ pub fn key_changes_proof_check, H: Hasher>( let mut proof_db = MemoryDB::::default(); for item in proof { - proof_db.insert(&item); + proof_db.insert(&[], &item); } let proof_db = InMemoryStorage::with_db(proof_db); diff --git a/core/state-machine/src/changes_trie/input.rs b/core/state-machine/src/changes_trie/input.rs index c106774021be8ff5769bddf35746938020f55192..3154aff715c2ba79070b6ecd6dd3c49a77c0729b 100644 --- a/core/state-machine/src/changes_trie/input.rs +++ b/core/state-machine/src/changes_trie/input.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/state-machine/src/changes_trie/mod.rs b/core/state-machine/src/changes_trie/mod.rs index 2bde6a259242bb2bb76285aa617d9fe0b03fb575..c29131cc0c5d8bd82724a02b0a2b072c59f2fd81 100644 --- a/core/state-machine/src/changes_trie/mod.rs +++ b/core/state-machine/src/changes_trie/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -77,7 +77,7 @@ pub trait RootsStorage: Send + Sync { /// Changes trie storage. Provides access to trie roots and trie nodes. pub trait Storage: RootsStorage { /// Get a trie node. - fn get(&self, key: &H::Out) -> Result, String>; + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String>; } /// Changes trie configuration. diff --git a/core/state-machine/src/changes_trie/prune.rs b/core/state-machine/src/changes_trie/prune.rs index 74bf0c97bfdfe2b12bebd4f28a08c072e25cec69..de872a325589e9854b135ab1c3acce981edac994 100644 --- a/core/state-machine/src/changes_trie/prune.rs +++ b/core/state-machine/src/changes_trie/prune.rs @@ -1,4 +1,4 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/state-machine/src/changes_trie/storage.rs b/core/state-machine/src/changes_trie/storage.rs index 2ac00a853577add04129021f18a8c185bfeefdfa..decc332c1a6187ea364eb4db2a2fb5e75a38a82c 100644 --- a/core/state-machine/src/changes_trie/storage.rs +++ b/core/state-machine/src/changes_trie/storage.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -92,7 +92,7 @@ impl InMemoryStorage where H::Out: HeapSizeOf { pub fn remove_from_storage(&self, keys: &HashSet) { let mut data = self.data.write(); for key in keys { - data.mdb.remove_and_purge(key); + data.mdb.remove_and_purge(key, &[]); } } @@ -116,8 +116,8 @@ impl RootsStorage for InMemoryStorage where H::Out: HeapSizeOf } impl Storage for InMemoryStorage where H::Out: HeapSizeOf { - fn get(&self, key: &H::Out) -> Result, String> { - MemoryDB::::get(&self.data.read().mdb, key) + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String> { + MemoryDB::::get(&self.data.read().mdb, key, prefix) } } @@ -128,7 +128,9 @@ impl<'a, H: Hasher, S: 'a + Storage> TrieBackendAdapter<'a, H, S> { } impl<'a, H: Hasher, S: 'a + Storage> TrieBackendStorage for TrieBackendAdapter<'a, H, S> { - fn get(&self, key: &H::Out) -> Result, String> { - self.storage.get(key) + type Overlay = MemoryDB; + + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String> { + self.storage.get(key, prefix) } } diff --git a/core/state-machine/src/ext.rs b/core/state-machine/src/ext.rs index e0f164b42b2aaea3b2091a4a2dcddf56c1910c67..33074c70590b1a42cc4d2eae668ae5c7e2b3cab5 100644 --- a/core/state-machine/src/ext.rs +++ b/core/state-machine/src/ext.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,13 +20,13 @@ use std::{error, fmt, cmp::Ord}; use log::warn; use crate::backend::{Backend, Consolidate}; use crate::changes_trie::{AnchorBlockId, Storage as ChangesTrieStorage, compute_changes_trie_root}; -use crate::{Externalities, OverlayedChanges}; +use crate::{Externalities, OverlayedChanges, OffchainExt}; use hash_db::Hasher; use primitives::storage::well_known_keys::is_child_storage_key; use trie::{MemoryDB, TrieDBMut, TrieMut, default_child_trie_root, is_child_trie_key_valid}; use heapsize::HeapSizeOf; -const EXT_NOT_ALLOWED_TO_FAIL: &'static str = "Externalities not allowed to fail within runtime"; +const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime"; /// Errors that can occur when interacting with the externalities. #[derive(Debug, Copy, Clone)] @@ -58,12 +58,11 @@ impl error::Error for Error { } /// Wraps a read-only backend, call executor, and current overlayed changes. -pub struct Ext<'a, H, B, T> +pub struct Ext<'a, H, B, T, O> where H: Hasher, B: 'a + Backend, - T: 'a + ChangesTrieStorage, { /// The overlayed changes to write to. overlay: &'a mut OverlayedChanges, @@ -81,23 +80,34 @@ where /// `storage_changes_root` is called matters + we need to remember additional /// data at this moment (block number). changes_trie_transaction: Option<(u64, MemoryDB, H::Out)>, + /// Additional externalities for offchain workers. + /// + /// If None, some methods from the trait might not supported. + offchain_externalities: Option<&'a mut O>, } -impl<'a, H, B, T> Ext<'a, H, B, T> +impl<'a, H, B, T, O> Ext<'a, H, B, T, O> where H: Hasher, B: 'a + Backend, T: 'a + ChangesTrieStorage, + O: 'a + OffchainExt, H::Out: Ord + HeapSizeOf, { /// Create a new `Ext` from overlayed changes and read-only backend - pub fn new(overlay: &'a mut OverlayedChanges, backend: &'a B, changes_trie_storage: Option<&'a T>) -> Self { + pub fn new( + overlay: &'a mut OverlayedChanges, + backend: &'a B, + changes_trie_storage: Option<&'a T>, + offchain_externalities: Option<&'a mut O>, + ) -> Self { Ext { overlay, backend, storage_transaction: None, changes_trie_storage, changes_trie_transaction: None, + offchain_externalities, } } @@ -152,12 +162,13 @@ where } #[cfg(test)] -impl<'a, H, B, T> Ext<'a, H, B, T> +impl<'a, H, B, T, O> Ext<'a, H, B, T, O> where H: Hasher, B: 'a + Backend, T: 'a + ChangesTrieStorage, + O: 'a + OffchainExt, { pub fn storage_pairs(&self) -> Vec<(Vec, Vec)> { use std::collections::HashMap; @@ -173,11 +184,12 @@ where } } -impl<'a, B: 'a, T: 'a, H> Externalities for Ext<'a, H, B, T> +impl<'a, B, T, H, O> Externalities for Ext<'a, H, B, T, O> where H: Hasher, B: 'a + Backend, T: 'a + ChangesTrieStorage, + O: 'a + OffchainExt, H::Out: Ord + HeapSizeOf, { fn storage(&self, key: &[u8]) -> Option> { @@ -329,6 +341,17 @@ where self.changes_trie_transaction = root_and_tx; root } + + fn submit_extrinsic(&mut self, extrinsic: Vec) -> Result<(), ()> { + let _guard = panic_handler::AbortGuard::new(true); + if let Some(ext) = self.offchain_externalities.as_mut() { + ext.submit_extrinsic(extrinsic); + Ok(()) + } else { + warn!("Call to submit_extrinsic without offchain externalities set."); + Err(()) + } + } } #[cfg(test)] @@ -345,7 +368,7 @@ mod tests { type TestBackend = InMemory; type TestChangesTrieStorage = InMemoryChangesTrieStorage; - type TestExt<'a> = Ext<'a, Blake2Hasher, TestBackend, TestChangesTrieStorage>; + type TestExt<'a> = Ext<'a, Blake2Hasher, TestBackend, TestChangesTrieStorage, crate::NeverOffchainExt>; fn prepare_overlay_with_changes() -> OverlayedChanges { OverlayedChanges { @@ -371,7 +394,7 @@ mod tests { fn storage_changes_root_is_none_when_storage_is_not_provided() { let mut overlay = prepare_overlay_with_changes(); let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, None); + let mut ext = TestExt::new(&mut overlay, &backend, None, None); assert_eq!(ext.storage_changes_root(Default::default(), 100), None); } @@ -381,7 +404,7 @@ mod tests { overlay.changes_trie_config = None; let storage = TestChangesTrieStorage::new(); let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage)); + let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None); assert_eq!(ext.storage_changes_root(Default::default(), 100), None); } @@ -390,7 +413,7 @@ mod tests { let mut overlay = prepare_overlay_with_changes(); let storage = TestChangesTrieStorage::new(); let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage)); + let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None); assert_eq!(ext.storage_changes_root(Default::default(), 99), Some(hex!("5b829920b9c8d554a19ee2a1ba593c4f2ee6fc32822d083e04236d693e8358d5").into())); } @@ -401,7 +424,7 @@ mod tests { overlay.prospective.top.get_mut(&vec![1]).unwrap().value = None; let storage = TestChangesTrieStorage::new(); let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage)); + let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None); assert_eq!(ext.storage_changes_root(Default::default(), 99), Some(hex!("bcf494e41e29a15c9ae5caa053fe3cb8b446ee3e02a254efbdec7a19235b76e4").into())); } diff --git a/core/state-machine/src/lib.rs b/core/state-machine/src/lib.rs index 3b9e482e8211f0c697fd64e73f2622ae57f0b66f..0500aa72cfcc3782ac06670e1f77a32d30f97856 100644 --- a/core/state-machine/src/lib.rs +++ b/core/state-machine/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,12 +23,13 @@ use log::warn; use hash_db::Hasher; use heapsize::HeapSizeOf; use parity_codec::{Decode, Encode}; -use primitives::{storage::well_known_keys, NativeOrEncoded, NeverNativeValue}; +use primitives::{storage::well_known_keys, NativeOrEncoded, NeverNativeValue, OffchainExt}; pub mod backend; mod changes_trie; mod ext; mod testing; +mod basic; mod overlayed_changes; mod proving_backend; mod trie_backend; @@ -37,6 +38,7 @@ mod trie_backend_essence; use overlayed_changes::OverlayedChangeSet; pub use trie::{TrieMut, TrieDBMut, DBValue, MemoryDB}; pub use testing::TestExternalities; +pub use basic::BasicExternalities; pub use ext::Ext; pub use backend::Backend; pub use changes_trie::{ @@ -149,8 +151,27 @@ pub trait Externalities { /// Returns None if key provided is not a storage key. This can due to not being started with CHILD_STORAGE_KEY_PREFIX, or the trie implementation regards the key as invalid. fn child_storage_root(&mut self, storage_key: &[u8]) -> Option>; - /// Get the change trie root of the current storage overlay at a block wth given parent. + /// Get the change trie root of the current storage overlay at a block with given parent. fn storage_changes_root(&mut self, parent: H::Out, parent_num: u64) -> Option where H::Out: Ord; + + /// Submit extrinsic. + /// + /// Returns an error in case the API is not available. + fn submit_extrinsic(&mut self, extrinsic: Vec) -> Result<(), ()>; +} + +/// An implementation of offchain extensions that should never be triggered. +pub enum NeverOffchainExt {} + +impl NeverOffchainExt { + /// Create new offchain extensions. + pub fn new<'a>() -> Option<&'a mut Self> { + None + } +} + +impl OffchainExt for NeverOffchainExt { + fn submit_extrinsic(&mut self, _extrinsic: Vec) { unreachable!() } } /// Code execution engine. @@ -250,17 +271,19 @@ pub fn always_wasm() -> ExecutionManager> { } /// Creates new substrate state machine. -pub fn new<'a, H, B, T, Exec>( +pub fn new<'a, H, B, T, O, Exec>( backend: &'a B, changes_trie_storage: Option<&'a T>, + offchain_ext: Option<&'a mut O>, overlay: &'a mut OverlayedChanges, exec: &'a Exec, method: &'a str, call_data: &'a [u8], -) -> StateMachine<'a, H, B, T, Exec> { +) -> StateMachine<'a, H, B, T, O, Exec> { StateMachine { backend, changes_trie_storage, + offchain_ext, overlay, exec, method, @@ -270,9 +293,10 @@ pub fn new<'a, H, B, T, Exec>( } /// The substrate state machine. -pub struct StateMachine<'a, H, B, T, Exec> { +pub struct StateMachine<'a, H, B, T, O, Exec> { backend: &'a B, changes_trie_storage: Option<&'a T>, + offchain_ext: Option<&'a mut O>, overlay: &'a mut OverlayedChanges, exec: &'a Exec, method: &'a str, @@ -280,11 +304,12 @@ pub struct StateMachine<'a, H, B, T, Exec> { _hasher: PhantomData, } -impl<'a, H, B, T, Exec> StateMachine<'a, H, B, T, Exec> where +impl<'a, H, B, T, O, Exec> StateMachine<'a, H, B, T, O, Exec> where H: Hasher, Exec: CodeExecutor, B: Backend, T: ChangesTrieStorage, + O: OffchainExt, H::Out: Ord + HeapSizeOf, { /// Execute a call using the given state backend, overlayed changes, and call executor. @@ -322,7 +347,13 @@ impl<'a, H, B, T, Exec> StateMachine<'a, H, B, T, Exec> where R: Decode + Encode + PartialEq, NC: FnOnce() -> result::Result + UnwindSafe, { - let mut externalities = ext::Ext::new(self.overlay, self.backend, self.changes_trie_storage); + let offchain = self.offchain_ext.as_mut(); + let mut externalities = ext::Ext::new( + self.overlay, + self.backend, + self.changes_trie_storage, + offchain.map(|x| &mut **x), + ); let (result, was_native) = self.exec.call( &mut externalities, self.method, @@ -503,6 +534,7 @@ where let mut sm = StateMachine { backend: &proving_backend, changes_trie_storage: None as Option<&changes_trie::InMemoryStorage>, + offchain_ext: NeverOffchainExt::new(), overlay, exec, method, @@ -552,6 +584,7 @@ where let mut sm = StateMachine { backend: trie_backend, changes_trie_storage: None as Option<&changes_trie::InMemoryStorage>, + offchain_ext: NeverOffchainExt::new(), overlay, exec, method, @@ -625,7 +658,7 @@ where /// differs from previous OR config decode has failed. pub(crate) fn set_changes_trie_config(overlay: &mut OverlayedChanges, config: Option>, final_check: bool) -> Result<(), Box> { let config = match config { - Some(v) => Some(changes_trie::Configuration::decode(&mut &v[..]) + Some(v) => Some(Decode::decode(&mut &v[..]) .ok_or_else(|| Box::new("Failed to decode changes trie configuration".to_owned()) as Box)?), None => None, }; @@ -728,6 +761,7 @@ mod tests { assert_eq!(new( &trie_backend::tests::test_trie(), Some(&InMemoryChangesTrieStorage::new()), + NeverOffchainExt::new(), &mut Default::default(), &DummyCodeExecutor { change_changes_trie_config: false, @@ -748,6 +782,7 @@ mod tests { assert_eq!(new( &trie_backend::tests::test_trie(), Some(&InMemoryChangesTrieStorage::new()), + NeverOffchainExt::new(), &mut Default::default(), &DummyCodeExecutor { change_changes_trie_config: false, @@ -768,6 +803,7 @@ mod tests { assert!(new( &trie_backend::tests::test_trie(), Some(&InMemoryChangesTrieStorage::new()), + NeverOffchainExt::new(), &mut Default::default(), &DummyCodeExecutor { change_changes_trie_config: false, @@ -836,7 +872,7 @@ mod tests { { let changes_trie_storage = InMemoryChangesTrieStorage::new(); - let mut ext = Ext::new(&mut overlay, &backend, Some(&changes_trie_storage)); + let mut ext = Ext::new(&mut overlay, &backend, Some(&changes_trie_storage), NeverOffchainExt::new()); ext.clear_prefix(b"ab"); } overlay.commit_prospective(); @@ -860,7 +896,7 @@ mod tests { let backend = InMemory::::default().try_into_trie_backend().unwrap(); let changes_trie_storage = InMemoryChangesTrieStorage::new(); let mut overlay = OverlayedChanges::default(); - let mut ext = Ext::new(&mut overlay, &backend, Some(&changes_trie_storage)); + let mut ext = Ext::new(&mut overlay, &backend, Some(&changes_trie_storage), NeverOffchainExt::new()); assert!(ext.set_child_storage(b":child_storage:testchild".to_vec(), b"abc".to_vec(), b"def".to_vec())); assert_eq!(ext.child_storage(b":child_storage:testchild", b"abc"), Some(b"def".to_vec())); @@ -887,6 +923,7 @@ mod tests { assert!(new( &trie_backend::tests::test_trie(), Some(&InMemoryChangesTrieStorage::new()), + NeverOffchainExt::new(), &mut Default::default(), &DummyCodeExecutor { change_changes_trie_config: true, @@ -906,6 +943,7 @@ mod tests { assert!(new( &trie_backend::tests::test_trie(), Some(&InMemoryChangesTrieStorage::new()), + NeverOffchainExt::new(), &mut Default::default(), &DummyCodeExecutor { change_changes_trie_config: true, diff --git a/core/state-machine/src/overlayed_changes.rs b/core/state-machine/src/overlayed_changes.rs index 2f7522c48e7d75376deac6a946a89c305a4ac579..56e69323e878ccb98b180907b8f41618dc480b57 100644 --- a/core/state-machine/src/overlayed_changes.rs +++ b/core/state-machine/src/overlayed_changes.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -375,7 +375,12 @@ mod tests { }; let changes_trie_storage = InMemoryChangesTrieStorage::new(); - let mut ext = Ext::new(&mut overlay, &backend, Some(&changes_trie_storage)); + let mut ext = Ext::new( + &mut overlay, + &backend, + Some(&changes_trie_storage), + crate::NeverOffchainExt::new(), + ); const ROOT: [u8; 32] = hex!("0b41e488cccbd67d1f1089592c2c235f5c5399b053f7fe9152dd4b5f279914cd"); assert_eq!(ext.storage_root(), H256::from(ROOT)); } diff --git a/core/state-machine/src/proving_backend.rs b/core/state-machine/src/proving_backend.rs index 1aeb83fe3ad0c2b04e4885a1762bf8ab9e79ce27..4d85791faf681afbaaa94cef9090aad7ce98bd3f 100644 --- a/core/state-machine/src/proving_backend.rs +++ b/core/state-machine/src/proving_backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ use log::debug; use hash_db::Hasher; use heapsize::HeapSizeOf; use hash_db::HashDB; -use trie::{Recorder, MemoryDB, TrieError, default_child_trie_root, read_trie_value_with, read_child_trie_value_with, record_all_keys}; +use trie::{Recorder, MemoryDB, PrefixedMemoryDB, TrieError, default_child_trie_root, read_trie_value_with, read_child_trie_value_with, record_all_keys}; use crate::trie_backend::TrieBackend; use crate::trie_backend_essence::{Ephemeral, TrieBackendEssence, TrieBackendStorage}; use crate::{Error, ExecutionError, Backend}; @@ -40,7 +40,7 @@ impl<'a, S, H> ProvingBackendEssence<'a, S, H> H::Out: HeapSizeOf, { pub fn storage(&mut self, key: &[u8]) -> Result>, String> { - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral::new( self.backend.backend_storage(), &mut read_overlay, @@ -54,7 +54,7 @@ impl<'a, S, H> ProvingBackendEssence<'a, S, H> pub fn child_storage(&mut self, storage_key: &[u8], key: &[u8]) -> Result>, String> { let root = self.storage(storage_key)?.unwrap_or(default_child_trie_root::(storage_key)); - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral::new( self.backend.backend_storage(), &mut read_overlay, @@ -66,7 +66,7 @@ impl<'a, S, H> ProvingBackendEssence<'a, S, H> } pub fn record_all_keys(&mut self) { - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral::new( self.backend.backend_storage(), &mut read_overlay, @@ -116,8 +116,8 @@ impl<'a, S, H> Backend for ProvingBackend<'a, S, H> H::Out: Ord + HeapSizeOf, { type Error = String; - type Transaction = MemoryDB; - type TrieBackendStorage = MemoryDB; + type Transaction = S::Overlay; + type TrieBackendStorage = PrefixedMemoryDB; fn storage(&self, key: &[u8]) -> Result>, Self::Error> { ProvingBackendEssence { @@ -151,7 +151,7 @@ impl<'a, S, H> Backend for ProvingBackend<'a, S, H> self.backend.keys(prefix) } - fn storage_root(&self, delta: I) -> (H::Out, MemoryDB) + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) where I: IntoIterator, Option>)> { self.backend.storage_root(delta) @@ -181,7 +181,7 @@ where { let db = create_proof_check_backend_storage(proof); - if !db.contains(&root) { + if !db.contains(&root, &[]) { return Err(Box::new(ExecutionError::InvalidProof) as Box); } @@ -198,7 +198,7 @@ where { let mut db = MemoryDB::default(); for item in proof { - db.insert(&item); + db.insert(&[], &item); } db } @@ -210,7 +210,7 @@ mod tests { use super::*; use primitives::{Blake2Hasher}; - fn test_proving<'a>(trie_backend: &'a TrieBackend, Blake2Hasher>) -> ProvingBackend<'a, MemoryDB, Blake2Hasher> { + fn test_proving<'a>(trie_backend: &'a TrieBackend, Blake2Hasher>) -> ProvingBackend<'a, PrefixedMemoryDB, Blake2Hasher> { ProvingBackend::new(trie_backend) } diff --git a/core/state-machine/src/testing.rs b/core/state-machine/src/testing.rs index a0448dad7cc646c85c0949f8f8c086df8e2118a1..d03cc8e76dccce3bcd7e5c8bca5746865eb96130 100644 --- a/core/state-machine/src/testing.rs +++ b/core/state-machine/src/testing.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -107,6 +107,9 @@ impl From< HashMap, Vec> > for TestExternalities where } } +// TODO child test primitives are currently limited to `changes` (for non child the way +// things are defined seems utterly odd to (put changes in changes but never make them +// available for read through inner) impl Externalities for TestExternalities where H::Out: Ord + HeapSizeOf { fn storage(&self, key: &[u8]) -> Option> { match key { @@ -115,8 +118,8 @@ impl Externalities for TestExternalities where H::Out: Ord + He } } - fn child_storage(&self, _storage_key: &[u8], _key: &[u8]) -> Option> { - None + fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option> { + self.changes.child_storage(storage_key, key)?.map(Vec::from) } fn place_storage(&mut self, key: Vec, maybe_value: Option>) { @@ -132,11 +135,15 @@ impl Externalities for TestExternalities where H::Out: Ord + He } } - fn place_child_storage(&mut self, _storage_key: Vec, _key: Vec, _value: Option>) -> bool { - false + fn place_child_storage(&mut self, storage_key: Vec, key: Vec, value: Option>) -> bool { + self.changes.set_child_storage(storage_key, key, value); + // TODO place_child_storage and set_child_storage should always be valid (create child on set)? + true } - fn kill_child_storage(&mut self, _storage_key: &[u8]) { } + fn kill_child_storage(&mut self, storage_key: &[u8]) { + self.changes.clear_child_storage(storage_key); + } fn clear_prefix(&mut self, prefix: &[u8]) { self.changes.clear_prefix(prefix); @@ -161,6 +168,10 @@ impl Externalities for TestExternalities where H::Out: Ord + He &AnchorBlockId { hash: parent, number: parent_num }, ).map(|(root, _)| root.clone()) } + + fn submit_extrinsic(&mut self, _extrinsic: Vec) -> Result<(), ()> { + unimplemented!() + } } #[cfg(test)] diff --git a/core/state-machine/src/trie_backend.rs b/core/state-machine/src/trie_backend.rs index 989b990d93815ea9bf63a8681c9555e833e76108..b152d7fea18578aedf032efb2ab482627d087f58 100644 --- a/core/state-machine/src/trie_backend.rs +++ b/core/state-machine/src/trie_backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,7 +19,7 @@ use log::{warn, debug}; use hash_db::Hasher; use heapsize::HeapSizeOf; -use trie::{TrieDB, TrieError, Trie, MemoryDB, delta_trie_root, default_child_trie_root, child_delta_trie_root}; +use trie::{TrieDB, TrieError, Trie, delta_trie_root, default_child_trie_root, child_delta_trie_root}; use crate::trie_backend_essence::{TrieBackendEssence, TrieBackendStorage, Ephemeral}; use crate::Backend; @@ -63,7 +63,7 @@ impl, H: Hasher> Backend for TrieBackend where H::Out: Ord + HeapSizeOf, { type Error = String; - type Transaction = MemoryDB; + type Transaction = S::Overlay; type TrieBackendStorage = S; fn storage(&self, key: &[u8]) -> Result>, Self::Error> { @@ -83,7 +83,7 @@ impl, H: Hasher> Backend for TrieBackend where } fn pairs(&self) -> Vec<(Vec, Vec)> { - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral::new(self.essence.backend_storage(), &mut read_overlay); let collect_all = || -> Result<_, Box>> { @@ -107,7 +107,7 @@ impl, H: Hasher> Backend for TrieBackend where } fn keys(&self, prefix: &Vec) -> Vec> { - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral::new(self.essence.backend_storage(), &mut read_overlay); let collect_all = || -> Result<_, Box>> { @@ -126,10 +126,10 @@ impl, H: Hasher> Backend for TrieBackend where collect_all().map_err(|e| debug!(target: "trie", "Error extracting trie keys: {}", e)).unwrap_or_default() } - fn storage_root(&self, delta: I) -> (H::Out, MemoryDB) + fn storage_root(&self, delta: I) -> (H::Out, S::Overlay) where I: IntoIterator, Option>)> { - let mut write_overlay = MemoryDB::default(); + let mut write_overlay = S::Overlay::default(); let mut root = *self.essence.root(); { @@ -154,7 +154,7 @@ impl, H: Hasher> Backend for TrieBackend where { let default_root = default_child_trie_root::(storage_key); - let mut write_overlay = MemoryDB::default(); + let mut write_overlay = S::Overlay::default(); let mut root = match self.storage(storage_key) { Ok(value) => value.unwrap_or(default_child_trie_root::(storage_key)), Err(e) => { @@ -189,12 +189,12 @@ impl, H: Hasher> Backend for TrieBackend where pub mod tests { use std::collections::HashSet; use primitives::{Blake2Hasher, H256}; - use trie::{TrieMut, TrieDBMut}; + use trie::{TrieMut, TrieDBMut, PrefixedMemoryDB}; use super::*; - fn test_db() -> (MemoryDB, H256) { + fn test_db() -> (PrefixedMemoryDB, H256) { let mut root = H256::default(); - let mut mdb = MemoryDB::::default(); + let mut mdb = PrefixedMemoryDB::::default(); { let mut trie = TrieDBMut::new(&mut mdb, &mut root); trie.insert(b"key", b"value").expect("insert failed"); @@ -208,7 +208,7 @@ pub mod tests { (mdb, root) } - pub(crate) fn test_trie() -> TrieBackend, Blake2Hasher> { + pub(crate) fn test_trie() -> TrieBackend, Blake2Hasher> { let (mdb, root) = test_db(); TrieBackend::new(mdb, root) } @@ -230,8 +230,8 @@ pub mod tests { #[test] fn pairs_are_empty_on_empty_storage() { - assert!(TrieBackend::, Blake2Hasher>::new( - MemoryDB::default(), + assert!(TrieBackend::, Blake2Hasher>::new( + PrefixedMemoryDB::default(), Default::default(), ).pairs().is_empty()); } diff --git a/core/state-machine/src/trie_backend_essence.rs b/core/state-machine/src/trie_backend_essence.rs index 5a2fc8d76d6467399103a4aee26a28b07dd7821d..8101126c39d78c7b386ae94a33a74195a8122d94 100644 --- a/core/state-machine/src/trie_backend_essence.rs +++ b/core/state-machine/src/trie_backend_essence.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,13 +22,14 @@ use std::sync::Arc; use log::{debug, warn}; use hash_db::{self, Hasher}; use heapsize::HeapSizeOf; -use trie::{TrieDB, Trie, MemoryDB, DBValue, TrieError, default_child_trie_root, read_trie_value, read_child_trie_value, for_keys_in_child_trie}; +use trie::{TrieDB, Trie, MemoryDB, PrefixedMemoryDB, DBValue, TrieError, default_child_trie_root, read_trie_value, read_child_trie_value, for_keys_in_child_trie}; use crate::changes_trie::Storage as ChangesTrieStorage; +use crate::backend::Consolidate; /// Patricia trie-based storage trait. pub trait Storage: Send + Sync { /// Get a trie node. - fn get(&self, key: &H::Out) -> Result, String>; + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String>; } /// Patricia trie-based pairs storage essence. @@ -63,7 +64,7 @@ impl, H: Hasher> TrieBackendEssence where H::Out: /// Get the value of storage at given key. pub fn storage(&self, key: &[u8]) -> Result>, String> { - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral { storage: &self.storage, overlay: &mut read_overlay, @@ -78,7 +79,7 @@ impl, H: Hasher> TrieBackendEssence where H::Out: pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, String> { let root = self.storage(storage_key)?.unwrap_or(default_child_trie_root::(storage_key)); - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral { storage: &self.storage, overlay: &mut read_overlay, @@ -99,7 +100,7 @@ impl, H: Hasher> TrieBackendEssence where H::Out: } }; - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral { storage: &self.storage, overlay: &mut read_overlay, @@ -112,7 +113,7 @@ impl, H: Hasher> TrieBackendEssence where H::Out: /// Execute given closure for all keys starting with prefix. pub fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { - let mut read_overlay = MemoryDB::default(); + let mut read_overlay = S::Overlay::default(); let eph = Ephemeral { storage: &self.storage, overlay: &mut read_overlay, @@ -145,7 +146,7 @@ impl, H: Hasher> TrieBackendEssence where H::Out: pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { storage: &'a S, - overlay: &'a mut MemoryDB, + overlay: &'a mut S::Overlay, } impl<'a, @@ -171,7 +172,7 @@ impl<'a, } impl<'a, S: TrieBackendStorage, H: Hasher> Ephemeral<'a, S, H> { - pub fn new(storage: &'a S, overlay: &'a mut MemoryDB) -> Self { + pub fn new(storage: &'a S, overlay: &'a mut S::Overlay) -> Self { Ephemeral { storage, overlay, @@ -187,10 +188,10 @@ impl<'a, where H::Out: HeapSizeOf { fn get(&self, key: &H::Out) -> Option { - if let Some(val) = hash_db::PlainDB::get(self.overlay, key) { + if let Some(val) = hash_db::HashDB::get(self.overlay, key, &[]) { Some(val) } else { - match self.storage.get(&key) { + match self.storage.get(&key, &[]) { Ok(x) => x, Err(e) => { warn!(target: "trie", "Failed to read from DB: {}", e); @@ -201,15 +202,15 @@ impl<'a, } fn contains(&self, key: &H::Out) -> bool { - hash_db::PlainDB::get(self, key).is_some() + hash_db::HashDB::get(self, key, &[]).is_some() } fn emplace(&mut self, key: H::Out, value: DBValue) { - hash_db::PlainDB::emplace(self.overlay, key, value) + hash_db::HashDB::emplace(self.overlay, key, &[], value) } fn remove(&mut self, key: &H::Out) { - hash_db::PlainDB::remove(self.overlay, key) + hash_db::HashDB::remove(self.overlay, key, &[]) } } @@ -231,11 +232,11 @@ impl<'a, for Ephemeral<'a, S, H> where H::Out: HeapSizeOf { - fn get(&self, key: &H::Out) -> Option { - if let Some(val) = hash_db::HashDB::get(self.overlay, key) { + fn get(&self, key: &H::Out, prefix: &[u8]) -> Option { + if let Some(val) = hash_db::HashDB::get(self.overlay, key, prefix) { Some(val) } else { - match self.storage.get(&key) { + match self.storage.get(&key, prefix) { Ok(x) => x, Err(e) => { warn!(target: "trie", "Failed to read from DB: {}", e); @@ -245,20 +246,20 @@ impl<'a, } } - fn contains(&self, key: &H::Out) -> bool { - hash_db::HashDB::get(self, key).is_some() + fn contains(&self, key: &H::Out, prefix: &[u8]) -> bool { + hash_db::HashDB::get(self, key, prefix).is_some() } - fn insert(&mut self, value: &[u8]) -> H::Out { - hash_db::HashDB::insert(self.overlay, value) + fn insert(&mut self, prefix: &[u8], value: &[u8]) -> H::Out { + hash_db::HashDB::insert(self.overlay, prefix, value) } - fn emplace(&mut self, key: H::Out, value: DBValue) { - hash_db::HashDB::emplace(self.overlay, key, value) + fn emplace(&mut self, key: H::Out, prefix: &[u8], value: DBValue) { + hash_db::HashDB::emplace(self.overlay, key, prefix, value) } - fn remove(&mut self, key: &H::Out) { - hash_db::HashDB::remove(self.overlay, key) + fn remove(&mut self, key: &H::Out, prefix: &[u8]) { + hash_db::HashDB::remove(self.overlay, key, prefix) } } @@ -269,33 +270,49 @@ impl<'a, for Ephemeral<'a, S, H> where H::Out: HeapSizeOf { - fn get(&self, key: &H::Out) -> Option { hash_db::HashDB::get(self, key) } - fn contains(&self, key: &H::Out) -> bool { hash_db::HashDB::contains(self, key) } + fn get(&self, key: &H::Out, prefix: &[u8]) -> Option { hash_db::HashDB::get(self, key, prefix) } + fn contains(&self, key: &H::Out, prefix: &[u8]) -> bool { hash_db::HashDB::contains(self, key, prefix) } } /// Key-value pairs storage that is used by trie backend essence. pub trait TrieBackendStorage: Send + Sync { + /// Type of in-memory overlay. + type Overlay: hash_db::HashDB + Default + Consolidate; /// Get the value stored at key. - fn get(&self, key: &H::Out) -> Result, String>; + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String>; } // This implementation is used by normal storage trie clients. impl TrieBackendStorage for Arc> { - fn get(&self, key: &H::Out) -> Result, String> { - Storage::::get(self.deref(), key) + type Overlay = PrefixedMemoryDB; + + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String> { + Storage::::get(self.deref(), key, prefix) } } // This implementation is used by test storage trie clients. +impl TrieBackendStorage for PrefixedMemoryDB { + type Overlay = PrefixedMemoryDB; + + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String> { + Ok(hash_db::HashDB::get(self, key, prefix)) + } +} + impl TrieBackendStorage for MemoryDB { - fn get(&self, key: &H::Out) -> Result, String> { - Ok(hash_db::PlainDB::get(self, key)) + type Overlay = MemoryDB; + + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String> { + Ok(hash_db::HashDB::get(self, key, prefix)) } } // This implementation is used by changes trie clients. impl<'a, S, H: Hasher> TrieBackendStorage for &'a S where S: ChangesTrieStorage { - fn get(&self, key: &H::Out) -> Result, String> { - ChangesTrieStorage::::get(*self, key) + type Overlay = MemoryDB; + + fn get(&self, key: &H::Out, prefix: &[u8]) -> Result, String> { + ChangesTrieStorage::::get(*self, key, prefix) } } diff --git a/core/telemetry/src/lib.rs b/core/telemetry/src/lib.rs index 37bb8c1a8e7e3ac9e3bfbde3e61e8bdf0f18618c..fba75c196aa369401e2de149ef69add7dc677b87 100644 --- a/core/telemetry/src/lib.rs +++ b/core/telemetry/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -93,7 +93,7 @@ impl Drain for Multiply { } } -/// Initialise telemetry. +/// Initialize telemetry. pub fn init_telemetry(config: TelemetryConfig) -> slog_scope::GlobalLoggerGuard { let mut endpoint_drains: Vec>> = Vec::new(); let mut out_syncs = Vec::new(); diff --git a/core/test-client/Cargo.toml b/core/test-client/Cargo.toml index 821e87da4004f26a8b55e12ff8ecbecb89f5d6a1..5049b2ff9fd62d5511b246a0a90bf25d6be8bd40 100644 --- a/core/test-client/Cargo.toml +++ b/core/test-client/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" client = { package = "substrate-client", path = "../client" } client-db = { package = "substrate-client-db", path = "../client/db", features = ["test-helpers"] } futures = { version = "0.1.17" } -parity-codec = "3.1" +parity-codec = "3.2" executor = { package = "substrate-executor", path = "../executor" } consensus = { package = "substrate-consensus-common", path = "../consensus/common" } keyring = { package = "substrate-keyring", path = "../../core/keyring" } diff --git a/core/test-client/src/block_builder_ext.rs b/core/test-client/src/block_builder_ext.rs index 68f4371d3e27a63b5b5e608e481c259caa37b97d..e427b5789291e705605b553332e0e7f21abffcd7 100644 --- a/core/test-client/src/block_builder_ext.rs +++ b/core/test-client/src/block_builder_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ //! Block Builder extensions for tests. use client; -use keyring; +use super::AccountKeyring; use runtime; use runtime_primitives::traits::ProvideRuntimeApi; use client::block_builder::api::BlockBuilder; @@ -38,9 +38,8 @@ impl<'a, A> BlockBuilderExt for client::block_builder::BlockBuilder<'a, runtime: } fn sign_tx(transfer: runtime::Transfer) -> runtime::Extrinsic { - let signature = keyring::Keyring::from_raw_public(transfer.from.to_fixed_bytes()) + let signature = AccountKeyring::from_public(&transfer.from) .unwrap() - .sign(&parity_codec::Encode::encode(&transfer)) - .into(); + .sign(&parity_codec::Encode::encode(&transfer)); runtime::Extrinsic::Transfer(transfer, signature) } diff --git a/core/test-client/src/client_ext.rs b/core/test-client/src/client_ext.rs index f766f427cd724494f7c34484977ce56af7bc4ddc..70e7feb0788828bd398fc9b007e7c8c705c9b63d 100644 --- a/core/test-client/src/client_ext.rs +++ b/core/test-client/src/client_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,6 +22,7 @@ use runtime_primitives::Justification; use runtime_primitives::generic::BlockId; use primitives::Blake2Hasher; use runtime; +use parity_codec::alloc::collections::hash_map::HashMap; /// Extension trait for a test client. pub trait TestClient: Sized { @@ -60,7 +61,7 @@ impl TestClient for Client fork_choice: ForkChoiceStrategy::LongestChain, }; - self.import_block(import, None).map(|_| ()) + self.import_block(import, HashMap::new()).map(|_| ()) } fn import_justified(&self, origin: BlockOrigin, block: runtime::Block, justification: Justification) @@ -77,7 +78,7 @@ impl TestClient for Client fork_choice: ForkChoiceStrategy::LongestChain, }; - self.import_block(import, None).map(|_| ()) + self.import_block(import, HashMap::new()).map(|_| ()) } fn finalize_block(&self, id: BlockId, justification: Option) -> client::error::Result<()> { diff --git a/core/test-client/src/lib.rs b/core/test-client/src/lib.rs index bd2d3a298a04422a58cb4728661874dd91661c78..4a99df65a5467c07d7ce4a29c0a0253d232b39df 100644 --- a/core/test-client/src/lib.rs +++ b/core/test-client/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -29,9 +29,9 @@ pub use client::ExecutionStrategies; pub use client::blockchain; pub use client::backend; pub use executor::NativeExecutor; -pub use keyring; pub use runtime; pub use consensus; +pub use keyring::{AuthorityKeyring, AccountKeyring}; use std::sync::Arc; use futures::future::FutureResult; @@ -39,7 +39,6 @@ use primitives::Blake2Hasher; use runtime_primitives::StorageOverlay; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, NumberFor}; use runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; -use keyring::Keyring; use state_machine::ExecutionStrategy; use client::LocalCallExecutor; @@ -129,6 +128,7 @@ pub fn new_with_execution_strategy( syncing: execution_strategy, importing: execution_strategy, block_construction: execution_strategy, + offchain_worker: execution_strategy, other: execution_strategy, }; @@ -165,10 +165,16 @@ pub fn new_with_backend( fn genesis_config(support_changes_trie: bool) -> GenesisConfig { GenesisConfig::new(support_changes_trie, vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Bob.to_raw_public().into(), - Keyring::Charlie.to_raw_public().into(), - ], 1000) + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Bob.into(), + AuthorityKeyring::Charlie.into(), + ], vec![ + AccountKeyring::Alice.into(), + AccountKeyring::Bob.into(), + AccountKeyring::Charlie.into(), + ], + 1000 + ) } fn genesis_storage(support_changes_trie: bool) -> StorageOverlay { diff --git a/core/test-client/src/trait_tests.rs b/core/test-client/src/trait_tests.rs index 8242f30d2e23f412477a8bdfb0753dea53469084..aa51f7d8bf9e33b24bad88060c5b8dca23a04018 100644 --- a/core/test-client/src/trait_tests.rs +++ b/core/test-client/src/trait_tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,10 +20,9 @@ #![allow(missing_docs)] use std::sync::Arc; -use keyring::Keyring; use consensus::BlockOrigin; use primitives::Blake2Hasher; -use crate::TestClient; +use crate::{TestClient, AccountKeyring}; use runtime_primitives::traits::Block as BlockT; use crate::backend; use crate::blockchain::{Backend as BlockChainBackendT, HeaderBackend}; @@ -88,8 +87,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -117,8 +116,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -132,8 +131,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); @@ -180,8 +179,8 @@ pub fn test_children_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -200,8 +199,8 @@ pub fn test_children_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -212,8 +211,8 @@ pub fn test_children_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); @@ -269,8 +268,8 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc(backend: Arc(backend: Arc, - pub authorities: Vec, - pub balances: Vec<(Ed25519AuthorityId, u64)>, + pub authorities: Vec, + pub balances: Vec<(AccountId, u64)>, } impl GenesisConfig { - pub fn new_simple(authorities: Vec, balance: u64) -> Self { - Self::new(false, authorities, balance) - } - - pub fn new(support_changes_trie: bool, authorities: Vec, balance: u64) -> Self { + pub fn new(support_changes_trie: bool, authorities: Vec, endowed_accounts: Vec, balance: u64) -> Self { GenesisConfig { changes_trie_config: match support_changes_trie { true => Some(super::changes_trie_config()), false => None, }, authorities: authorities.clone(), - balances: authorities.into_iter().map(|a| (a, balance)).collect(), + balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(), } } pub fn genesis_map(&self) -> HashMap, Vec> { let wasm_runtime = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm").to_vec(); let mut map: HashMap, Vec> = self.balances.iter() - .map(|&(account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) + .map(|&(ref account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) .map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec())) .chain(vec![ (well_known_keys::CODE.into(), wasm_runtime), diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 1aa172fd60d22daa1c1f6f987db35b7f5b64356d..028bb7ba52b2a2ed45bd5e8d2ffd5ad87c2c7207 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,7 +18,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(feature = "std")] pub mod genesismap; +#[cfg(feature = "std")] +pub mod genesismap; pub mod system; use rstd::{prelude::*, marker::PhantomData}; @@ -29,16 +30,16 @@ use substrate_client::{ impl_runtime_apis, }; use runtime_primitives::{ - ApplyResult, Ed25519Signature, transaction_validity::TransactionValidity, + ApplyResult, transaction_validity::TransactionValidity, create_runtime_str, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, - GetNodeBlockType, GetRuntimeBlockType, + GetNodeBlockType, GetRuntimeBlockType, AuthorityIdFor, }, }; use runtime_version::RuntimeVersion; pub use primitives::hash::H256; -use primitives::{Ed25519AuthorityId, OpaqueMetadata}; +use primitives::{ed25519, sr25519, OpaqueMetadata}; #[cfg(any(feature = "std", test))] use runtime_version::NativeVersion; use inherents::{CheckInherentsResult, InherentData}; @@ -77,12 +78,23 @@ pub struct Transfer { pub nonce: u64, } +impl Transfer { + /// Convert into a signed extrinsic. + #[cfg(feature = "std")] + pub fn into_signed_tx(self) -> Extrinsic { + let signature = keyring::AccountKeyring::from_public(&self.from) + .expect("Creates keyring from public key.").sign(&self.encode()).into(); + Extrinsic::Transfer(self, signature) + } +} + /// Extrinsic for test-runtime. #[derive(Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] pub enum Extrinsic { - AuthoritiesChange(Vec), - Transfer(Transfer, Ed25519Signature), + AuthoritiesChange(Vec), + Transfer(Transfer, AccountSignature), + IncludeData(Vec), } #[cfg(feature = "std")] @@ -106,6 +118,7 @@ impl BlindCheckable for Extrinsic { Err(runtime_primitives::BAD_SIGNATURE) } }, + Extrinsic::IncludeData(data) => Ok(Extrinsic::IncludeData(data)), } } } @@ -125,8 +138,14 @@ impl Extrinsic { } } +// The identity type used by authorities. +pub type AuthorityId = ed25519::Public; +// The signature type used by authorities. +pub type AuthoritySignature = ed25519::Signature; /// An identifier for an account on this system. -pub type AccountId = H256; +pub type AccountId = sr25519::Public; +// The signature type used by accounts/transactions. +pub type AccountSignature = sr25519::Signature; /// A simple hash type for all our hashing. pub type Hash = H256; /// The block number type used in this runtime. @@ -134,7 +153,7 @@ pub type BlockNumber = u64; /// Index of a transaction. pub type Index = u64; /// The item of a block digest. -pub type DigestItem = runtime_primitives::generic::DigestItem; +pub type DigestItem = runtime_primitives::generic::DigestItem; /// The digest of a block. pub type Digest = runtime_primitives::generic::Digest; /// A test block. @@ -148,9 +167,9 @@ pub fn run_tests(mut input: &[u8]) -> Vec { print("run_tests..."); let block = Block::decode(&mut input).unwrap(); - print("deserialised block."); + print("deserialized block."); let stxs = block.extrinsics.iter().map(Encode::encode).collect::>(); - print("reserialised transactions."); + print("reserialized transactions."); [stxs.len() as u8].encode() } @@ -197,7 +216,7 @@ cfg_if! { pub trait TestAPI { /// Return the balance of the given account id. fn balance_of(id: AccountId) -> u64; - /// A benchmkark function that adds one to the given value and returns the result. + /// A benchmark function that adds one to the given value and returns the result. fn benchmark_add_one(val: &u64) -> u64; /// A benchmark function that adds one to each value in the given vector and returns the /// result. @@ -213,6 +232,8 @@ cfg_if! { fn function_signature_changed() -> u64; fn fail_on_native() -> u64; fn fail_on_wasm() -> u64; + fn benchmark_indirect_call() -> u64; + fn benchmark_direct_call() -> u64; } } } else { @@ -220,7 +241,7 @@ cfg_if! { pub trait TestAPI { /// Return the balance of the given account id. fn balance_of(id: AccountId) -> u64; - /// A benchmkark function that adds one to the given value and returns the result. + /// A benchmark function that adds one to the given value and returns the result. fn benchmark_add_one(val: &u64) -> u64; /// A benchmark function that adds one to each value in the given vector and returns the /// result. @@ -233,6 +254,8 @@ cfg_if! { fn function_signature_changed() -> Vec; fn fail_on_native() -> u64; fn fail_on_wasm() -> u64; + fn benchmark_indirect_call() -> u64; + fn benchmark_direct_call() -> u64; } } } @@ -248,6 +271,16 @@ impl GetRuntimeBlockType for Runtime { type RuntimeBlock = Block; } +/// Adds one to the given input and returns the final result. +#[inline(never)] +fn benchmark_add_one(i: u64) -> u64 { + i + 1 +} + +/// The `benchmark_add_one` function as function pointer. +#[cfg(not(feature = "std"))] +static BENCHMARK_ADD_ONE: runtime_io::ExchangeableFunction u64> = runtime_io::ExchangeableFunction::new(benchmark_add_one); + cfg_if! { if #[cfg(feature = "std")] { impl_runtime_apis! { @@ -256,16 +289,12 @@ cfg_if! { version() } - fn authorities() -> Vec { - system::authorities() - } - fn execute_block(block: Block) { system::execute_block(block) } - fn initialise_block(header: &::Header) { - system::initialise_block(header) + fn initialize_block(header: &::Header) { + system::initialize_block(header) } } @@ -286,8 +315,8 @@ cfg_if! { system::execute_transaction(extrinsic) } - fn finalise_block() -> ::Header { - system::finalise_block() + fn finalize_block() -> ::Header { + system::finalize_block() } fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { @@ -334,11 +363,31 @@ cfg_if! { fn fail_on_wasm() -> u64 { 1 } + fn benchmark_indirect_call() -> u64 { + let function = benchmark_add_one; + (0..1000).fold(0, |p, i| p + function(i)) + } + fn benchmark_direct_call() -> u64 { + (0..1000).fold(0, |p, i| p + benchmark_add_one(i)) + } } impl consensus_aura::AuraApi for Runtime { fn slot_duration() -> u64 { 1 } } + + impl offchain_primitives::OffchainWorkerApi for Runtime { + fn offchain_worker(block: u64) { + let ex = Extrinsic::IncludeData(block.encode()); + runtime_io::submit_extrinsic(&ex) + } + } + + impl consensus_authorities::AuthoritiesApi for Runtime { + fn authorities() -> Vec> { + crate::system::authorities() + } + } } } else { impl_runtime_apis! { @@ -347,16 +396,12 @@ cfg_if! { version() } - fn authorities() -> Vec { - system::authorities() - } - fn execute_block(block: Block) { system::execute_block(block) } - fn initialise_block(header: &::Header) { - system::initialise_block(header) + fn initialize_block(header: &::Header) { + system::initialize_block(header) } } @@ -377,8 +422,8 @@ cfg_if! { system::execute_transaction(extrinsic) } - fn finalise_block() -> ::Header { - system::finalise_block() + fn finalize_block() -> ::Header { + system::finalize_block() } fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { @@ -429,11 +474,32 @@ cfg_if! { fn fail_on_wasm() -> u64 { panic!("Failing because we are on wasm") } + + fn benchmark_indirect_call() -> u64 { + (0..10000).fold(0, |p, i| p + BENCHMARK_ADD_ONE.get()(i)) + } + + fn benchmark_direct_call() -> u64 { + (0..10000).fold(0, |p, i| p + benchmark_add_one(i)) + } } impl consensus_aura::AuraApi for Runtime { fn slot_duration() -> u64 { 1 } } + + impl offchain_primitives::OffchainWorkerApi for Runtime { + fn offchain_worker(block: u64) { + let ex = Extrinsic::IncludeData(block.encode()); + runtime_io::submit_extrinsic(&ex) + } + } + + impl consensus_authorities::AuthoritiesApi for Runtime { + fn authorities() -> Vec> { + crate::system::authorities() + } + } } } -} +} \ No newline at end of file diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 110666a6e06a0db7ec8f83fdd48237d4030b488a..a119c8b62db4019b6f3b92dd8fb1b0ca7e51a162 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,13 +21,13 @@ use rstd::prelude::*; use runtime_io::{storage_root, enumerated_trie_root, storage_changes_root, twox_128}; use runtime_support::storage::{self, StorageValue, StorageMap}; use runtime_support::storage_items; -use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Digest as DigestT}; +use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Digest as DigestT, NumberFor, Block as BlockT}; use runtime_primitives::generic; use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity}; use parity_codec::{KeyedVec, Encode}; use super::{AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest}; -use primitives::{Ed25519AuthorityId, Blake2Hasher}; -use primitives::storage::well_known_keys; +use primitives::{Blake2Hasher, storage::well_known_keys}; +use primitives::ed25519::Public as AuthorityId; const NONCE_OF: &[u8] = b"nonce:"; const BALANCE_OF: &[u8] = b"balance:"; @@ -37,7 +37,7 @@ storage_items! { // The current block number being processed. Set by `execute_block`. Number: b"sys:num" => required BlockNumber; ParentHash: b"sys:pha" => required Hash; - NewAuthorities: b"sys:new_auth" => Vec; + NewAuthorities: b"sys:new_auth" => Vec; } pub fn balance_of_key(who: AccountId) -> Vec { @@ -52,8 +52,8 @@ pub fn nonce_of(who: AccountId) -> u64 { storage::get_or(&who.to_keyed_vec(NONCE_OF), 0) } -/// Get authorities ar given block. -pub fn authorities() -> Vec { +/// Get authorities at given block. +pub fn authorities() -> Vec { let len: u32 = storage::unhashed::get(well_known_keys::AUTHORITY_COUNT) .expect("There are always authorities in test-runtime"); (0..len) @@ -63,31 +63,65 @@ pub fn authorities() -> Vec { .collect() } -pub fn initialise_block(header: &Header) { +pub fn initialize_block(header: &Header) { // populate environment. ::put(&header.number); ::put(&header.parent_hash); storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); } +fn execute_extrinsics_without_checks(extrinsics: Vec<::Extrinsic>) { + // execute transactions + extrinsics.into_iter().enumerate().for_each(|(i, e)| { + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); + execute_transaction_backend(&e).unwrap_or_else(|_| panic!("Invalid transaction")); + storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); + }); +} + /// Actually execute all transitioning for `block`. -pub fn execute_block(block: Block) { - let ref header = block.header; +pub fn polish_block(block: &mut Block) { + let header = &mut block.header; // check transaction trie root represents the transactions. let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); let txs = txs.iter().map(Vec::as_slice).collect::>(); let txs_root = enumerated_trie_root::(&txs).into(); info_expect_equal_hash(&txs_root, &header.extrinsics_root); - assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); + header.extrinsics_root = txs_root; // execute transactions block.extrinsics.iter().enumerate().for_each(|(i, e)| { storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - execute_transaction_backend(e).map_err(|_| ()).expect("Extrinsic error"); + execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); }); + header.state_root = storage_root().into(); + + // check digest + let mut digest = Digest::default(); + if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into(), header.number - 1) { + digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); + } + if let Some(new_authorities) = ::take() { + digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); + } + header.digest = digest; +} + +pub fn execute_block(block: Block) { + let ref header = block.header; + + // check transaction trie root represents the transactions. + let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); + let txs = txs.iter().map(Vec::as_slice).collect::>(); + let txs_root = enumerated_trie_root::(&txs).into(); + info_expect_equal_hash(&txs_root, &header.extrinsics_root); + assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); + + execute_extrinsics_without_checks(block.extrinsics); + // check storage root. let storage_root = storage_root().into(); info_expect_equal_hash(&storage_root, &header.state_root); @@ -104,6 +138,19 @@ pub fn execute_block(block: Block) { assert!(digest == header.digest, "Header digest items must match that calculated."); } +/// The block executor. +pub struct BlockExecutor; + +impl executive::ExecuteBlock for BlockExecutor { + fn execute_block(block: Block) { + execute_block(block); + } + + fn execute_extrinsics_without_checks(_: NumberFor, extrinsics: Vec<::Extrinsic>) { + execute_extrinsics_without_checks(extrinsics); + } +} + /// Execute a transaction outside of the block execution function. /// This doesn't attempt to validate anything regarding the block. pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { @@ -122,7 +169,7 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { } let hash = |from: &AccountId, nonce: u64| { - twox_128(&nonce.to_keyed_vec(from.as_bytes())).to_vec() + twox_128(&nonce.to_keyed_vec(&from.encode())).to_vec() }; let requires = if tx.nonce != expected_nonce && tx.nonce > 0 { let mut deps = Vec::new(); @@ -144,7 +191,6 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { } } - /// Execute a transaction outside of the block execution function. /// This doesn't attempt to validate anything regarding the block. pub fn execute_transaction(utx: Extrinsic) -> ApplyResult { @@ -155,8 +201,8 @@ pub fn execute_transaction(utx: Extrinsic) -> ApplyResult { result } -/// Finalise the block. -pub fn finalise_block() -> Header { +/// Finalize the block. +pub fn finalize_block() -> Header { let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap(); let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect(); let txs = txs.iter().map(Vec::as_slice).collect::>(); @@ -196,6 +242,7 @@ fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { match utx { Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), + Extrinsic::IncludeData(_) => Ok(ApplyOutcome::Success), } } @@ -225,8 +272,8 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { Ok(ApplyOutcome::Success) } -fn execute_new_authorities_backend(new_authorities: &[Ed25519AuthorityId]) -> ApplyResult { - let new_authorities: Vec = new_authorities.iter().cloned().collect(); +fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult { + let new_authorities: Vec = new_authorities.iter().cloned().collect(); ::put(new_authorities); Ok(ApplyOutcome::Success) } @@ -258,12 +305,11 @@ mod tests { use runtime_io::{with_externalities, twox_128, TestExternalities}; use parity_codec::{Joiner, KeyedVec}; - use keyring::Keyring; - use crate::{Header, Digest, Extrinsic, Transfer}; + use substrate_test_client::{AuthorityKeyring, AccountKeyring}; + use crate::{Header, Transfer}; use primitives::{Blake2Hasher, map}; use primitives::storage::well_known_keys; use substrate_executor::WasmExecutor; - use hex_literal::{hex, hex_impl}; const WASM_CODE: &'static [u8] = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"); @@ -272,36 +318,29 @@ mod tests { TestExternalities::new(map![ twox_128(b"latest").to_vec() => vec![69u8; 32], twox_128(well_known_keys::AUTHORITY_COUNT).to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Alice.to_raw_public().to_vec(), - twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Bob.to_raw_public().to_vec(), - twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Charlie.to_raw_public().to_vec(), - twox_128(&Keyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Alice.to_raw_public().to_vec(), + twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Bob.to_raw_public().to_vec(), + twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Charlie.to_raw_public().to_vec(), + twox_128(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ]) } - fn construct_signed_tx(tx: Transfer) -> Extrinsic { - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); - Extrinsic::Transfer(tx, signature) - } - fn block_import_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { - let mut t = new_test_ext(); - let h = Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("e51369d0b37e4aa1383f1e7a34c2eec75f18ee6b4b199a440f4f2456906e0eb7").into(), - extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }; - - let b = Block { + let mut b = Block { header: h, extrinsics: vec![], }; - block_executor(b, &mut t); + with_externalities(&mut new_test_ext(), || polish_block(&mut b)); + block_executor(b, &mut new_test_ext()); } #[test] @@ -321,69 +360,74 @@ mod tests { } fn block_import_with_transaction_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 111); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 0); - }); - - let b = Block { + let mut b1 = Block { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("f61a14ce70846cd6a1714bbe1b63b2ca1172df1c8c01adfd798bb08bd30dc486").into(), - extrinsics_root: hex!("198205cb7729fec8ccdc2e58571a4858586a4f305898078e0e8bee1dddea7e4b").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }, extrinsics: vec![ - construct_signed_tx(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Bob.to_raw_public().into(), + Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), amount: 69, nonce: 0, - }) + }.into_signed_tx() ], }; - with_externalities(&mut t, || { - execute_block(b.clone()); - - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 42); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 69); - }); + let mut dummy_ext = new_test_ext(); + with_externalities(&mut dummy_ext, || polish_block(&mut b1)); - let b = Block { + let mut b2 = Block { header: Header { - parent_hash: b.header.hash(), + parent_hash: b1.header.hash(), number: 2, - state_root: hex!("a47383d9a5d6c8c7531386abccdf512c76729a1a19c59b6c2e4f95dde419923a").into(), - extrinsics_root: hex!("041fa8971dda28745967179a9f39e3ca1a595c510682105df1cff74ae6f05e0d").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }, extrinsics: vec![ - construct_signed_tx(Transfer { - from: Keyring::Bob.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + Transfer { + from: AccountKeyring::Bob.into(), + to: AccountKeyring::Alice.into(), amount: 27, nonce: 0, - }), - construct_signed_tx(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Charlie.to_raw_public().into(), + }.into_signed_tx(), + Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Charlie.into(), amount: 69, nonce: 1, - }), + }.into_signed_tx(), ], }; - block_executor(b, &mut t); + with_externalities(&mut dummy_ext, || polish_block(&mut b2)); + drop(dummy_ext); + + let mut t = new_test_ext(); with_externalities(&mut t, || { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 111); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 0); + }); + + block_executor(b1, &mut t); - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 0); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 42); - assert_eq!(balance_of(Keyring::Charlie.to_raw_public().into()), 69); + with_externalities(&mut t, || { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 42); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 69); + }); + + block_executor(b2, &mut t); + + with_externalities(&mut t, || { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 0); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 42); + assert_eq!(balance_of(AccountKeyring::Charlie.into()), 69); }); } diff --git a/core/test-runtime/wasm/Cargo.lock b/core/test-runtime/wasm/Cargo.lock index 1dae80fcbadf91fcaa7af938cfcbc2941ecb322a..e3c211fa936c992ea2c181aab2dda15fbf2b2f7e 100644 --- a/core/test-runtime/wasm/Cargo.lock +++ b/core/test-runtime/wasm/Cargo.lock @@ -1,5 +1,57 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aes-ctr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aes-soft" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aesni" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aio-limited" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayref" version = "0.3.5" @@ -7,49 +59,102 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arrayvec" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "asn1_der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "asn1_der_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base-x" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "base58" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bigint" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitmask" +version = "0.5.0" +source = "git+https://github.com/paritytech/bitmask#a84e147be602631617badd18b6b9af83391db4a9" + +[[package]] +name = "blake2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -69,7 +174,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-cipher-trait" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -81,6 +194,11 @@ dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bs58" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byte-tools" version = "0.2.0" @@ -93,26 +211,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.7" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -122,7 +245,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -130,7 +253,7 @@ name = "clear_on_drop" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -148,46 +271,105 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crossbeam" -version = "0.2.12" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "crossbeam-channel" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.6.2" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.6.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" -version = "0.6.2" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -209,18 +391,50 @@ dependencies = [ "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ctr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cuckoofilter" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "curve25519-dalek" -version = "1.0.3" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "data-encoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "digest" version = "0.6.2" @@ -237,21 +451,40 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ed25519-dalek" version = "1.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -259,7 +492,7 @@ dependencies = [ [[package]] name = "environmental" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -267,13 +500,28 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "fake-simd" @@ -285,10 +533,10 @@ name = "fixed-hash" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -311,6 +559,11 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -330,6 +583,15 @@ name = "futures" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "generic-array" version = "0.8.3" @@ -349,17 +611,26 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "heapsize" version = "0.4.2" @@ -368,9 +639,22 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hex-literal" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -395,6 +679,15 @@ dependencies = [ "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hmac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hmac-drbg" version = "0.1.2" @@ -417,7 +710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -425,7 +718,7 @@ name = "impl-codec" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -434,7 +727,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -447,7 +740,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -475,18 +768,13 @@ name = "kvdb" version = "0.1.0" source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", ] [[package]] name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -496,37 +784,356 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "libsecp256k1" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-core-derive 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-dns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-floodsub 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-kad 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-mdns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-mplex 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-noise 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-plaintext 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ratelimit 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-secio 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-tcp 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-uds 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-yamux 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p-core" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "log" -version = "0.4.6" +name = "libp2p-core-derive" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-dns" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-floodsub" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-identify" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-kad" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mdns" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mplex" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-noise" +version = "0.3.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ping" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-plaintext" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ratelimit" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-secio" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-tcp" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-uds" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-yamux" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libsecp256k1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -534,6 +1141,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memoffset" version = "0.2.1" @@ -541,10 +1153,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memory-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -555,14 +1167,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "merlin" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -575,11 +1186,11 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -591,7 +1202,7 @@ dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -600,7 +1211,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -615,13 +1226,27 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "multistream-select" +version = "0.3.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -630,6 +1255,11 @@ name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "nohash-hasher" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num-integer" version = "0.1.39" @@ -645,16 +1275,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "once_cell" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "opaque-debug" @@ -663,28 +1296,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.16" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.40" +version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "owning_ref" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" version = "0.4.0" @@ -700,12 +1342,12 @@ source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7 [[package]] name = "parity-codec" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -714,9 +1356,36 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multiaddr" +version = "0.2.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multihash" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -724,7 +1393,16 @@ name = "parity-wasm" version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -745,15 +1423,26 @@ dependencies = [ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -762,10 +1451,10 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -784,9 +1473,19 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -831,9 +1530,9 @@ name = "proc-macro-hack" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -843,80 +1542,106 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "protobuf" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quick-error" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -924,54 +1649,127 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_isaac" -version = "0.1.1" +name = "rayon-core" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_pcg" -version = "0.1.1" +name = "rdrand" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_xorshift" -version = "0.1.0" +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "redox_syscall" -version = "0.1.43" +name = "regex-syntax" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "ring" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -987,23 +1785,59 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rw-stream-sink" +version = "0.1.1" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ryu" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "safe-mix" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "schnorrkel" version = "0.0.0" +source = "git+https://github.com/w3f/schnorrkel#3179838da9dd4896c12bb910e7c42477a3250641" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schnorrkel" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1013,6 +1847,16 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "secp256k1" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -1028,27 +1872,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.81" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.81" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.33" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1093,7 +1937,7 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1117,27 +1961,41 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "slog-scope" -version = "4.0.1" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "snow" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1151,19 +2009,19 @@ version = "0.1.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sr-io" version = "0.1.0" dependencies = [ - "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1179,9 +2037,9 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1199,20 +2057,33 @@ name = "sr-version" version = "0.1.0" dependencies = [ "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", +] + +[[package]] +name = "srml-executive" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", ] [[package]] name = "srml-metadata" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", ] @@ -1221,12 +2092,13 @@ dependencies = [ name = "srml-support" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1239,11 +2111,11 @@ dependencies = [ name = "srml-support-procedural" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "srml-support-procedural-tools 0.1.0", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1251,19 +2123,35 @@ name = "srml-support-procedural-tools" version = "0.1.0" dependencies = [ "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "srml-support-procedural-tools-derive 0.1.0", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools-derive" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-system" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "substrate-primitives 0.1.0", ] [[package]] @@ -1276,6 +2164,90 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "static_slice" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stdweb" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-macros 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stream-cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strum" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strum_macros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-bip39" +version = "0.2.0" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" +dependencies = [ + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-client" version = "0.1.0" @@ -1283,12 +2255,12 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "sr-primitives 0.1.0", @@ -1308,39 +2280,55 @@ dependencies = [ name = "substrate-consensus-aura-primitives" version = "0.1.0" dependencies = [ + "sr-primitives 0.1.0", + "substrate-client 0.1.0", +] + +[[package]] +name = "substrate-consensus-authorities" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", + "srml-support 0.1.0", "substrate-client 0.1.0", + "substrate-primitives 0.1.0", ] [[package]] name = "substrate-consensus-common" version = "0.1.0" dependencies = [ - "crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", - "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-executor" version = "0.1.0" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", "substrate-panic-handler 0.1.0", @@ -1356,7 +2344,7 @@ dependencies = [ name = "substrate-inherents" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1366,16 +2354,26 @@ dependencies = [ name = "substrate-keyring" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-offchain-primitives" +version = "0.1.0" +dependencies = [ + "sr-primitives 0.1.0", + "substrate-client 0.1.0", +] + [[package]] name = "substrate-panic-handler" version = "0.1.0" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1385,21 +2383,25 @@ version = "0.1.0" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1409,41 +2411,41 @@ dependencies = [ name = "substrate-serializer" version = "0.1.0" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-state-machine" version = "0.1.0" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-telemetry" version = "0.3.1" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1451,21 +2453,24 @@ dependencies = [ name = "substrate-test-runtime" version = "0.1.0" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", + "srml-executive 0.1.0", "srml-support 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-authorities 0.1.0", "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", + "substrate-offchain-primitives 0.1.0", "substrate-primitives 0.1.0", ] @@ -1480,13 +2485,18 @@ dependencies = [ name = "substrate-trie" version = "0.4.0" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "subtle" version = "2.0.0" @@ -1494,11 +2504,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.26" +version = "0.15.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1512,19 +2533,33 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "time" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tiny-keccak" version = "1.4.2" @@ -1533,26 +2568,38 @@ dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tk-listen" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1560,101 +2607,125 @@ name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-dns-unofficial" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-tcp" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1662,30 +2733,30 @@ name = "tokio-udp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1693,26 +2764,36 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.11.0" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "twofish" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1720,7 +2801,7 @@ name = "twox-hash" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1728,12 +2809,17 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1749,7 +2835,15 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.7" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1758,11 +2852,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "unreachable" -version = "1.0.0" +name = "unsigned-varint" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1780,6 +2875,11 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" version = "0.2.6" @@ -1795,7 +2895,7 @@ name = "wasmi" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1834,16 +2934,16 @@ name = "ws" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1856,59 +2956,124 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "x25519-dalek" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "yamux" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zeroize" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] +"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f10b352bc3fc08ae24dc5d2d3ddcac153678533986122dc283d747b12071000" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9893d63fc3b1c44231e667da6836a33f27d8b6b3bdc82f83da5dfd579d1b6528" +"checksum asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7f92edafad155aff997fa5b727c6429b91e996b5a5d62a2b0adbae1306b5fe" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d55aa264e822dbafa12db4d54767aff17c6ba55ea2d8559b3e17392c7d000e5d" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" +"checksum bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebecac13b3c745150d7b6c3ea7572d372f09d627c2077e893bf26c5c7f70d282" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)" = "" +"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" -"checksum crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8d4f5844607ce8da3fff431e7dba56cda8bfcc570aa50bee36adba8a32b8cad7" -"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3" -"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" -"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" "checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" -"checksum curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dae47cc3529cdab597dbc8b606e565707209b506e55848f3c15679214a56c956" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" +"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" +"checksum curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f8a6fc0376eb52dc18af94915cc04dfdf8353746c0e8c550ae683a0815e5c1" +"checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" "checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" "checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" -"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" -"checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" +"checksum environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c7464757b80de8930c91c9afe77ddce501826bf9d134a87db2c67d9dc177e2c" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" -"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" -"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07463834729d0ce8d475e7dd6d302e407093ad9a9c02d77eb07fb74b5373829d" +"checksum hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1224388a21c88a80ae7087a2a245ca6d80acc97a9186b75789fb3eeefd0609af" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" "checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" +"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" "checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" @@ -1920,42 +3085,67 @@ dependencies = [ "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-core-derive 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-dns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-floodsub 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-kad 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-mdns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-mplex 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-noise 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-plaintext 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-ratelimit 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-secio 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-tcp 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-uds 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-yamux 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" +"checksum memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd87d4d64f7b86d8804bbb419f8ecb187cb8f40a50e91c72848075c604ba88d" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9e97b439f6d38cbe2a4a4aa93f6770c5305f62761b78b1851406c09c87ee2a" +"checksum merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "83c2dda19c01176e8e7148f7bdb88bbdf215a8db0641f89fc40e4b81736aeda5" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum multistream-select 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d138afcce92d219ccb6eb53d9b1e8a96ac0d633cfd3c53cd9856d96d1741bb8" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum once_cell 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d7ce3535d54560c937c1652ba4a0da66bfc63e0f8e07bed127483afb6e5ee925" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" -"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" -"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" +"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" +"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" +"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67a4d27831e31e27f1454d6e3d3bb34bcac6bf7ad7032eed0ad0070dc8cf55c1" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" "checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" +"checksum parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" +"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" "checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" @@ -1963,74 +3153,109 @@ dependencies = [ "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" -"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24d5d73d2b88fddb8b8141f2730d950d88772c940ac4f8f3e93230b9a99d92df" +"checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" -"checksum ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "148fc853f6d85f53f5f315d46701eaacc565cdfb3cb1959730c96e81e7e49999" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe554f318830b48e5da8ab1ccb1ffd02b79228364dac7766b7cd1ec461ca5116" +"checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" +"checksum schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a700659388785588c75b197cecda0f23c7112a9281ef703e8ffc651061ce014c" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4070f3906e65249228094cf97b04a90799fba04468190bbbcfa812309cf86e32" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c91eb5b0190ae87b4e2e39cbba6e3bed3ac6186935fe265f0426156c4c49961b" -"checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" -"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" -"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" "checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -"checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5a64f02fd208ef15bd2d1a65861df4707e416151e1272d02c8faafad1c138100" "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362" +"checksum stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a3edad410e603184d656e2abded5fd4d3d6e93d5763d21130dbaf99795db74eb" +"checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" +"checksum stdweb-internal-macros 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1635afd059cbfac7d5b1274f0c44cec110c1e013c48e8bbc22e07e52696cf887" +"checksum stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a2f4a2eb556337b2d1a302630bbddf989ae383c70393e89b48152b9896cbda" +"checksum stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8861bc80f649f5b4c9bd38b696ae9af74499d479dbfb327f0607de6b326a36bc" +"checksum strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1810e25f576e7ffce1ff5243b37066da5ded0310b3274c20baaeccb1145b2806" +"checksum strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "572a2f4e53dd4c3483fd79e5cc10ddd773a3acb1169bbfe8762365e107110579" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1415431cb2398d84da64173f8473c792808314427d4a6f2f3ea85ae67239fe3" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" -"checksum tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "a7817d4c98cc5be21360b3b37d6036fe9b7aefa5b7a201b7b16ff33423822f7d" +"checksum tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5462b0f968c0457efe38fcd2df7e487096b992419e4f5337b06775a614bbda4b" +"checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" -"checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75" -"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" -"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" -"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912" -"checksum tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "56c5556262383032878afad66943926a1d1f0967f17e94bd7764ceceb3b70e7f" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" +"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99ce87382f6c1a24b513a72c048b2c8efe66cb5161c9061d00bee510f08dc168" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" -"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" +"checksum trie-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f23230c31251bdbdba89cd9caa0cbe2aa9e4aa5f92a80e6eb6296bb290e9146" +"checksum trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e45632ecaf2b8b4a40b5208383cd659b4e66f58ccd40086467a4614b45781430" +"checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c64cdf40b4a9645534a943668681bcb219faf51874d4b65d2e0abda1b10a2ab" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" @@ -2041,3 +3266,6 @@ dependencies = [ "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4aca1ba6bec2719576bd20dfe5b24d9359552e616d10bff257e50cd85f745d17" +"checksum yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "302defd1bed8a9a6d43b82f0e5a50510dfdfbbd02c270c93ff9d6f3f5e2dea89" +"checksum zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddfeb6eee2fb3b262ef6e0898a52b7563bb8e0d5955a313b3cf2f808246ea14" diff --git a/core/test-runtime/wasm/src/lib.rs b/core/test-runtime/wasm/src/lib.rs index fd89232f1550cdced022bbdd0b4c642df658ab3b..6620f276d0397fbd44840aef3f1500b2877798cb 100644 --- a/core/test-runtime/wasm/src/lib.rs +++ b/core/test-runtime/wasm/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 13b55df5d1434798d967fb35a1e13737b982c3fd..ac76f1c7ce0f3ce62d87a65937e585f03243e18e 100644 Binary files a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/core/transaction-pool/Cargo.toml b/core/transaction-pool/Cargo.toml index 4e8c4dd0f62257997488156fca8f74f4f7895040..1286b7bde4b093de55512f1fba4528ef44b8cf3c 100644 --- a/core/transaction-pool/Cargo.toml +++ b/core/transaction-pool/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" error-chain = "0.12" futures = "0.1" log = "0.4" -parity-codec = "3.1" +parity-codec = "3.2" parking_lot = "0.7.1" sr-primitives = { path = "../sr-primitives" } client = { package = "substrate-client", path = "../client" } diff --git a/core/transaction-pool/graph/Cargo.toml b/core/transaction-pool/graph/Cargo.toml index cd0e1ec274a6701de439a106d3767fbc0d6102cd..58aeec885d849e52e8fc6d34803c3a4984d8d271 100644 --- a/core/transaction-pool/graph/Cargo.toml +++ b/core/transaction-pool/graph/Cargo.toml @@ -11,9 +11,11 @@ log = "0.4" parking_lot = "0.7.1" serde = "1.0" serde_derive = "1.0" +substrate-primitives = { path = "../../primitives" } sr-primitives = { path = "../../sr-primitives" } [dev-dependencies] assert_matches = "1.1" -parity-codec = "3.1" +env_logger = "0.6" +parity-codec = "3.2" test_runtime = { package = "substrate-test-runtime", path = "../../test-runtime" } diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index e2d21de2140377163ea508592abbe93a134d22c0..ad434e57d45a21cdc2cec8a10984f1c782eb8a27 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,13 +19,16 @@ //! For a more full-featured pool, have a look at the `pool` module. use std::{ + collections::HashSet, + fmt, hash, sync::Arc, }; -use serde::Serialize; use error_chain::bail; use log::{trace, debug, warn}; +use serde::Serialize; +use substrate_primitives::hexdisplay::HexDisplay; use sr_primitives::traits::Member; use sr_primitives::transaction_validity::{ TransactionTag as Tag, @@ -82,7 +85,7 @@ pub struct PruneStatus { /// Immutable transaction #[cfg_attr(test, derive(Clone))] -#[derive(Debug, PartialEq, Eq)] +#[derive(PartialEq, Eq)] pub struct Transaction { /// Raw extrinsic representing that transaction. pub data: Extrinsic, @@ -100,6 +103,41 @@ pub struct Transaction { pub provides: Vec, } +impl fmt::Debug for Transaction where + Hash: fmt::Debug, + Extrinsic: fmt::Debug, +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn print_tags(fmt: &mut fmt::Formatter, tags: &[Tag]) -> fmt::Result { + let mut it = tags.iter(); + if let Some(t) = it.next() { + write!(fmt, "{}", HexDisplay::from(t))?; + } + for t in it { + write!(fmt, ",{}", HexDisplay::from(t))?; + } + Ok(()) + } + + write!(fmt, "Transaction {{ ")?; + write!(fmt, "hash: {:?}, ", &self.hash)?; + write!(fmt, "priority: {:?}, ", &self.priority)?; + write!(fmt, "valid_till: {:?}, ", &self.valid_till)?; + write!(fmt, "bytes: {:?}, ", &self.bytes)?; + write!(fmt, "requires: [")?; + print_tags(fmt, &self.requires)?; + write!(fmt, "], provides: [")?; + print_tags(fmt, &self.provides)?; + write!(fmt, "], ")?; + write!(fmt, "data: {:?}", &self.data)?; + write!(fmt, "}}")?; + Ok(()) + } +} + +/// Store last pruned tags for given number of invocations. +const RECENTLY_PRUNED_TAGS: usize = 2; + /// Transaction pool. /// /// Builds a dependency graph for all transactions in the pool and returns @@ -114,6 +152,12 @@ pub struct Transaction { pub struct BasePool { future: FutureTransactions, ready: ReadyTransactions, + /// Store recently pruned tags (for last two invocations). + /// + /// This is used to make sure we don't accidentally put + /// transactions to future in case they were just stuck in verification. + recently_pruned: [HashSet; RECENTLY_PRUNED_TAGS], + recently_pruned_index: usize, } impl Default for BasePool { @@ -121,6 +165,8 @@ impl Default for BasePool { BasePool { future: Default::default(), ready: Default::default(), + recently_pruned: Default::default(), + recently_pruned_index: 0, } } } @@ -141,7 +187,11 @@ impl BasePool BasePool) -> PruneStatus { let mut to_import = vec![]; let mut pruned = vec![]; + let recently_pruned = &mut self.recently_pruned[self.recently_pruned_index]; + self.recently_pruned_index = (self.recently_pruned_index + 1) % RECENTLY_PRUNED_TAGS; + recently_pruned.clear(); for tag in tags { // make sure to promote any future transactions that could be unlocked to_import.append(&mut self.future.satisfy_tags(::std::iter::once(&tag))); // and actually prune transactions in ready queue - pruned.append(&mut self.ready.prune_tags(tag)); + pruned.append(&mut self.ready.prune_tags(tag.clone())); + // store the tags for next submission + recently_pruned.insert(tag); } let mut promoted = vec![]; @@ -360,6 +415,7 @@ impl BasePool { /// Transaction details. pub transaction: Arc>, @@ -38,6 +39,23 @@ pub struct WaitingTransaction { pub imported_at: time::Instant, } +impl fmt::Debug for WaitingTransaction { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "WaitingTransaction {{ ")?; + write!(fmt, "imported_at: {:?}, ", self.imported_at)?; + write!(fmt, "transaction: {:?}, ", self.transaction)?; + write!(fmt, "missing_tags: {{")?; + let mut it = self.missing_tags.iter().map(|tag| HexDisplay::from(tag)); + if let Some(tag) = it.next() { + write!(fmt, "{}", tag)?; + } + for tag in it { + write!(fmt, ", {}", tag)?; + } + write!(fmt, " }}}}") + } +} + impl Clone for WaitingTransaction { fn clone(&self) -> Self { WaitingTransaction { @@ -53,10 +71,19 @@ impl WaitingTransaction { /// /// Computes the set of missing tags based on the requirements and tags that /// are provided by all transactions in the ready queue. - pub fn new(transaction: Transaction, provided: &HashMap) -> Self { + pub fn new( + transaction: Transaction, + provided: &HashMap, + recently_pruned: &[HashSet], + ) -> Self { let missing_tags = transaction.requires .iter() - .filter(|tag| !provided.contains_key(&**tag)) + .filter(|tag| { + // is true if the tag is already satisfied either via transaction in the pool + // or one that was recently included. + let is_provided = provided.contains_key(&**tag) || recently_pruned.iter().any(|x| x.contains(&**tag)); + !is_provided + }) .cloned() .collect(); diff --git a/core/transaction-pool/graph/src/lib.rs b/core/transaction-pool/graph/src/lib.rs index d30032830c7ad85be4b55c80cded3180baab2dca..ea890a5cd0f2182d3d85c95250bf37c6914957eb 100644 --- a/core/transaction-pool/graph/src/lib.rs +++ b/core/transaction-pool/graph/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/transaction-pool/graph/src/listener.rs b/core/transaction-pool/graph/src/listener.rs index e2dfaef915f5f66c070ec57cb846e9d41c02f38d..335ff8a0537e9e500e2cef19d5b202818efeeebd 100644 --- a/core/transaction-pool/graph/src/listener.rs +++ b/core/transaction-pool/graph/src/listener.rs @@ -1,5 +1,5 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -93,6 +93,6 @@ impl Listener { /// Transaction was pruned from the pool. pub fn pruned(&mut self, header_hash: H2, tx: &H) { - self.fire(tx, |watcher| watcher.finalised(header_hash)) + self.fire(tx, |watcher| watcher.finalized(header_hash)) } } diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index f705385f94aebc48c220f005c728f30f6e02d38d..91ded26630cf183eb3d1fcb98fe3681dcadf5372 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -176,6 +176,8 @@ impl Pool { let ready_limit = &self.options.ready; let future_limit = &self.options.future; + debug!(target: "txpool", "Pool Status: {:?}", status); + if ready_limit.is_exceeded(status.ready, status.ready_bytes) || future_limit.is_exceeded(status.future, status.future_bytes) { // clean up the pool @@ -453,12 +455,14 @@ mod tests { use super::*; use futures::Stream; use parity_codec::Encode; - use test_runtime::{Block, Extrinsic, Transfer, H256}; + use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; use assert_matches::assert_matches; use crate::watcher; #[derive(Debug, Default)] - struct TestApi; + struct TestApi { + delay: Mutex>>, + } impl ChainApi for TestApi { type Block = Block; @@ -467,9 +471,20 @@ mod tests { /// Verify extrinsic at given block. fn validate_transaction(&self, at: &BlockId, uxt: ExtrinsicFor) -> Result { + let block_number = self.block_id_to_number(at)?.unwrap(); let nonce = uxt.transfer().nonce; + // This is used to control the test flow. + if nonce > 0 { + let opt = self.delay.lock().take(); + if let Some(delay) = opt { + if delay.recv().is_err() { + println!("Error waiting for delay!"); + } + } + } + if nonce < block_number { Ok(TransactionValidity::Invalid(0)) } else { @@ -493,7 +508,7 @@ mod tests { /// Returns a block hash given the block id. fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error> { Ok(match at { - BlockId::Number(num) => Some(H256::from_low_u64_be(*num)), + BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), BlockId::Hash(_) => None, }) } @@ -502,7 +517,7 @@ mod tests { fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { let len = uxt.encode().len(); ( - (uxt.transfer().from.to_low_u64_be() << 5) + uxt.transfer().nonce, + (H256::from(uxt.transfer().from.clone()).to_low_u64_be() << 5) + uxt.transfer().nonce, len ) } @@ -524,8 +539,8 @@ mod tests { // when let hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -539,8 +554,8 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -564,21 +579,21 @@ mod tests { // when let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); // future doesn't count let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 3, })).unwrap(); @@ -600,20 +615,20 @@ mod tests { // given let pool = pool(); let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); let hash2 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); let hash3 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 3, })).unwrap(); @@ -636,8 +651,8 @@ mod tests { // given let pool = pool(); let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -662,8 +677,8 @@ mod tests { }, TestApi::default()); let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); @@ -671,8 +686,8 @@ mod tests { // when let hash2 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(2), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(2)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 10, })).unwrap(); @@ -697,8 +712,8 @@ mod tests { // when pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap_err(); @@ -713,12 +728,12 @@ mod tests { use super::*; #[test] - fn should_trigger_ready_and_finalised() { + fn should_trigger_ready_and_finalized() { // given let pool = pool(); let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -733,17 +748,17 @@ mod tests { // then let mut stream = watcher.into_stream().wait(); assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalised(H256::from_low_u64_be(2))))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalized(H256::from_low_u64_be(2).into())))); assert_eq!(stream.next(), None); } #[test] - fn should_trigger_ready_and_finalised_when_pruning_via_hash() { + fn should_trigger_ready_and_finalized_when_pruning_via_hash() { // given let pool = pool(); let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -758,7 +773,7 @@ mod tests { // then let mut stream = watcher.into_stream().wait(); assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalised(H256::from_low_u64_be(2))))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalized(H256::from_low_u64_be(2).into())))); assert_eq!(stream.next(), None); } @@ -767,8 +782,8 @@ mod tests { // given let pool = pool(); let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); @@ -777,8 +792,8 @@ mod tests { // when pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -795,8 +810,8 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -819,8 +834,8 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -853,8 +868,8 @@ mod tests { }, TestApi::default()); let xt = uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -863,8 +878,8 @@ mod tests { // when let xt = uxt(Transfer { - from: H256::from_low_u64_be(2), - to: H256::from_low_u64_be(1), + from: AccountId::from_h256(H256::from_low_u64_be(2)), + to: AccountId::from_h256(H256::from_low_u64_be(1)), amount: 4, nonce: 1, }); @@ -876,5 +891,59 @@ mod tests { assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); assert_eq!(stream.next(), Some(Ok(watcher::Status::Dropped))); } + + #[test] + fn should_handle_pruning_in_the_middle_of_import() { + let _ = env_logger::try_init(); + // given + let (ready, is_ready) = std::sync::mpsc::sync_channel(0); + let (tx, rx) = std::sync::mpsc::sync_channel(1); + let mut api = TestApi::default(); + api.delay = Mutex::new(rx.into()); + let pool = Arc::new(Pool::new(Default::default(), api)); + + // when + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 1, + }); + + // This transaction should go to future, since we use `nonce: 1` + let pool2 = pool.clone(); + std::thread::spawn(move || { + pool2.submit_one(&BlockId::Number(0), xt).unwrap(); + ready.send(()).unwrap(); + }); + + // But now before the previous one is imported we import + // the one that it depends on. + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 4, + nonce: 0, + }); + // The tag the above transaction provides (TestApi is using just nonce as u8) + let provides = vec![0_u8]; + pool.submit_one(&BlockId::Number(0), xt).unwrap(); + assert_eq!(pool.status().ready, 1); + + // Now block import happens before the second transaction is able to finish verification. + pool.prune_tags(&BlockId::Number(1), vec![provides], vec![]).unwrap(); + assert_eq!(pool.status().ready, 0); + + + // so when we release the verification of the previous one it will have + // something in `requires`, but should go to ready directly, since the previous transaction was imported + // correctly. + tx.send(()).unwrap(); + + // then + is_ready.recv().unwrap(); // wait for finish + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 0); + } } } diff --git a/core/transaction-pool/graph/src/ready.rs b/core/transaction-pool/graph/src/ready.rs index faca722d12c37ef590cda283ad0c17a652dd3df4..befb1b60ccc2deb18e18eee7a4a08b977f87045d 100644 --- a/core/transaction-pool/graph/src/ready.rs +++ b/core/transaction-pool/graph/src/ready.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -517,18 +517,18 @@ mod tests { tx3.provides = vec![vec![4]]; // when - let x = WaitingTransaction::new(tx2, &ready.provided_tags()); + let x = WaitingTransaction::new(tx2, &ready.provided_tags(), &[]); ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx3, &ready.provided_tags()); + let x = WaitingTransaction::new(tx3, &ready.provided_tags(), &[]); ready.import(x).unwrap(); assert_eq!(ready.get().count(), 2); // too low priority - let x = WaitingTransaction::new(tx1.clone(), &ready.provided_tags()); + let x = WaitingTransaction::new(tx1.clone(), &ready.provided_tags(), &[]); ready.import(x).unwrap_err(); tx1.priority = 10; - let x = WaitingTransaction::new(tx1.clone(), &ready.provided_tags()); + let x = WaitingTransaction::new(tx1.clone(), &ready.provided_tags(), &[]); ready.import(x).unwrap(); // then @@ -562,15 +562,15 @@ mod tests { }; // when - let x = WaitingTransaction::new(tx1, &ready.provided_tags()); + let x = WaitingTransaction::new(tx1, &ready.provided_tags(), &[]); ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx2, &ready.provided_tags()); + let x = WaitingTransaction::new(tx2, &ready.provided_tags(), &[]); ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx3, &ready.provided_tags()); + let x = WaitingTransaction::new(tx3, &ready.provided_tags(), &[]); ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx4, &ready.provided_tags()); + let x = WaitingTransaction::new(tx4, &ready.provided_tags(), &[]); ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx5, &ready.provided_tags()); + let x = WaitingTransaction::new(tx5, &ready.provided_tags(), &[]); ready.import(x).unwrap(); // then diff --git a/core/transaction-pool/graph/src/rotator.rs b/core/transaction-pool/graph/src/rotator.rs index eed7e628932bc1620556ab338da2f39fa0a6e297..2ca51ef74e880007285ec8b0f279019fb2b5fa3f 100644 --- a/core/transaction-pool/graph/src/rotator.rs +++ b/core/transaction-pool/graph/src/rotator.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/transaction-pool/graph/src/watcher.rs b/core/transaction-pool/graph/src/watcher.rs index bb73a4b0e914f9e89fa184780255141fa63b154f..5516d8c43c7497c8dc698f072634c61f99c9c4aa 100644 --- a/core/transaction-pool/graph/src/watcher.rs +++ b/core/transaction-pool/graph/src/watcher.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -30,8 +30,8 @@ pub enum Status { Future, /// Extrinsic is part of the ready queue. Ready, - /// Extrinsic has been finalised in block with given hash. - Finalised(H2), + /// Extrinsic has been finalized in block with given hash. + Finalized(H2), /// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid. Usurped(H), /// The extrinsic has been broadcast to the given peers. @@ -70,14 +70,14 @@ impl Watcher { #[derive(Debug)] pub struct Sender { receivers: Vec>>, - finalised: bool, + finalized: bool, } impl Default for Sender { fn default() -> Self { Sender { receivers: Default::default(), - finalised: false, + finalized: false, } } } @@ -108,17 +108,17 @@ impl Sender { self.send(Status::Usurped(hash)) } - /// Extrinsic has been finalised in block with given hash. - pub fn finalised(&mut self, hash: H2) { - self.send(Status::Finalised(hash)); - self.finalised = true; + /// Extrinsic has been finalized in block with given hash. + pub fn finalized(&mut self, hash: H2) { + self.send(Status::Finalized(hash)); + self.finalized = true; } /// Extrinsic has been marked as invalid by the block builder. pub fn invalid(&mut self) { self.send(Status::Invalid); - // we mark as finalised as there are no more notifications - self.finalised = true; + // we mark as finalized as there are no more notifications + self.finalized = true; } /// Transaction has been dropped from the pool because of the limit. @@ -132,9 +132,9 @@ impl Sender { } - /// Returns true if the are no more listeners for this extrinsic or it was finalised. + /// Returns true if the are no more listeners for this extrinsic or it was finalized. pub fn is_done(&self) -> bool { - self.finalised || self.receivers.is_empty() + self.finalized || self.receivers.is_empty() } fn send(&mut self, status: Status) { diff --git a/core/transaction-pool/src/api.rs b/core/transaction-pool/src/api.rs index dd8cb95c7ddd641bf34da1eb80f13175b6f9abfe..84475376fe6377ff6c71afd2499bb941bd453865 100644 --- a/core/transaction-pool/src/api.rs +++ b/core/transaction-pool/src/api.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/transaction-pool/src/error.rs b/core/transaction-pool/src/error.rs index 9f191b8545e2f6125401c5e210c504573755bd0b..e1223c537de3731446840f1176489f2ebfec0d2e 100644 --- a/core/transaction-pool/src/error.rs +++ b/core/transaction-pool/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index ee9d8d8cbb17d985b98b9da34f6f995f1e2da9e1..1899c601b2fdbbc8b73aac524c5bd030026615e5 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/transaction-pool/src/tests.rs b/core/transaction-pool/src/tests.rs index 770f00fa6491614dae339452972175dd2c42ee28..cab44f49cc79c4b812c513a2cc197b0a5e00d01d 100644 --- a/core/transaction-pool/src/tests.rs +++ b/core/transaction-pool/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,10 +17,9 @@ use super::*; -use keyring::Keyring::{self, *}; use parity_codec::Encode; use txpool::{self, Pool}; -use test_client::runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}; +use test_client::{runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}, AccountKeyring::{self, *}}; use sr_primitives::{ generic::{self, BlockId}, traits::{Hash as HashT, BlakeTwo256}, @@ -86,9 +85,9 @@ fn number_of(at: &BlockId) -> u64 { } } -fn uxt(who: Keyring, nonce: Index) -> Extrinsic { +fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic { let transfer = Transfer { - from: who.to_raw_public().into(), + from: who.into(), to: AccountId::default(), nonce, amount: 1, diff --git a/core/trie/Cargo.toml b/core/trie/Cargo.toml index cf4b18ead06f1221f937ca1b43ef5f03e680866d..a75aac23431e98862a153e0da981af3f49d31ce8 100644 --- a/core/trie/Cargo.toml +++ b/core/trie/Cargo.toml @@ -12,17 +12,17 @@ name = "bench" harness = false [dependencies] -codec = { package = "parity-codec", version = "3.0" } -hash-db = { version = "0.11", default-features = false } -trie-db = { version = "0.11", optional = true } -trie-root = { version = "0.11", default-features = false } -memory-db = { version = "0.11", optional = true } +codec = { package = "parity-codec", version = "3.2" } +hash-db = { version = "0.12", default-features = false } +trie-db = { version = "0.12", optional = true } +trie-root = { version = "0.12", default-features = false } +memory-db = { version = "0.12", optional = true } [dev-dependencies] substrate-primitives = { path = "../primitives" } -trie-bench = { version = "0.11" } -trie-standardmap = { version = "0.11" } -keccak-hasher = { version = "0.11" } +trie-bench = { version = "0.12" } +trie-standardmap = { version = "0.12" } +keccak-hasher = { version = "0.12" } criterion = "0.2" hex-literal = "0.1.0" diff --git a/core/trie/benches/bench.rs b/core/trie/benches/bench.rs index f4100bff15fc6f855a3bc4a16c60f8450b681d52..179dc6aaf8413c0c85e88f3c95ecda7d3e089d5b 100644 --- a/core/trie/benches/bench.rs +++ b/core/trie/benches/bench.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify diff --git a/core/trie/src/lib.rs b/core/trie/src/lib.rs index cb766003700d54d73b2c3751d4c7c9e202b0bb63..999f1e67c9f8622b121fbc116279a84757f3e025 100644 --- a/core/trie/src/lib.rs +++ b/core/trie/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -32,6 +32,8 @@ pub use trie_stream::TrieStream; pub use node_codec::NodeCodec; /// Various re-exports from the `trie-db` crate. pub use trie_db::{Trie, TrieMut, DBValue, Recorder, Query}; +/// Various re-exports from the `memory-db` crate. +pub use memory_db::{KeyFunction, prefixed_key}; /// As in `trie_db`, but less generic, error type for the crate. pub type TrieError = trie_db::TrieError; @@ -42,8 +44,12 @@ impl> AsHashDB for T {} pub type HashDB<'a, H> = hash_db::HashDB + 'a; /// As in `hash_db`, but less generic, trait exposed. pub type PlainDB<'a, K> = hash_db::PlainDB + 'a; +/// As in `memory_db::MemoryDB` that uses prefixed storage key scheme. +pub type PrefixedMemoryDB = memory_db::MemoryDB, trie_db::DBValue>; +/// As in `memory_db::MemoryDB` that uses prefixed storage key scheme. +pub type MemoryDB = memory_db::MemoryDB, trie_db::DBValue>; /// As in `memory_db`, but less generic, trait exposed. -pub type MemoryDB = memory_db::MemoryDB; +pub type GenericMemoryDB = memory_db::MemoryDB; /// Persistent trie database read-access interface for the a given hasher. pub type TrieDB<'a, H> = trie_db::TrieDB<'a, H, NodeCodec>; @@ -313,7 +319,6 @@ mod tests { use super::*; use codec::{Encode, Compact}; use substrate_primitives::Blake2Hasher; - use memory_db::MemoryDB; use hash_db::{HashDB, Hasher}; use trie_db::{DBValue, TrieMut, Trie}; use trie_standardmap::{Alphabet, ValueMode, StandardMap}; diff --git a/core/trie/src/node_codec.rs b/core/trie/src/node_codec.rs index 438b40600905521b7d62ffbacdc1cedd619f29ff..b73519e87f4b7688a0f3fd3ec205c660b3015f67 100644 --- a/core/trie/src/node_codec.rs +++ b/core/trie/src/node_codec.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify diff --git a/core/trie/src/node_header.rs b/core/trie/src/node_header.rs index 99b1241cab4524c41c634a9e0d7d08d67a3a451e..4f7617c0684bb881d970c177d940559d0760d9a9 100644 --- a/core/trie/src/node_header.rs +++ b/core/trie/src/node_header.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -72,7 +72,6 @@ impl Decode for NodeHeader { BRANCH_NODE_NO_VALUE => NodeHeader::Branch(false), // 254 BRANCH_NODE_WITH_VALUE => NodeHeader::Branch(true), // 255 - _ => unreachable!(), }) } } diff --git a/core/trie/src/trie_stream.rs b/core/trie/src/trie_stream.rs index 5f1bf1c9d9f8bab4cd1f51cf925e60559000b586..e283a512bb509cbf680c1002c396c36084f6bf22 100644 --- a/core/trie/src/trie_stream.rs +++ b/core/trie/src/trie_stream.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -24,7 +24,7 @@ use codec::Encode; use super::{EMPTY_TRIE, LEAF_NODE_OFFSET, LEAF_NODE_BIG, EXTENSION_NODE_OFFSET, EXTENSION_NODE_BIG, branch_node}; -/// Codec-flavoured TrieStream +/// Codec-flavored TrieStream pub struct TrieStream { buffer: Vec, } diff --git a/core/util/fork-tree/Cargo.toml b/core/util/fork-tree/Cargo.toml index 7dfd82991f212759c72b627ed616b20604961c3a..4098fb80fad283d1eeab59f4b87ea8a8d704f63b 100644 --- a/core/util/fork-tree/Cargo.toml +++ b/core/util/fork-tree/Cargo.toml @@ -5,4 +5,4 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -parity-codec = { version = "3.1", features = ["derive"] } +parity-codec = { version = "3.2", features = ["derive"] } diff --git a/core/util/fork-tree/src/lib.rs b/core/util/fork-tree/src/lib.rs index 71c83f57ca48791dcf44770886e881daeadb0246..f194ac8915159b104be7e469bf5e27dcf9dbbdea 100644 --- a/core/util/fork-tree/src/lib.rs +++ b/core/util/fork-tree/src/lib.rs @@ -228,17 +228,19 @@ impl ForkTree where /// Checks if any node in the tree is finalized by either finalizing the /// node itself or a child node that's not in the tree, guaranteeing that /// the node being finalized isn't a descendent of any of the node's - /// children. The given `predicate` is checked on the prospective finalized - /// root and must pass for finalization to occur. The given function - /// `is_descendent_of` should return `true` if the second hash (target) is a - /// descendent of the first hash (base). + /// children. Returns `Some(true)` if the node being finalized is a root, + /// `Some(false)` if the node being finalized is not a root, and `None` if + /// no node in the tree is finalized. The given `predicate` is checked on + /// the prospective finalized root and must pass for finalization to occur. + /// The given function `is_descendent_of` should return `true` if the second + /// hash (target) is a descendent of the first hash (base). pub fn finalizes_any_with_descendent_if( &self, hash: &H, number: N, is_descendent_of: &F, predicate: P, - ) -> Result> + ) -> Result, Error> where E: std::error::Error, F: Fn(&H, &H) -> Result, P: Fn(&V) -> bool, @@ -253,20 +255,20 @@ impl ForkTree where // tree, if we find a valid node that passes the predicate then we must // ensure that we're not finalizing past any of its child nodes. for node in self.node_iter() { - if node.hash == *hash || is_descendent_of(&node.hash, hash)? { - if predicate(&node.data) { + if predicate(&node.data) { + if node.hash == *hash || is_descendent_of(&node.hash, hash)? { for node in node.children.iter() { if node.number <= number && is_descendent_of(&node.hash, &hash)? { return Err(Error::UnfinalizedAncestor); } } - return Ok(true); + return Ok(Some(self.roots.iter().any(|root| root.hash == node.hash))); } } } - Ok(false) + Ok(None) } /// Finalize a root in the tree by either finalizing the node itself or a @@ -298,8 +300,8 @@ impl ForkTree where // we're not finalizing past any children node. let mut position = None; for (i, root) in self.roots.iter().enumerate() { - if root.hash == *hash || is_descendent_of(&root.hash, hash)? { - if predicate(&root.data) { + if predicate(&root.data) { + if root.hash == *hash || is_descendent_of(&root.hash, hash)? { for node in root.children.iter() { if node.number <= number && is_descendent_of(&node.hash, &hash)? { return Err(Error::UnfinalizedAncestor); @@ -692,7 +694,19 @@ mod test { &is_descendent_of, |c| c.effective <= 2, ), - Ok(false), + Ok(None), + ); + + // finalizing "D" will finalize a block from the tree, but it can't be applied yet + // since it is not a root change + assert_eq!( + tree.finalizes_any_with_descendent_if( + &"D", + 10, + &is_descendent_of, + |c| c.effective == 10, + ), + Ok(Some(false)), ); // finalizing "B" doesn't finalize "A0" since the predicate doesn't pass, @@ -720,7 +734,7 @@ mod test { &is_descendent_of, |c| c.effective <= 5, ), - Ok(true), + Ok(Some(true)), ); assert_eq!( @@ -757,7 +771,7 @@ mod test { &is_descendent_of, |c| c.effective <= 100, ), - Ok(true), + Ok(Some(true)), ); assert_eq!( @@ -788,4 +802,76 @@ mod test { ], ); } + + #[test] + fn minimizes_calls_to_is_descendent_of() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + let n_is_descendent_of_calls = AtomicUsize::new(0); + + let is_descendent_of = |_: &&str, _: &&str| -> Result { + n_is_descendent_of_calls.fetch_add(1, Ordering::SeqCst); + Ok(true) + }; + + { + // Deep tree where we want to call `finalizes_any_with_descendent_if`. The + // search for the node should first check the predicate (which is cheaper) and + // only then call `is_descendent_of` + let mut tree = ForkTree::new(); + let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; + + for (i, letter) in letters.iter().enumerate() { + tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(true)).unwrap(); + } + + // "L" is a descendent of "K", but the predicate will only pass for "K", + // therefore only one call to `is_descendent_of` should be made + assert_eq!( + tree.finalizes_any_with_descendent_if( + &"L", + 11, + &is_descendent_of, + |i| *i == 10, + ), + Ok(Some(false)), + ); + + assert_eq!( + n_is_descendent_of_calls.load(Ordering::SeqCst), + 1, + ); + } + + n_is_descendent_of_calls.store(0, Ordering::SeqCst); + + { + // Multiple roots in the tree where we want to call `finalize_with_descendent_if`. + // The search for the root node should first check the predicate (which is cheaper) + // and only then call `is_descendent_of` + let mut tree = ForkTree::new(); + let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; + + for (i, letter) in letters.iter().enumerate() { + tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(false)).unwrap(); + } + + // "L" is a descendent of "K", but the predicate will only pass for "K", + // therefore only one call to `is_descendent_of` should be made + assert_eq!( + tree.finalize_with_descendent_if( + &"L", + 11, + &is_descendent_of, + |i| *i == 10, + ), + Ok(FinalizationResult::Changed(Some(10))), + ); + + assert_eq!( + n_is_descendent_of_calls.load(Ordering::SeqCst), + 1, + ); + } + } } diff --git a/license_header.txt b/license_header.txt index c357cc10ed409fad4f845affd912fe93a0b983f6..15b778660733f3b2b5415f3044df5e7a0d9e04d7 100644 --- a/license_header.txt +++ b/license_header.txt @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/node-template/Cargo.toml b/node-template/Cargo.toml index 063ccfbedff932642425e6890e61dc827274b80f..786f49023b4039e445e892fa9c4f3a8fe9341e4d 100644 --- a/node-template/Cargo.toml +++ b/node-template/Cargo.toml @@ -18,9 +18,8 @@ tokio = "0.1" exit-future = "0.1" parking_lot = "0.7.1" hex-literal = "0.1" -slog = "^2" -parity-codec = "3.1" -trie-root = "0.11.0" +parity-codec = "3.2" +trie-root = "0.12.0" sr-io = { path = "../core/sr-io" } substrate-cli = { path = "../core/cli" } primitives = { package = "substrate-primitives", path = "../core/primitives" } @@ -33,7 +32,6 @@ consensus = { package = "substrate-consensus-aura", path = "../core/consensus/au substrate-client = { path = "../core/client" } basic-authorship = { package = "substrate-basic-authorship", path = "../core/basic-authorship" } node-template-runtime = { path = "runtime" } -node-executor = { path = "../node/executor" } [build-dependencies] vergen = "3" diff --git a/node-template/build.rs b/node-template/build.rs index d30f13c0c9d793b545974a2dfd9851ab693272b1..afc39d3b63c5eab92b362d436f3f2b4786088ed0 100644 --- a/node-template/build.rs +++ b/node-template/build.rs @@ -1,6 +1,6 @@ use vergen::{ConstantsFlags, generate_cargo_keys}; -const ERROR_MSG: &'static str = "Failed to generate metadata files"; +const ERROR_MSG: &str = "Failed to generate metadata files"; fn main() { generate_cargo_keys(ConstantsFlags::all()).expect(ERROR_MSG); diff --git a/node-template/init.sh b/node-template/init.sh index 5dde6d42418b58844640bd41214948ef329065aa..cf5ecf97926fea7a5e8fd2a91df96853f90e8ee7 100755 --- a/node-template/init.sh +++ b/node-template/init.sh @@ -2,7 +2,7 @@ set -e -echo "*** Initialising WASM build environment" +echo "*** Initializing WASM build environment" if [ -z $CI_PROJECT_NAME ] ; then rustup update nightly diff --git a/node-template/runtime/Cargo.toml b/node-template/runtime/Cargo.toml index 986b12ce9492993250b517aefeb87c6b8eca78f0..6a312e5530fa5e1266a38f01839712c59229f9ef 100644 --- a/node-template/runtime/Cargo.toml +++ b/node-template/runtime/Cargo.toml @@ -5,17 +5,16 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default_features = false } runtime-io = { package = "sr-io", path = "../../core/sr-io", default_features = false } version = { package = "sr-version", path = "../../core/sr-version", default_features = false } support = { package = "srml-support", path = "../../srml/support", default_features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives", default_features = false } balances = { package = "srml-balances", path = "../../srml/balances", default_features = false } -fees = { package = "srml-fees", path = "../../srml/fees", default_features = false } consensus = { package = "srml-consensus", path = "../../srml/consensus", default_features = false } aura = { package = "srml-aura", path = "../../srml/aura", default_features = false } executive = { package = "srml-executive", path = "../../srml/executive", default_features = false } @@ -26,6 +25,8 @@ sudo = { package = "srml-sudo", path = "../../srml/sudo", default_features = fal runtime-primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default_features = false } client = { package = "substrate-client", path = "../../core/client", default_features = false } consensus-aura = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default_features = false } +offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false } +consensus_authorities = { package = "substrate-consensus-authorities", path = "../../core/consensus/authorities", default-features = false } [features] default = ["std"] @@ -37,7 +38,6 @@ std = [ "runtime-io/std", "support/std", "balances/std", - "fees/std", "executive/std", "aura/std", "indices/std", @@ -47,7 +47,8 @@ std = [ "sudo/std", "version/std", "serde_derive", - "serde/std", + "serde", "safe-mix/std", "consensus-aura/std", + "offchain-primitives/std", ] diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 9caef856fd083eb3b5ff0bd14467bae81946d20f..5299831ea5cf20c3d5c9d7a6713493a3de2fa057 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -11,10 +11,10 @@ use parity_codec::{Encode, Decode}; use rstd::prelude::*; #[cfg(feature = "std")] use primitives::bytes; -use primitives::{Ed25519AuthorityId, OpaqueMetadata}; +use primitives::{ed25519, sr25519, OpaqueMetadata}; use runtime_primitives::{ - ApplyResult, transaction_validity::TransactionValidity, Ed25519Signature, generic, - traits::{self, BlakeTwo256, Block as BlockT, StaticLookup}, create_runtime_str + ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str, + traits::{self, NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify} }; use client::{ block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api}, @@ -34,8 +34,17 @@ pub use runtime_primitives::{Permill, Perbill}; pub use timestamp::BlockPeriod; pub use support::{StorageValue, construct_runtime}; -/// Alias to Ed25519 pubkey that identifies an account on the chain. -pub type AccountId = primitives::H256; +/// The type that is used for identifying authorities. +pub type AuthorityId = ::Signer; + +/// The type used by authorities to prove their ID. +pub type AuthoritySignature = ed25519::Signature; + +/// Alias to pubkey that identifies an account on the chain. +pub type AccountId = ::Signer; + +/// The type used by authorities to prove their ID. +pub type AccountSignature = sr25519::Signature; /// A hash of some data used by the chain. pub type Hash = primitives::H256; @@ -58,21 +67,27 @@ pub mod opaque { /// Opaque, encoded, unchecked extrinsic. #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] - #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct UncheckedExtrinsic(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); + #[cfg(feature = "std")] + impl std::fmt::Debug for UncheckedExtrinsic { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "{}", primitives::hexdisplay::HexDisplay::from(&self.0)) + } + } impl traits::Extrinsic for UncheckedExtrinsic { fn is_signed(&self) -> Option { None } } /// Opaque block header type. - pub type Header = generic::Header>; + pub type Header = generic::Header>; /// Opaque block type. pub type Block = generic::Block; /// Opaque block identifier type. pub type BlockId = generic::BlockId; /// Opaque session key type. - pub type SessionKey = Ed25519AuthorityId; + pub type SessionKey = AuthorityId; } /// This runtime version. @@ -125,7 +140,7 @@ impl aura::Trait for Runtime { impl consensus::Trait for Runtime { /// The identifier we use to refer to authorities. - type SessionKey = Ed25519AuthorityId; + type SessionKey = AuthorityId; // The aura module handles offline-reports internally // rather than using an explicit report system. type InherentOfflineReport = (); @@ -158,15 +173,12 @@ impl balances::Trait for Runtime { type OnFreeBalanceZero = (); /// What to do if a new account is created. type OnNewAccount = Indices; - /// Restrict whether an account can transfer funds. We don't place any further restrictions. - type EnsureAccountLiquid = (); /// The uniquitous event type. type Event = Event; -} -impl fees::Trait for Runtime { - type TransferAsset = Balances; - type Event = Event; + type TransactionPayment = (); + type DustRemoval = (); + type TransferPayment = (); } impl sudo::Trait for Runtime { @@ -176,12 +188,12 @@ impl sudo::Trait for Runtime { } /// Used for the module template in `./template.rs` -impl template::Trait for Runtime { +impl template::Trait for Runtime { type Event = Event; } construct_runtime!( - pub enum Runtime with Log(InternalLog: DigestItem) where + pub enum Runtime with Log(InternalLog: DigestItem) where Block = Block, NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic @@ -193,7 +205,6 @@ construct_runtime!( Indices: indices, Balances: balances, Sudo: sudo, - Fees: fees::{Module, Storage, Config, Event}, // Used for the module template in `./template.rs` TemplateModule: template::{Module, Call, Storage, Event}, } @@ -210,11 +221,11 @@ pub type Block = generic::Block; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive; +pub type Executive = executive::Executive; // Implement our runtime API endpoints. This is just a bunch of proxying. impl_runtime_apis! { @@ -223,16 +234,12 @@ impl_runtime_apis! { VERSION } - fn authorities() -> Vec { - Consensus::authorities() - } - fn execute_block(block: Block) { Executive::execute_block(block) } - fn initialise_block(header: &::Header) { - Executive::initialise_block(header) + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) } } @@ -247,8 +254,8 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } - fn finalise_block() -> ::Header { - Executive::finalise_block() + fn finalize_block() -> ::Header { + Executive::finalize_block() } fn inherent_extrinsics(data: InherentData) -> Vec<::Extrinsic> { @@ -275,4 +282,16 @@ impl_runtime_apis! { Aura::slot_duration() } } + + impl offchain_primitives::OffchainWorkerApi for Runtime { + fn offchain_worker(n: NumberFor) { + Executive::offchain_worker(n) + } + } + + impl consensus_authorities::AuthoritiesApi for Runtime { + fn authorities() -> Vec { + Consensus::authorities() + } + } } diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index 300b48af114c7b47f028c419dc23743b5086ad2b..fd122433daea3460d170b1d5c1cc068d024be7e1 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -6,7 +6,7 @@ /// For more guidance on Substrate modules, see the example module -/// https://github.com/paritytech/substrate/blob/gav-template/srml/example/src/lib.rs +/// https://github.com/paritytech/substrate/blob/master/srml/example/src/lib.rs use support::{decl_module, decl_storage, decl_event, StorageValue, dispatch::Result}; use system::ensure_signed; @@ -55,7 +55,6 @@ decl_module! { } decl_event!( - /// An event in this module. pub enum Event where AccountId = ::AccountId { // Just a dummy event. // Event `Something` is declared with a parameter of the type `u32` and `AccountId` @@ -95,7 +94,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; diff --git a/node-template/runtime/wasm/Cargo.lock b/node-template/runtime/wasm/Cargo.lock index f1b317903e093b7a5740374e2c53c146f1d992e2..824a8f3650fec43a6041cba8169e172fbca0e257 100644 --- a/node-template/runtime/wasm/Cargo.lock +++ b/node-template/runtime/wasm/Cargo.lock @@ -1,5 +1,57 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aes-ctr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aes-soft" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aesni" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aio-limited" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayref" version = "0.3.5" @@ -13,6 +65,23 @@ dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "asn1_der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "asn1_der_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "autocfg" version = "0.1.2" @@ -20,13 +89,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -36,20 +105,50 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base-x" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "base58" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bigint" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitmask" +version = "0.5.0" +source = "git+https://github.com/paritytech/bitmask#a84e147be602631617badd18b6b9af83391db4a9" + +[[package]] +name = "blake2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "blake2-rfc" version = "0.2.18" @@ -79,6 +178,14 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-cipher-trait" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "block-padding" version = "0.1.3" @@ -87,6 +194,11 @@ dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bs58" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byte-tools" version = "0.2.0" @@ -97,6 +209,11 @@ name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.3.1" @@ -104,7 +221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -113,12 +230,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.28" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -136,7 +253,7 @@ name = "clear_on_drop" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -157,25 +274,32 @@ name = "crossbeam" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-channel" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -183,29 +307,69 @@ name = "crossbeam-deque" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-epoch" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" -version = "0.6.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -227,18 +391,50 @@ dependencies = [ "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ctr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cuckoofilter" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "curve25519-dalek" -version = "1.0.3" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "data-encoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "digest" version = "0.6.2" @@ -255,21 +451,40 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ed25519-dalek" version = "1.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -277,7 +492,7 @@ dependencies = [ [[package]] name = "environmental" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -285,13 +500,28 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "fake-simd" @@ -305,8 +535,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -329,6 +559,11 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -348,6 +583,15 @@ name = "futures" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "generic-array" version = "0.8.3" @@ -367,17 +611,26 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "heapsize" version = "0.4.2" @@ -386,9 +639,22 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hex-literal" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -413,6 +679,15 @@ dependencies = [ "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hmac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hmac-drbg" version = "0.1.2" @@ -443,7 +718,7 @@ name = "impl-codec" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -452,7 +727,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -465,7 +740,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -493,13 +768,13 @@ name = "kvdb" version = "0.1.0" source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", ] [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -509,9 +784,328 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libp2p" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-core-derive 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-dns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-floodsub 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-kad 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-mdns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-mplex 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-noise 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-plaintext 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ratelimit 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-secio 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-tcp 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-uds 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-yamux 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-core" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-core-derive" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-dns" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-floodsub" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-identify" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-kad" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mdns" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mplex" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-noise" +version = "0.3.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ping" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-plaintext" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ratelimit" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-secio" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-tcp" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-uds" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-yamux" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libsecp256k1" version = "0.2.2" @@ -520,7 +1114,7 @@ dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -539,7 +1133,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -547,6 +1141,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memoffset" version = "0.2.1" @@ -554,10 +1153,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memory-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -568,13 +1167,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "merlin" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -588,7 +1186,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -613,7 +1211,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -628,13 +1226,27 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "multistream-select" +version = "0.3.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -642,10 +1254,10 @@ dependencies = [ name = "node-template-runtime" version = "0.9.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -654,7 +1266,6 @@ dependencies = [ "srml-balances 0.1.0", "srml-consensus 0.1.0", "srml-executive 0.1.0", - "srml-fees 0.1.0", "srml-indices 0.1.0", "srml-sudo 0.1.0", "srml-support 0.1.0", @@ -662,6 +1273,8 @@ dependencies = [ "srml-timestamp 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-authorities 0.1.0", + "substrate-offchain-primitives 0.1.0", "substrate-primitives 0.1.0", ] @@ -677,6 +1290,11 @@ name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "nohash-hasher" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num-integer" version = "0.1.39" @@ -692,16 +1310,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "once_cell" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "opaque-debug" @@ -710,28 +1331,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.16" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.40" +version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "owning_ref" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" version = "0.4.0" @@ -747,12 +1377,12 @@ source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7 [[package]] name = "parity-codec" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -761,9 +1391,36 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multiaddr" +version = "0.2.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multihash" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -774,6 +1431,24 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot" version = "0.7.1" @@ -783,15 +1458,38 @@ dependencies = [ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -810,9 +1508,19 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -857,9 +1565,9 @@ name = "proc-macro-hack" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -869,27 +1577,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "protobuf" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quick-error" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.5" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -897,29 +1629,30 @@ dependencies = [ [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -933,14 +1666,6 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_core" version = "0.3.1" @@ -963,33 +1688,43 @@ dependencies = [ ] [[package]] -name = "rand_isaac" -version = "0.1.1" +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_os" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_pcg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1000,6 +1735,27 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -1013,16 +1769,37 @@ name = "redox_syscall" version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ring" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1043,6 +1820,16 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rw-stream-sink" +version = "0.1.1" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ryu" version = "0.2.7" @@ -1059,15 +1846,33 @@ dependencies = [ [[package]] name = "schnorrkel" version = "0.0.0" +source = "git+https://github.com/w3f/schnorrkel#0a0de4294b475ef6abdeebb50067f213ca79b3c7" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schnorrkel" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1077,6 +1882,16 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "secp256k1" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -1092,27 +1907,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.85" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.85" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.37" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1181,8 +1996,8 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1192,16 +2007,30 @@ version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.8" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "snow" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1215,19 +2044,19 @@ version = "0.1.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sr-io" version = "0.1.0" dependencies = [ - "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1243,9 +2072,9 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1263,9 +2092,9 @@ name = "sr-version" version = "0.1.0" dependencies = [ "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", ] @@ -1274,9 +2103,10 @@ dependencies = [ name = "srml-aura" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-session 0.1.0", @@ -1291,10 +2121,10 @@ dependencies = [ name = "srml-balances" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", @@ -1306,10 +2136,10 @@ dependencies = [ name = "srml-consensus" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", @@ -1322,40 +2152,24 @@ dependencies = [ name = "srml-executive" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", - "sr-primitives 0.1.0", - "sr-std 0.1.0", - "srml-support 0.1.0", - "srml-system 0.1.0", -] - -[[package]] -name = "srml-fees" -version = "0.1.0" -dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] name = "srml-indices" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1369,9 +2183,9 @@ dependencies = [ name = "srml-metadata" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", ] @@ -1380,11 +2194,11 @@ dependencies = [ name = "srml-session" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", @@ -1397,10 +2211,11 @@ dependencies = [ name = "srml-staking" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", @@ -1414,10 +2229,10 @@ dependencies = [ name = "srml-sudo" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", @@ -1429,12 +2244,13 @@ dependencies = [ name = "srml-support" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1447,11 +2263,11 @@ dependencies = [ name = "srml-support-procedural" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "srml-support-procedural-tools 0.1.0", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1459,30 +2275,30 @@ name = "srml-support-procedural-tools" version = "0.1.0" dependencies = [ "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "srml-support-procedural-tools-derive 0.1.0", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools-derive" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-system" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1494,12 +2310,11 @@ dependencies = [ name = "srml-timestamp" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-consensus 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "substrate-inherents 0.1.0", @@ -1515,6 +2330,90 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "static_slice" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stdweb" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-macros 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stream-cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strum" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strum_macros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-bip39" +version = "0.2.0" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" +dependencies = [ + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-client" version = "0.1.0" @@ -1522,12 +2421,12 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "sr-primitives 0.1.0", @@ -1547,24 +2446,40 @@ dependencies = [ name = "substrate-consensus-aura-primitives" version = "0.1.0" dependencies = [ + "sr-primitives 0.1.0", + "substrate-client 0.1.0", +] + +[[package]] +name = "substrate-consensus-authorities" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", + "srml-support 0.1.0", "substrate-client 0.1.0", + "substrate-primitives 0.1.0", ] [[package]] name = "substrate-consensus-common" version = "0.1.0" dependencies = [ - "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1573,13 +2488,13 @@ version = "0.1.0" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", "substrate-panic-handler 0.1.0", @@ -1595,7 +2510,7 @@ dependencies = [ name = "substrate-inherents" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1605,16 +2520,26 @@ dependencies = [ name = "substrate-keyring" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-offchain-primitives" +version = "0.1.0" +dependencies = [ + "sr-primitives 0.1.0", + "substrate-client 0.1.0", +] + [[package]] name = "substrate-panic-handler" version = "0.1.0" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1625,20 +2550,24 @@ dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1648,37 +2577,37 @@ dependencies = [ name = "substrate-serializer" version = "0.1.0" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-state-machine" version = "0.1.0" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-telemetry" version = "0.3.1" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1690,13 +2619,18 @@ dependencies = [ name = "substrate-trie" version = "0.4.0" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "subtle" version = "2.0.0" @@ -1704,11 +2638,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.26" +version = "0.15.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1722,7 +2667,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1730,11 +2675,25 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tiny-keccak" version = "1.4.2" @@ -1743,24 +2702,36 @@ dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tk-listen" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1770,64 +2741,85 @@ name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-dns-unofficial" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-executor" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1835,35 +2827,36 @@ name = "tokio-tcp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1874,13 +2867,13 @@ name = "tokio-udp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1888,16 +2881,16 @@ name = "tokio-uds" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1905,26 +2898,36 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.11.0" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "twofish" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1932,7 +2935,7 @@ name = "twox-hash" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1940,6 +2943,11 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" version = "0.6.1" @@ -1964,20 +2972,26 @@ name = "unicode-normalization" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-segmentation" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "unreachable" -version = "1.0.0" +name = "unsigned-varint" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1995,6 +3009,11 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" version = "0.2.6" @@ -2050,13 +3069,13 @@ version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2071,60 +3090,124 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "x25519-dalek" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "yamux" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zeroize" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] +"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f10b352bc3fc08ae24dc5d2d3ddcac153678533986122dc283d747b12071000" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9893d63fc3b1c44231e667da6836a33f27d8b6b3bdc82f83da5dfd579d1b6528" +"checksum asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7f92edafad155aff997fa5b727c6429b91e996b5a5d62a2b0adbae1306b5fe" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d55aa264e822dbafa12db4d54767aff17c6ba55ea2d8559b3e17392c7d000e5d" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" +"checksum bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebecac13b3c745150d7b6c3ea7572d372f09d627c2077e893bf26c5c7f70d282" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)" = "" +"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" -"checksum crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "137bc235f622ffaa0428e3854e24acb53291fc0b3ff6fb2cb75a8be6fb02f06b" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" -"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" "checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" -"checksum curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dae47cc3529cdab597dbc8b606e565707209b506e55848f3c15679214a56c956" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" +"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" +"checksum curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f8a6fc0376eb52dc18af94915cc04dfdf8353746c0e8c550ae683a0815e5c1" +"checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" "checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" "checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" -"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" -"checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" +"checksum environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c7464757b80de8930c91c9afe77ddce501826bf9d134a87db2c67d9dc177e2c" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" -"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" -"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07463834729d0ce8d475e7dd6d302e407093ad9a9c02d77eb07fb74b5373829d" +"checksum hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1224388a21c88a80ae7087a2a245ca6d80acc97a9186b75789fb3eeefd0609af" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" "checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" +"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" "checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" @@ -2136,39 +3219,67 @@ dependencies = [ "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-core-derive 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-dns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-floodsub 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-kad 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-mdns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-mplex 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-noise 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-plaintext 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-ratelimit 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-secio 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-tcp 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-uds 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-yamux 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" +"checksum memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd87d4d64f7b86d8804bbb419f8ecb187cb8f40a50e91c72848075c604ba88d" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9e97b439f6d38cbe2a4a4aa93f6770c5305f62761b78b1851406c09c87ee2a" +"checksum merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "83c2dda19c01176e8e7148f7bdb88bbdf215a8db0641f89fc40e4b81736aeda5" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum multistream-select 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d138afcce92d219ccb6eb53d9b1e8a96ac0d633cfd3c53cd9856d96d1741bb8" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" -"checksum once_cell 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "53075ac5dbd2798cfbcf9f710f2737de031d8076c192d8fe66fb23f639ccbdf4" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" -"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" -"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" +"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" +"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" +"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67a4d27831e31e27f1454d6e3d3bb34bcac6bf7ad7032eed0ad0070dc8cf55c1" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" "checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" +"checksum parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" +"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" +"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" +"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" "checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" @@ -2176,35 +3287,46 @@ dependencies = [ "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" -"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24d5d73d2b88fddb8b8141f2730d950d88772c940ac4f8f3e93230b9a99d92df" +"checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" -"checksum rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dee497e66d8d76bf08ce20c8d36e16f93749ab0bf89975b4f8ae5cee660c2da2" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" +"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" -"checksum ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "148fc853f6d85f53f5f315d46701eaacc565cdfb3cb1959730c96e81e7e49999" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe554f318830b48e5da8ab1ccb1ffd02b79228364dac7766b7cd1ec461ca5116" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" +"checksum schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a700659388785588c75b197cecda0f23c7112a9281ef703e8ffc651061ce014c" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4070f3906e65249228094cf97b04a90799fba04468190bbbcfa812309cf86e32" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" -"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" -"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" @@ -2214,40 +3336,60 @@ dependencies = [ "checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" "checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" -"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5a64f02fd208ef15bd2d1a65861df4707e416151e1272d02c8faafad1c138100" "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362" +"checksum stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a3edad410e603184d656e2abded5fd4d3d6e93d5763d21130dbaf99795db74eb" +"checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" +"checksum stdweb-internal-macros 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1635afd059cbfac7d5b1274f0c44cec110c1e013c48e8bbc22e07e52696cf887" +"checksum stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a2f4a2eb556337b2d1a302630bbddf989ae383c70393e89b48152b9896cbda" +"checksum stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8861bc80f649f5b4c9bd38b696ae9af74499d479dbfb327f0607de6b326a36bc" +"checksum strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1810e25f576e7ffce1ff5243b37066da5ded0310b3274c20baaeccb1145b2806" +"checksum strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "572a2f4e53dd4c3483fd79e5cc10ddd773a3acb1169bbfe8762365e107110579" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1415431cb2398d84da64173f8473c792808314427d4a6f2f3ea85ae67239fe3" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" -"checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" +"checksum tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5462b0f968c0457efe38fcd2df7e487096b992419e4f5337b06775a614bbda4b" +"checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" +"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" +"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" "checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" -"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" -"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" -"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" -"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" +"checksum trie-db 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "843af112ba3a8c919cd961edf3cac9272353f5e277ad8678c7023fa70e5c0e2d" +"checksum trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e45632ecaf2b8b4a40b5208383cd659b4e66f58ccd40086467a4614b45781430" +"checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c64cdf40b4a9645534a943668681bcb219faf51874d4b65d2e0abda1b10a2ab" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" @@ -2258,3 +3400,6 @@ dependencies = [ "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4aca1ba6bec2719576bd20dfe5b24d9359552e616d10bff257e50cd85f745d17" +"checksum yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "302defd1bed8a9a6d43b82f0e5a50510dfdfbbd02c270c93ff9d6f3f5e2dea89" +"checksum zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddfeb6eee2fb3b262ef6e0898a52b7563bb8e0d5955a313b3cf2f808246ea14" diff --git a/node-template/src/chain_spec.rs b/node-template/src/chain_spec.rs index b9f61e45f546b3a07e1900568a97282bf47868ba..3cb8d21d5d0dac64a6c38a18716d92b431085a15 100644 --- a/node-template/src/chain_spec.rs +++ b/node-template/src/chain_spec.rs @@ -1,14 +1,16 @@ -use primitives::{Ed25519AuthorityId, ed25519}; +use primitives::{ed25519, sr25519, Pair}; use node_template_runtime::{ AccountId, GenesisConfig, ConsensusConfig, TimestampConfig, BalancesConfig, - SudoConfig, IndicesConfig, FeesConfig, + SudoConfig, IndicesConfig, }; use substrate_service; +use ed25519::Public as AuthorityId; + // Note this is the URL for the telemetry server //const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; -/// Specialised `ChainSpec`. This is a specialisation of the general Substrate ChainSpec type. +/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = substrate_service::ChainSpec; /// The chain specification option. This is expected to come in from the CLI and @@ -22,6 +24,18 @@ pub enum Alternative { LocalTestnet, } +fn authority_key(s: &str) -> AuthorityId { + ed25519::Pair::from_string(&format!("//{}", s), None) + .expect("static values are valid; qed") + .public() +} + +fn account_key(s: &str) -> AccountId { + sr25519::Pair::from_string(&format!("//{}", s), None) + .expect("static values are valid; qed") + .public() +} + impl Alternative { /// Get an actual chain config from one of the alternatives. pub(crate) fn load(self) -> Result { @@ -30,11 +44,11 @@ impl Alternative { "Development", "dev", || testnet_genesis(vec![ - ed25519::Pair::from_seed(b"Alice ").public().into(), + authority_key("Alice") ], vec![ - ed25519::Pair::from_seed(b"Alice ").public().0.into(), + account_key("Alice") ], - ed25519::Pair::from_seed(b"Alice ").public().0.into() + account_key("Alice") ), vec![], None, @@ -46,17 +60,17 @@ impl Alternative { "Local Testnet", "local_testnet", || testnet_genesis(vec![ - ed25519::Pair::from_seed(b"Alice ").public().into(), - ed25519::Pair::from_seed(b"Bob ").public().into(), + authority_key("Alice"), + authority_key("Bob"), ], vec![ - ed25519::Pair::from_seed(b"Alice ").public().0.into(), - ed25519::Pair::from_seed(b"Bob ").public().0.into(), - ed25519::Pair::from_seed(b"Charlie ").public().0.into(), - ed25519::Pair::from_seed(b"Dave ").public().0.into(), - ed25519::Pair::from_seed(b"Eve ").public().0.into(), - ed25519::Pair::from_seed(b"Ferdie ").public().0.into(), + account_key("Alice"), + account_key("Bob"), + account_key("Charlie"), + account_key("Dave"), + account_key("Eve"), + account_key("Ferdie"), ], - ed25519::Pair::from_seed(b"Alice ").public().0.into() + account_key("Alice"), ), vec![], None, @@ -76,7 +90,7 @@ impl Alternative { } } -fn testnet_genesis(initial_authorities: Vec, endowed_accounts: Vec, root_key: AccountId) -> GenesisConfig { +fn testnet_genesis(initial_authorities: Vec, endowed_accounts: Vec, root_key: AccountId) -> GenesisConfig { GenesisConfig { consensus: Some(ConsensusConfig { code: include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm").to_vec(), @@ -84,24 +98,22 @@ fn testnet_genesis(initial_authorities: Vec, endowed_account }), system: None, timestamp: Some(TimestampConfig { - period: 5, // 5 second block time. + minimum_period: 5, // 10 second block time. }), indices: Some(IndicesConfig { ids: endowed_accounts.clone(), }), balances: Some(BalancesConfig { + transaction_base_fee: 1, + transaction_byte_fee: 0, existential_deposit: 500, transfer_fee: 0, creation_fee: 0, - balances: endowed_accounts.iter().map(|&k|(k, (1 << 60))).collect(), + balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), vesting: vec![], }), sudo: Some(SudoConfig { key: root_key, }), - fees: Some(FeesConfig { - transaction_base_fee: 1, - transaction_byte_fee: 0, - }) } } diff --git a/node-template/src/cli.rs b/node-template/src/cli.rs index 698f0ce7632131ae4715fa9e15ad6deb0908d8f4..258d2194a66c682d2c917bd8855a2ddf075826d4 100644 --- a/node-template/src/cli.rs +++ b/node-template/src/cli.rs @@ -66,6 +66,11 @@ fn run_until_exit( let _ = runtime.block_on(e.into_exit()); exit_send.fire(); + + // we eagerly drop the service so that the internal exit future is fired, + // but we need to keep holding a reference to the global telemetry guard + let _telemetry = service.telemetry(); + drop(service); Ok(()) } diff --git a/node-template/src/service.rs b/node-template/src/service.rs index cc51fba51c3f4fd5450f2a9787bfb29110c5ce89..2b7554c79dacd3723b3bc05bb0947a20d9d1bbf6 100644 --- a/node-template/src/service.rs +++ b/node-template/src/service.rs @@ -12,10 +12,9 @@ use substrate_service::{ TaskExecutor, }; use basic_authorship::ProposerFactory; -use node_executor; use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration, NothingExtra}; use substrate_client as client; -use primitives::ed25519::Pair; +use primitives::{ed25519::Pair, Pair as PairT}; use inherents::InherentDataProviders; use network::construct_simple_protocol; use substrate_executor::native_executor_instance; @@ -45,7 +44,7 @@ construct_service_factory! { Block = Block, RuntimeApi = RuntimeApi, NetworkProtocol = NodeProtocol { |config| Ok(NodeProtocol::new()) }, - RuntimeDispatch = node_executor::Executor, + RuntimeDispatch = Executor, FullTransactionPoolApi = transaction_pool::ChainApi, FullExecutor, Block, RuntimeApi>, Block> { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, LightTransactionPoolApi = transaction_pool::ChainApi, LightExecutor, Block, RuntimeApi>, Block> @@ -63,6 +62,7 @@ construct_service_factory! { let proposer = Arc::new(ProposerFactory { client: service.client(), transaction_pool: service.transaction_pool(), + inherents_pool: service.inherents_pool(), }); let client = service.client(); executor.spawn(start_aura( @@ -74,6 +74,7 @@ construct_service_factory! { service.network(), service.on_exit(), service.config.custom.inherent_data_providers.clone(), + service.config.force_authoring, )?); } @@ -85,28 +86,32 @@ construct_service_factory! { FullImportQueue = AuraImportQueue< Self::Block, > - { |config: &mut FactoryFullConfiguration , client: Arc>| - import_queue( - SlotDuration::get_or_compute(&*client)?, - client.clone(), - None, - client, - NothingExtra, - config.custom.inherent_data_providers.clone(), - ).map_err(Into::into) + { |config: &mut FactoryFullConfiguration , client: Arc>| { + import_queue::<_, _, _, Pair>( + SlotDuration::get_or_compute(&*client)?, + client.clone(), + None, + client, + NothingExtra, + config.custom.inherent_data_providers.clone(), + true, + ).map_err(Into::into) + } }, LightImportQueue = AuraImportQueue< Self::Block, > - { |config: &mut FactoryFullConfiguration, client: Arc>| - import_queue( - SlotDuration::get_or_compute(&*client)?, - client.clone(), - None, - client, - NothingExtra, - config.custom.inherent_data_providers.clone(), - ).map_err(Into::into) + { |config: &mut FactoryFullConfiguration, client: Arc>| { + import_queue::<_, _, _, Pair>( + SlotDuration::get_or_compute(&*client)?, + client.clone(), + None, + client, + NothingExtra, + config.custom.inherent_data_providers.clone(), + true, + ).map_err(Into::into) + } }, } } diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml index 7b6549ba5066efdf1f759352e1666ae0ac2a8a44..28fb297e5731a7b0a617bd568c62e20010e2dc23 100644 --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -12,8 +12,7 @@ tokio = "0.1.7" futures = "0.1" exit-future = "0.1" cli = { package = "substrate-cli", path = "../../core/cli" } -parity-codec = { version = "3.1" } -slog = "^2" +parity-codec = { version = "3.2" } sr-io = { path = "../../core/sr-io" } client = { package = "substrate-client", path = "../../core/client" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } diff --git a/node/cli/build.rs b/node/cli/build.rs index 6eab113babf88e1375077edea958590c6df89654..e7a7b271f15034498ad00dbf17827a96a7a0a127 100644 --- a/node/cli/build.rs +++ b/node/cli/build.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index 85d26702b873fda36ec9ed1dbdaa5ef53c67ed40..a45b25249fbe3c099ae744af2a3ce450b227c9df 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,21 +16,19 @@ //! Substrate chain configurations. -use primitives::{Ed25519AuthorityId as AuthorityId, ed25519}; +use primitives::{ed25519::Public as AuthorityId, ed25519, sr25519, Pair, crypto::UncheckedInto}; use node_primitives::AccountId; use node_runtime::{ConsensusConfig, CouncilSeatsConfig, CouncilVotingConfig, DemocracyConfig, - SessionConfig, StakingConfig, TimestampConfig, BalancesConfig, TreasuryConfig, - SudoConfig, ContractConfig, GrandpaConfig, IndicesConfig, FeesConfig, Permill, Perbill}; + SessionConfig, StakingConfig, StakerStatus, TimestampConfig, BalancesConfig, TreasuryConfig, + SudoConfig, ContractConfig, GrandpaConfig, IndicesConfig, Permill, Perbill}; pub use node_runtime::GenesisConfig; use substrate_service; use hex_literal::{hex, hex_impl}; - -use substrate_keystore::pad_seed; use substrate_telemetry::TelemetryEndpoints; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; -/// Specialised `ChainSpec`. +/// Specialized `ChainSpec`. pub type ChainSpec = substrate_service::ChainSpec; /// Dried Danta testnet generator @@ -40,25 +38,30 @@ pub fn dried_danta_config() -> Result { fn staging_testnet_config_genesis() -> GenesisConfig { // stash, controller, session-key + // generated with secret: + // for i in 1 2 3 4 ; do for j in stash controller; do subkey -p danta-$i-$j restore $secret; done; done + // and + // for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 -p danta-$i-$j restore $secret; done; done let initial_authorities: Vec<(AccountId, AccountId, AuthorityId)> = vec![( - hex!["fbecf7767fc63a6f9fa8094bbc5751d7269cd8e619cfdd9edfbe1fbc716b173e"].into(), // 5Hm2GcbuUct7sWX8d56zRktxr9D9Lw5hTFjSUhUoVHwFNmYW TODO: change once we switch to sr25519 - hex!["6ed35e632190b9c795f019030e6c5cff1508655db28c83577e0a4366c9bd5773"].into(), // 5Ea1uyGz6H5WHZhWvPDxxLXWyiUkzWDwx54Hcn8LJ5dbFawH TODO: change once we switch to sr25519 - hex!["82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5"].into(), + hex!["d807f8bd6b4b02b3db716dd5372960b094ed0e62b5704a07bc990130a642992b"].unchecked_into(), // 5GwxZv7LxSUQn89TLUaLi3oEWhFcabqW3nHcEg2J88gZNhrb + hex!["1a934af462454e512e22b5d9455c0c3c2df479b1c61406b3d990f6bc2eb25e09"].unchecked_into(), // 5CfYrg5cW8UebBdfJpJbKFhZLyk7yHWXUgdxZnSGb2dWKgpt + hex!["831fcce3a9565baf093b52568a8cb9875cb54974d80da8fc4f0cc767128a23e9"].unchecked_into(), // 5F2daQPHK7yv4Yuwyz3cggvvn1R5u1ofGMQ5LK5XvnfebMcX ),( - hex!["30b76ef977b84a575992ef52f561db315221123c68074269d3d51ce211c4a3dc"].into(), // 5DAaeTwVuyUmTyLBR5vKEDWeDJ75nhLutDuCJH58it7EHDM2 TODO: change once we switch to sr25519 - hex!["a270edf24cb2a472b0e913fc43bfd4da0ef337cc715eaf94073d5198f7659f0c"].into(), // 5FjhAKgzpuzt1dYWE7H7Jb1sEHSuG5hcyZdPtfX829gmFVXh TODO: change once we switch to sr25519 - hex!["4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7"].into(), + hex!["12652f26e427c56268095bb0ec5824471e37722b073a9fa5de61c61c1de94656"].unchecked_into(), // 5CUpn2JmpsWkHQjZgWjN3rqPEUnjjUQZYcMk14nbUgR2Gpab + hex!["5279e73e22971d729276ebad4eb6804d1b9c0c35bd32e8aba4513c674760a461"].unchecked_into(), // 5Dvqzke7Mdp3fP6Ysut7UXPSepPr3Qguys6LNkZGPSwXwAkR + hex!["dbe61640d854bb7bf83cbfaf638a8a4c76c49a919ec3bbdd86799061fc1903e4"].unchecked_into(), // 5H32hCtKf6nXSckviVhUvWb7N14wDCRunRkCM29mxEXwjcUZ ),( - hex!["7b9e79c1bfc71ad0c4389565c01e79269dc512cb9bd856489671662481355417"].into(), // 5ErnpkRUbmM3WdbQwnVwfZeYs3iKmggEQceyB9db9ft18dSn TODO: change once we switch to sr25519 - hex!["9ffec660c4d328306cf5e38faf4b132fb5c9f38287af95d9b25629fc29de3945"].into(), // 5FgV9vxNpdCXMUmHCLQcsN4mUUUG6ZpFuvAMrm5X4BUnFhie TODO: change once we switch to sr25519 - hex!["063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5"].into(), + hex!["a81d738fdeeaed440cfce5635e0820d0d23e89207cf66a62b8c0d2a968e37d32"].unchecked_into(), // 5Fs8ehAjDEnenDwULCPnEr3HVXgepAVfyk9ABW84NfxCYtWD + hex!["443a2c779a5f5dada8ee6921efec9673f67e5ce1bd6012899ff6c1adc437696c"].unchecked_into(), // 5DcAPqR269myKXhZmwbU1x2xLbuTojr85jHNRuDhrFdZ3vwi + hex!["5bc01f56225e8602372fb343dba65a73e20c55bdbb3b8343a8f34df298a616fb"].unchecked_into(), // 5E91HbY2xo2qDJzi3KY8nRXjDNAQE9WtmMaji6YRwT8DAuK1 ),( - hex!["7e58b096b95c4b3b271f27fedd9f2c51edd48b9d37046240e601180c9dcc8c27"].into(), // 5EvNEhYYd4b9giczuCo2o8bfLZoKW9jnTeUukfL1NWsAAeEx TODO: change once we switch to sr25519 - hex!["36dfc933bb0848d8addf16a961369b2e122633a5819a19e43c8142381a1280e3"].into(), // 5DJevPKpz4EEvmSpK7W6KemS3i5JYPq5FEuEewgRY2cZCxNg TODO: change once we switch to sr25519 - hex!["8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c"].into(), + hex!["e269e835e0bc07c497d55bc17c7bb29c85c5615f9e61582ffdeca7e5f5c66578"].unchecked_into(), // 5HBa95U5HDFCV1N5Xyrjti65F71tHRQcPbZBmkxRJ39SpqzM + hex!["3e9829e6fd4fc7501b504fc16f12177c6c7f38aeb3b8344efb9b15ee85118b2c"].unchecked_into(), // 5DUn2afs2QevZ6PrGu8snrt76157oacH6JXUD8JNM18VKMwK + hex!["0fd673ee5e95ed124bcd71463ff924c810573dad91527ab9d2b5af36f66ff84b"].unchecked_into(), // 5CRUHGLA1JYe2v4p479VCHybqjB9uBXjGkJ2npdduVdrTuUM )]; + // generated with secret: subkey -p danta-root restore $secret let endowed_accounts: Vec = vec![ - hex!["f295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd"].into(), // 5HYmsxGRAmZMjyZYmf7uGPL2YDQGHEt6NjGrfUuxNEgeGBRN TODO: change once we switch to sr25519 + hex!["343df6f04ffae0840f214f6cb0da00b612c7e9347f980e7afafc520582f79136"].unchecked_into(), // 5DFCkiP9vky31C1ZP3LpuQYinLAFwQqq6vda7NXa8ALCpq5D ]; const MILLICENTS: u128 = 1_000_000_000; const CENTS: u128 = 1_000 * MILLICENTS; // assume this is worth about a cent. @@ -79,8 +82,10 @@ fn staging_testnet_config_genesis() -> GenesisConfig { }), system: None, balances: Some(BalancesConfig { - balances: endowed_accounts.iter() - .map(|&k| (k, ENDOWMENT)) + transaction_base_fee: 1 * CENTS, + transaction_byte_fee: 10 * MILLICENTS, + balances: endowed_accounts.iter().cloned() + .map(|k| (k, ENDOWMENT)) .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) .collect(), existential_deposit: 1 * DOLLARS, @@ -94,7 +99,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig { .collect::>(), }), session: Some(SessionConfig { - validators: initial_authorities.iter().map(|x| x.1.into()).collect(), + validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), session_length: 5 * MINUTES, keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::>(), }), @@ -102,15 +107,14 @@ fn staging_testnet_config_genesis() -> GenesisConfig { current_era: 0, offline_slash: Perbill::from_billionths(1_000_000), session_reward: Perbill::from_billionths(2_065), - current_offline_slash: 0, current_session_reward: 0, validator_count: 7, sessions_per_era: 12, bonding_duration: 60 * MINUTES, offline_slash_grace: 4, minimum_validator_count: 4, - stakers: initial_authorities.iter().map(|x| (x.0.into(), x.1.into(), STASH)).collect(), - invulnerables: initial_authorities.iter().map(|x| x.1.into()).collect(), + stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)).collect(), + invulnerables: initial_authorities.iter().map(|x| x.1.clone()).collect(), }), democracy: Some(DemocracyConfig { launch_period: 10 * MINUTES, // 1 day per public referendum @@ -137,7 +141,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig { enact_delay_period: 0, }), timestamp: Some(TimestampConfig { - period: SECS_PER_BLOCK / 2, // due to the nature of aura the slots are 2*period + minimum_period: SECS_PER_BLOCK / 2, // due to the nature of aura the slots are 2*period }), treasury: Some(TreasuryConfig { proposal_bond: Permill::from_percent(5), @@ -146,6 +150,10 @@ fn staging_testnet_config_genesis() -> GenesisConfig { burn: Permill::from_percent(50), }), contract: Some(ContractConfig { + transaction_base_fee: 1 * CENTS, + transaction_byte_fee: 10 * MILLICENTS, + transfer_fee: 1 * CENTS, + creation_fee: 1 * CENTS, contract_fee: 1 * CENTS, call_base_fee: 1000, create_base_fee: 1000, @@ -160,10 +168,6 @@ fn staging_testnet_config_genesis() -> GenesisConfig { grandpa: Some(GrandpaConfig { authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), }), - fees: Some(FeesConfig { - transaction_base_fee: 1 * CENTS, - transaction_byte_fee: 10 * MILLICENTS, - }), } } @@ -182,23 +186,26 @@ pub fn staging_testnet_config() -> ChainSpec { ) } -/// Helper function to generate AuthorityID from seed +/// Helper function to generate AccountId from seed pub fn get_account_id_from_seed(seed: &str) -> AccountId { - let padded_seed = pad_seed(seed); - // NOTE from ed25519 impl: - // prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests. - ed25519::Pair::from_seed(&padded_seed).public().0.into() + sr25519::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// Helper function to generate AuthorityId from seed +pub fn get_session_key_from_seed(seed: &str) -> AuthorityId { + ed25519::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() } /// Helper function to generate stash, controller and session key from seed pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, AuthorityId) { - let padded_seed = pad_seed(seed); - // NOTE from ed25519 impl: - // prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests. ( - get_account_id_from_seed(&format!("{}-stash", seed)), + get_account_id_from_seed(&format!("{}//stash", seed)), get_account_id_from_seed(seed), - ed25519::Pair::from_seed(&padded_seed).public().0.into() + get_session_key_from_seed(seed) ) } @@ -216,6 +223,12 @@ pub fn testnet_genesis( get_account_id_from_seed("Dave"), get_account_id_from_seed("Eve"), get_account_id_from_seed("Ferdie"), + get_account_id_from_seed("Alice//stash"), + get_account_id_from_seed("Bob//stash"), + get_account_id_from_seed("Charlie//stash"), + get_account_id_from_seed("Dave//stash"), + get_account_id_from_seed("Eve//stash"), + get_account_id_from_seed("Ferdie//stash"), ] }); @@ -232,14 +245,16 @@ pub fn testnet_genesis( ids: endowed_accounts.clone(), }), balances: Some(BalancesConfig { + transaction_base_fee: 1, + transaction_byte_fee: 0, existential_deposit: 500, transfer_fee: 0, creation_fee: 0, - balances: endowed_accounts.iter().map(|&k| (k.into(), ENDOWMENT)).collect(), + balances: endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect(), vesting: vec![], }), session: Some(SessionConfig { - validators: initial_authorities.iter().map(|x| x.1.into()).collect(), + validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), session_length: 10, keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::>(), }), @@ -251,11 +266,10 @@ pub fn testnet_genesis( bonding_duration: 2 * 60 * 12, offline_slash: Perbill::zero(), session_reward: Perbill::zero(), - current_offline_slash: 0, current_session_reward: 0, offline_slash_grace: 0, - stakers: initial_authorities.iter().map(|x| (x.0.into(), x.1.into(), STASH)).collect(), - invulnerables: initial_authorities.iter().map(|x| x.1.into()).collect(), + stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)).collect(), + invulnerables: initial_authorities.iter().map(|x| x.1.clone()).collect(), }), democracy: Some(DemocracyConfig { launch_period: 9, @@ -267,7 +281,7 @@ pub fn testnet_genesis( council_seats: Some(CouncilSeatsConfig { active_council: endowed_accounts.iter() .filter(|&endowed| initial_authorities.iter().find(|&(_, controller, _)| controller == endowed).is_none()) - .map(|a| (a.clone().into(), 1000000)).collect(), + .map(|a| (a.clone(), 1000000)).collect(), candidacy_bond: 10, voter_bond: 2, present_slash_per_voter: 1, @@ -275,7 +289,7 @@ pub fn testnet_genesis( presentation_duration: 10, approval_voting_period: 20, term_duration: 1000000, - desired_seats: (endowed_accounts.len() - initial_authorities.len()) as u32, + desired_seats: (endowed_accounts.len() / 2 - initial_authorities.len()) as u32, inactive_grace_period: 1, }), council_voting: Some(CouncilVotingConfig { @@ -284,7 +298,7 @@ pub fn testnet_genesis( enact_delay_period: 0, }), timestamp: Some(TimestampConfig { - period: 2, // 2*2=4 second block time. + minimum_period: 2, // 2*2=4 second block time. }), treasury: Some(TreasuryConfig { proposal_bond: Permill::from_percent(5), @@ -293,6 +307,10 @@ pub fn testnet_genesis( burn: Permill::from_percent(50), }), contract: Some(ContractConfig { + transaction_base_fee: 1, + transaction_byte_fee: 0, + transfer_fee: 0, + creation_fee: 0, contract_fee: 21, call_base_fee: 135, create_base_fee: 175, @@ -307,10 +325,6 @@ pub fn testnet_genesis( grandpa: Some(GrandpaConfig { authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), }), - fees: Some(FeesConfig { - transaction_base_fee: 1, - transaction_byte_fee: 0, - }), } } @@ -319,7 +333,7 @@ fn development_config_genesis() -> GenesisConfig { vec![ get_authority_keys_from_seed("Alice"), ], - get_account_id_from_seed("Alice").into(), + get_account_id_from_seed("Alice"), None, ) } @@ -335,7 +349,7 @@ fn local_testnet_genesis() -> GenesisConfig { get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Bob"), ], - get_account_id_from_seed("Alice").into(), + get_account_id_from_seed("Alice"), None, ) } @@ -353,7 +367,7 @@ mod tests { fn local_testnet_genesis_instant() -> GenesisConfig { let mut genesis = local_testnet_genesis(); - genesis.timestamp = Some(TimestampConfig { period: 0 }); + genesis.timestamp = Some(TimestampConfig { minimum_period: 1 }); genesis } diff --git a/node/cli/src/error.rs b/node/cli/src/error.rs index eba18eacdfffc4ceb279f810bf90d8399eff8da5..dd5448ac8ad6366813387e7694a4f69872117ff7 100644 --- a/node/cli/src/error.rs +++ b/node/cli/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/node/cli/src/lib.rs b/node/cli/src/lib.rs index 5586a9b1913575fcdcc364d01f1cc7ea1d7ea73a..1b103b7bfc1961fc6bbb35f00be0ca613334b82a 100644 --- a/node/cli/src/lib.rs +++ b/node/cli/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 9b1139f838e1dd02ff419efd3d6c72f6f8846db9..a1fb61f175b4b6d84651035e8a57f7853224cffb 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ use client; use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration, NothingExtra}; use grandpa; use node_executor; -use primitives::ed25519::Pair; +use primitives::{Pair as PairT, ed25519}; use node_primitives::Block; use node_runtime::{GenesisConfig, RuntimeApi}; use substrate_service::{ @@ -76,7 +76,7 @@ construct_service_factory! { { |config: FactoryFullConfiguration, executor: TaskExecutor| FullComponents::::new(config, executor) }, AuthoritySetup = { - |mut service: Self::FullService, executor: TaskExecutor, local_key: Option>| { + |mut service: Self::FullService, executor: TaskExecutor, local_key: Option>| { let (block_import, link_half) = service.config.custom.grandpa_import_setup.take() .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); @@ -85,6 +85,7 @@ construct_service_factory! { let proposer = Arc::new(substrate_basic_authorship::ProposerFactory { client: service.client(), transaction_pool: service.transaction_pool(), + inherents_pool: service.inherents_pool(), }); let client = service.client(); @@ -97,16 +98,23 @@ construct_service_factory! { service.network(), service.on_exit(), service.config.custom.inherent_data_providers.clone(), + service.config.force_authoring, )?); info!("Running Grandpa session as Authority {}", key.public()); } + let local_key = if service.config.disable_grandpa { + None + } else { + local_key + }; + executor.spawn(grandpa::run_grandpa( grandpa::Config { local_key, // FIXME #1578 make this available through chainspec - gossip_duration: Duration::new(4, 0), + gossip_duration: Duration::from_millis(333), justification_period: 4096, name: Some(service.config.name.clone()) }, @@ -133,27 +141,29 @@ construct_service_factory! { config.custom.grandpa_import_setup = Some((block_import.clone(), link_half)); - import_queue( + import_queue::<_, _, _, ed25519::Pair>( slot_duration, block_import, Some(justification_import), client, NothingExtra, config.custom.inherent_data_providers.clone(), + true, ).map_err(Into::into) }}, LightImportQueue = AuraImportQueue { |config: &FactoryFullConfiguration, client: Arc>| { - import_queue( - SlotDuration::get_or_compute(&*client)?, - client.clone(), - None, - client, - NothingExtra, - config.custom.inherent_data_providers.clone(), - ).map_err(Into::into) - } - }, + import_queue::<_, _, _, ed25519::Pair>( + SlotDuration::get_or_compute(&*client)?, + client.clone(), + None, + client, + NothingExtra, + config.custom.inherent_data_providers.clone(), + true, + ).map_err(Into::into) + } + }, } } diff --git a/node/executor/Cargo.toml b/node/executor/Cargo.toml index d0e329b264f27d7969d265a98b75823e7f3d781b..3c2e9a688cb9bb05ee795b9ee26b5c46b1f0b4fa 100644 --- a/node/executor/Cargo.toml +++ b/node/executor/Cargo.toml @@ -6,8 +6,8 @@ description = "Substrate node implementation in Rust." edition = "2018" [dependencies] -trie-root = "0.11" -parity-codec = "3.1" +trie-root = "0.12" +parity-codec = "3.2" runtime_io = { package = "sr-io", path = "../../core/sr-io" } state_machine = { package = "substrate-state-machine", path = "../../core/state-machine" } substrate-executor = { path = "../../core/executor" } @@ -30,7 +30,6 @@ treasury = { package = "srml-treasury", path = "../../srml/treasury" } contract = { package = "srml-contract", path = "../../srml/contract" } grandpa = { package = "srml-grandpa", path = "../../srml/grandpa" } indices = { package = "srml-indices", path = "../../srml/indices" } -fees = { package = "srml-fees", path = "../../srml/fees" } wabt = "~0.7.4" [features] diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 5b100c3a939626cf9ec6a864e874f9ab34a2ba0b..c855a4e6f00c50c0a69b980842be3b2472eeeb3d 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! A `CodeExecutor` specialisation which uses natively compiled runtime when the wasm to be +//! A `CodeExecutor` specialization which uses natively compiled runtime when the wasm to be //! executed is equivalent to the natively compiled code. #![cfg_attr(feature = "benchmarks", feature(test))] @@ -31,22 +31,20 @@ mod tests { use super::Executor; use substrate_executor::{WasmExecutor, NativeExecutionDispatch}; use parity_codec::{Encode, Decode, Joiner}; - use keyring::ed25519::Keyring; + use keyring::{AuthorityKeyring, AccountKeyring}; use runtime_support::{Hashable, StorageValue, StorageMap, traits::Currency}; use state_machine::{CodeExecutor, Externalities, TestExternalities}; - use primitives::{ - twox_128, Blake2Hasher, ChangesTrieConfiguration, ed25519::{Public, Pair}, NeverNativeValue, - NativeOrEncoded - }; + use primitives::{twox_128, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, + NativeOrEncoded}; use node_primitives::{Hash, BlockNumber, AccountId}; - use runtime_primitives::traits::{Header as HeaderT, Digest as DigestT, Hash as HashT}; + use runtime_primitives::traits::{Header as HeaderT, Hash as HashT}; use runtime_primitives::{generic, generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; - use {balances, indices, staking, session, system, consensus, timestamp, treasury, contract}; + use {balances, indices, session, system, staking, consensus, timestamp, treasury, contract}; use contract::ContractAddressFor; use system::{EventRecord, Phase}; use node_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System, - SystemConfig, GrandpaConfig, IndicesConfig, FeesConfig, Event, Log}; + SystemConfig, GrandpaConfig, IndicesConfig, Event, Log}; use wabt; use primitives::map; @@ -55,27 +53,27 @@ mod tests { const GENESIS_HASH: [u8; 32] = [69u8; 32]; fn alice() -> AccountId { - AccountId::from(Keyring::Alice.to_raw_public()) + AccountKeyring::Alice.into() } fn bob() -> AccountId { - AccountId::from(Keyring::Bob.to_raw_public()) + AccountKeyring::Bob.into() } fn charlie() -> AccountId { - AccountId::from(Keyring::Charlie.to_raw_public()) + AccountKeyring::Charlie.into() } fn dave() -> AccountId { - AccountId::from(Keyring::Dave.to_raw_public()) + AccountKeyring::Dave.into() } fn eve() -> AccountId { - AccountId::from(Keyring::Eve.to_raw_public()) + AccountKeyring::Eve.into() } fn ferdie() -> AccountId { - AccountId::from(Keyring::Ferdie.to_raw_public()) + AccountKeyring::Ferdie.into() } fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { @@ -83,12 +81,12 @@ mod tests { Some((signed, index)) => { let era = Era::mortal(256, 0); let payload = (index.into(), xt.function, era, GENESIS_HASH); - let pair = Pair::from(Keyring::from_public(Public::from_raw(signed.clone().into())).unwrap()); + let key = AccountKeyring::from_public(&signed).unwrap(); let signature = payload.using_encoded(|b| { if b.len() > 256 { - pair.sign(&runtime_io::blake2_256(b)) + key.sign(&runtime_io::blake2_256(b)) } else { - pair.sign(b) + key.sign(b) } }).into(); UncheckedExtrinsic { @@ -128,13 +126,13 @@ mod tests { twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + twox_128(>::key()).to_vec() => vec![70u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); let r = executor().call::<_, NeverNativeValue, fn() -> _>( &mut t, - "Core_initialise_block", + "Core_initialize_block", &vec![].and(&from_block_number(1u64)), true, None, @@ -161,13 +159,13 @@ mod tests { twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + twox_128(>::key()).to_vec() => vec![70u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); let r = executor().call::<_, NeverNativeValue, fn() -> _>( &mut t, - "Core_initialise_block", + "Core_initialize_block", &vec![].and(&from_block_number(1u64)), true, None, @@ -194,13 +192,13 @@ mod tests { twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); let r = executor().call::<_, NeverNativeValue, fn() -> _>( &mut t, - "Core_initialise_block", + "Core_initialize_block", &vec![].and(&from_block_number(1u64)), true, None, @@ -231,13 +229,13 @@ mod tests { twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); let r = executor().call::<_, NeverNativeValue, fn() -> _>( &mut t, - "Core_initialise_block", + "Core_initialize_block", &vec![].and(&from_block_number(1u64)), true, None, @@ -259,7 +257,7 @@ mod tests { } fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities { - let three = [3u8; 32].into(); + let three = AccountId::from_raw([3u8; 32]); TestExternalities::new_with_code(code, GenesisConfig { consensus: Some(Default::default()), system: Some(SystemConfig { @@ -273,12 +271,14 @@ mod tests { ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()], }), balances: Some(BalancesConfig { + transaction_base_fee: 1, + transaction_byte_fee: 0, balances: vec![ (alice(), 111), (bob(), 100), (charlie(), 100_000_000), - (dave(), 100), - (eve(), 100), + (dave(), 111), + (eve(), 101), (ferdie(), 100), ], existential_deposit: 0, @@ -288,23 +288,26 @@ mod tests { }), session: Some(SessionConfig { session_length: 2, - validators: vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into(), three], + validators: vec![AccountKeyring::One.into(), AccountKeyring::Two.into(), three], keys: vec![ - (alice(), keyring::ed25519::Keyring::Alice.to_raw_public().into()), - (bob(), keyring::ed25519::Keyring::Bob.to_raw_public().into()), - (charlie(), keyring::ed25519::Keyring::Charlie.to_raw_public().into()) + (alice(), AuthorityKeyring::Alice.into()), + (bob(), AuthorityKeyring::Bob.into()), + (charlie(), AuthorityKeyring::Charlie.into()) ] }), staking: Some(StakingConfig { sessions_per_era: 2, current_era: 0, - stakers: vec![(dave(), alice(), 111), (eve(), bob(), 100), (ferdie(), charlie(), 100)], + stakers: vec![ + (dave(), alice(), 111, staking::StakerStatus::Validator), + (eve(), bob(), 100, staking::StakerStatus::Validator), + (ferdie(), charlie(), 100, staking::StakerStatus::Validator) + ], validator_count: 3, minimum_validator_count: 0, bonding_duration: 0, offline_slash: Perbill::zero(), session_reward: Perbill::zero(), - current_offline_slash: 0, current_session_reward: 0, offline_slash_grace: 0, invulnerables: vec![alice(), bob(), charlie()], @@ -317,15 +320,7 @@ mod tests { contract: Some(Default::default()), sudo: Some(Default::default()), grandpa: Some(GrandpaConfig { - authorities: vec![ // set these so no GRANDPA events fire when session changes - (keyring::ed25519::Keyring::Alice.to_raw_public().into(), 1), - (keyring::ed25519::Keyring::Bob.to_raw_public().into(), 1), - (keyring::ed25519::Keyring::Charlie.to_raw_public().into(), 1), - ], - }), - fees: Some(FeesConfig { - transaction_base_fee: 1, - transaction_byte_fee: 0, + authorities: vec![], }), }.build_storage().unwrap().0) } @@ -358,7 +353,7 @@ mod tests { // execute the block to get the real header. Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( env, - "Core_initialise_block", + "Core_initialize_block", &header.encode(), true, None, @@ -376,7 +371,7 @@ mod tests { let header = match Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( env, - "BlockBuilder_finalise_block", + "BlockBuilder_finalize_block", &[0u8;0], true, None, @@ -447,12 +442,7 @@ mod tests { ] ); - let mut digest = generic::Digest::::default(); - digest.push(Log::from(::grandpa::RawLog::AuthoritiesChangeSignal(0, vec![ - (Keyring::One.to_raw_public().into(), 1), - (Keyring::Two.to_raw_public().into(), 1), - ([3u8; 32].into(), 1), - ]))); + let digest = generic::Digest::::default(); assert_eq!(Header::decode(&mut &block2.0[..]).unwrap().digest, digest); (block1, block2) @@ -525,13 +515,9 @@ mod tests { phase: Phase::Finalization, event: Event::treasury(treasury::RawEvent::Rollover(0)) }, - EventRecord { - phase: Phase::Finalization, - event: Event::fees(fees::RawEvent::Charged(1, 1)) - } ]); }); - + executor().call::<_, NeverNativeValue, fn() -> _>( &mut t, "Core_execute_block", @@ -543,7 +529,7 @@ mod tests { runtime_io::with_externalities(&mut t, || { // bob sends 5, alice sends 15 | bob += 10, alice -= 10 // 111 - 69 - 1 - 10 - 1 = 30 - assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1 - 10 - 1); + assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1 - 10 - 1); // 100 + 69 + 10 - 1 = 178 assert_eq!(Balances::total_balance(&bob()), 100 + 69 + 10 - 1); assert_eq!(System::events(), vec![ @@ -585,18 +571,6 @@ mod tests { phase: Phase::Finalization, event: Event::session(session::RawEvent::NewSession(1)) }, - // EventRecord { - // phase: Phase::Finalization, - // event: Event::staking(staking::RawEvent::Reward(0)) - // }, - EventRecord { - phase: Phase::Finalization, - event: Event::grandpa(::grandpa::RawEvent::NewAuthorities(vec![ - (Keyring::One.to_raw_public().into(), 1), - (Keyring::Two.to_raw_public().into(), 1), - ([3u8; 32].into(), 1), - ])), - }, EventRecord { phase: Phase::Finalization, event: Event::treasury(treasury::RawEvent::Spending(0)) @@ -609,14 +583,6 @@ mod tests { phase: Phase::Finalization, event: Event::treasury(treasury::RawEvent::Rollover(0)) }, - EventRecord { - phase: Phase::Finalization, - event: Event::fees(fees::RawEvent::Charged(1, 1)) - }, - EventRecord { - phase: Phase::Finalization, - event: Event::fees(fees::RawEvent::Charged(2, 1)) - } ]); }); } @@ -641,7 +607,7 @@ mod tests { runtime_io::with_externalities(&mut t, || { // bob sends 5, alice sends 15 | bob += 10, alice -= 10 // 111 - 69 - 1 - 10 - 1 = 30 - assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1 - 10 - 1); + assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1 - 10 - 1); // 100 + 69 + 10 - 1 = 178 assert_eq!(Balances::total_balance(&bob()), 100 + 69 + 10 - 1); }); @@ -767,7 +733,7 @@ mod tests { CheckedExtrinsic { signed: Some((charlie(), 2)), function: Call::Contract( - contract::Call::call::(indices::address::Address::Id(addr), 10, 10_000, vec![0x00, 0x01, 0x02, 0x03]) + contract::Call::call::(indices::address::Address::Id(addr.clone()), 10, 10_000, vec![0x00, 0x01, 0x02, 0x03]) ), }, ] @@ -837,11 +803,11 @@ mod tests { twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + twox_128(>::key()).to_vec() => vec![70u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialise_block", &vec![].and(&from_block_number(1u64))); + let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); @@ -859,11 +825,11 @@ mod tests { twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialise_block", &vec![].and(&from_block_number(1u64))); + let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); @@ -896,7 +862,7 @@ mod tests { #[test] fn full_wasm_block_import_works_with_changes_trie() { let block1 = changes_trie_block(); - + let mut t = new_test_ext(COMPACT_CODE, true); WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap(); diff --git a/node/primitives/Cargo.toml b/node/primitives/Cargo.toml index bdb1fd64cd4118df0a77a820473ca16205b5083c..b7da80c9a879e3b03f6d02758334b9828f02fea5 100644 --- a/node/primitives/Cargo.toml +++ b/node/primitives/Cargo.toml @@ -5,9 +5,9 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "3.1", default-features = false } +parity-codec = { version = "3.2", default-features = false } parity-codec-derive = { version = "3.1", default-features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } @@ -26,5 +26,5 @@ std = [ "rstd/std", "runtime_primitives/std", "serde_derive", - "serde/std", + "serde", ] diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs index 4c72239e6d57524dcb7cacc41f0c9c5e7a48e922..0d8906c47df817f4c6c62c2a3b6d54365b47bb77 100644 --- a/node/primitives/src/lib.rs +++ b/node/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,14 +22,14 @@ #![cfg_attr(not(feature = "std"), feature(alloc))] use runtime_primitives::{ - generic, traits::{Verify, BlakeTwo256}, Ed25519Signature, OpaqueExtrinsic + generic, traits::{Verify, BlakeTwo256}, OpaqueExtrinsic, AnySignature }; /// An index to a block. pub type BlockNumber = u64; -/// Alias to 512-bit hash when used in the context of a signature on the chain. -pub type Signature = Ed25519Signature; +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = AnySignature; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. @@ -44,7 +44,10 @@ pub type Balance = u128; /// The Ed25519 pub key of an session that belongs to an authority of the chain. This is /// exactly equivalent to what the substrate calls an "authority". -pub type SessionKey = primitives::Ed25519AuthorityId; +pub type AuthorityId = ::Signer; + +/// Alias to 512-bit hash when used in the context of a session signature on the chain. +pub type AuthoritySignature = primitives::ed25519::Signature; /// Index of a transaction in the chain. pub type Index = u64; @@ -56,7 +59,8 @@ pub type Hash = primitives::H256; pub type Timestamp = u64; /// Header type. -pub type Header = generic::Header>; +/// +pub type Header = generic::Header>; /// Block type. pub type Block = generic::Block; /// Block ID. diff --git a/node/runtime/Cargo.toml b/node/runtime/Cargo.toml index d009a544d594647837be2c30a6b53c787c1fc52e..3fe3adce30a493028e831363001b322cb39c6f36 100644 --- a/node/runtime/Cargo.toml +++ b/node/runtime/Cargo.toml @@ -7,11 +7,12 @@ edition = "2018" [dependencies] integer-sqrt = { version = "0.1.2" } safe-mix = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../../core/primitives", default-features = false } client = { package = "substrate-client", path = "../../core/client", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false } version = { package = "sr-version", path = "../../core/sr-version", default-features = false } support = { package = "srml-support", path = "../../srml/support", default-features = false } aura = { package = "srml-aura", path = "../../srml/aura", default-features = false } @@ -30,14 +31,13 @@ system = { package = "srml-system", path = "../../srml/system", default-features timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default-features = false } treasury = { package = "srml-treasury", path = "../../srml/treasury", default-features = false } sudo = { package = "srml-sudo", path = "../../srml/sudo", default-features = false } -srml-upgrade-key = { path = "../../srml/upgrade-key", default-features = false } -fees = { package = "srml-fees", path = "../../srml/fees", default-features = false } node-primitives = { path = "../primitives", default-features = false } consensus_aura = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default-features = false } rustc-hex = { version = "2.0", optional = true } hex-literal = { version = "0.1.0", optional = true } serde = { version = "1.0", optional = true } substrate-keyring = { path = "../../core/keyring", optional = true } +consensus_authorities = { package = "substrate-consensus-authorities", path = "../../core/consensus/authorities", default-features = false } [features] default = ["std"] @@ -61,11 +61,9 @@ std = [ "timestamp/std", "treasury/std", "sudo/std", - "srml-upgrade-key/std", - "fees/std", "version/std", "node-primitives/std", - "serde/std", + "serde", "safe-mix/std", "client/std", "consensus_aura/std", diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index d9089f6b0ad5b5cabd50caeb27ab7c47e3725f12..8be70a6bcfb1e5a4c124af122dfa28329855764d 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,13 +21,10 @@ #![recursion_limit="256"] use rstd::prelude::*; -use parity_codec::{Encode, Decode}; -#[cfg(feature = "std")] -use support::{Serialize, Deserialize}; use support::construct_runtime; use substrate_primitives::u32_trait::{_2, _4}; use node_primitives::{ - AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature + AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, AuthorityId, Signature, AuthoritySignature }; use grandpa::fg_primitives::{self, ScheduledChange}; use client::{ @@ -37,7 +34,8 @@ use client::{ use runtime_primitives::{ApplyResult, generic, create_runtime_str}; use runtime_primitives::transaction_validity::TransactionValidity; use runtime_primitives::traits::{ - Convert, BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, + BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, CurrencyToVoteHandler, + AuthorityIdFor, }; use version::RuntimeVersion; use council::{motions as council_motions, voting as council_voting}; @@ -54,14 +52,15 @@ pub use timestamp::Call as TimestampCall; pub use balances::Call as BalancesCall; pub use runtime_primitives::{Permill, Perbill}; pub use support::StorageValue; +pub use staking::StakerStatus; /// Runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 33, - impl_version: 33, + spec_version: 53, + impl_version: 53, apis: RUNTIME_API_VERSIONS, }; @@ -101,22 +100,19 @@ impl indices::Trait for Runtime { impl balances::Trait for Runtime { type Balance = Balance; - type OnFreeBalanceZero = (((Staking, Contract), Democracy), Session); + type OnFreeBalanceZero = ((Staking, Contract), Session); type OnNewAccount = Indices; - type EnsureAccountLiquid = (Staking, Democracy); type Event = Event; -} - -impl fees::Trait for Runtime { - type Event = Event; - type TransferAsset = Balances; + type TransactionPayment = (); + type DustRemoval = (); + type TransferPayment = (); } impl consensus::Trait for Runtime { type Log = Log; - type SessionKey = SessionKey; + type SessionKey = AuthorityId; - // the aura module handles offline-reports internally + // The Aura module handles offline-reports internally // rather than using an explicit report system. type InherentOfflineReport = (); } @@ -126,24 +122,19 @@ impl timestamp::Trait for Runtime { type OnTimestampSet = Aura; } -/// Session key conversion. -pub struct SessionKeyConversion; -impl Convert for SessionKeyConversion { - fn convert(a: AccountId) -> SessionKey { - a.to_fixed_bytes().into() - } -} - impl session::Trait for Runtime { - type ConvertAccountIdToSessionKey = SessionKeyConversion; + type ConvertAccountIdToSessionKey = (); type OnSessionChange = (Staking, grandpa::SyncedAuthorities); type Event = Event; } impl staking::Trait for Runtime { type Currency = balances::Module; + type CurrencyToVote = CurrencyToVoteHandler; type OnRewardMinted = Treasury; type Event = Event; + type Slash = (); + type Reward = (); } impl democracy::Trait for Runtime { @@ -154,6 +145,8 @@ impl democracy::Trait for Runtime { impl council::Trait for Runtime { type Event = Event; + type BadPresentation = (); + type BadReaper = (); } impl council::voting::Trait for Runtime { @@ -171,14 +164,19 @@ impl treasury::Trait for Runtime { type ApproveOrigin = council_motions::EnsureMembers<_4>; type RejectOrigin = council_motions::EnsureMembers<_2>; type Event = Event; + type MintedForSpending = (); + type ProposalRejection = (); } impl contract::Trait for Runtime { + type Currency = balances::Module; type Call = Call; type Event = Event; type Gas = u64; type DetermineContractAddress = contract::SimpleAddressDeterminator; type ComputeDispatchFee = contract::DefaultDispatchFeeComputor; + type TrieIdGenerator = contract::TrieIdFromParentCounter; + type GasPayment = (); } impl sudo::Trait for Runtime { @@ -187,7 +185,7 @@ impl sudo::Trait for Runtime { } impl grandpa::Trait for Runtime { - type SessionKey = SessionKey; + type SessionKey = AuthorityId; type Log = Log; type Event = Event; } @@ -197,7 +195,7 @@ impl finality_tracker::Trait for Runtime { } construct_runtime!( - pub enum Runtime with Log(InternalLog: DigestItem) where + pub enum Runtime with Log(InternalLog: DigestItem) where Block = Block, NodeBlock = node_primitives::Block, UncheckedExtrinsic = UncheckedExtrinsic @@ -220,7 +218,6 @@ construct_runtime!( Treasury: treasury, Contract: contract::{Module, Call, Storage, Config, Event}, Sudo: sudo, - Fees: fees::{Module, Storage, Config, Event}, } ); @@ -239,7 +236,7 @@ pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive, Fees, AllModules>; +pub type Executive = executive::Executive, Balances, AllModules>; impl_runtime_apis! { impl client_api::Core for Runtime { @@ -247,16 +244,12 @@ impl_runtime_apis! { VERSION } - fn authorities() -> Vec { - Consensus::authorities() - } - fn execute_block(block: Block) { Executive::execute_block(block) } - fn initialise_block(header: &::Header) { - Executive::initialise_block(header) + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) } } @@ -271,8 +264,8 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } - fn finalise_block() -> ::Header { - Executive::finalise_block() + fn finalize_block() -> ::Header { + Executive::finalize_block() } fn inherent_extrinsics(data: InherentData) -> Vec<::Extrinsic> { @@ -294,6 +287,12 @@ impl_runtime_apis! { } } + impl offchain_primitives::OffchainWorkerApi for Runtime { + fn offchain_worker(number: NumberFor) { + Executive::offchain_worker(number) + } + } + impl fg_primitives::GrandpaApi for Runtime { fn grandpa_pending_change(digest: &DigestFor) -> Option>> @@ -323,7 +322,7 @@ impl_runtime_apis! { None } - fn grandpa_authorities() -> Vec<(SessionKey, u64)> { + fn grandpa_authorities() -> Vec<(AuthorityId, u64)> { Grandpa::grandpa_authorities() } } @@ -333,4 +332,10 @@ impl_runtime_apis! { Aura::slot_duration() } } + + impl consensus_authorities::AuthoritiesApi for Runtime { + fn authorities() -> Vec> { + Consensus::authorities() + } + } } diff --git a/node/runtime/wasm/Cargo.lock b/node/runtime/wasm/Cargo.lock index 5bb473efb18409c66a083a563df533be9fa110f0..d9bb349bc982371523580c3191fb99780420c153 100644 --- a/node/runtime/wasm/Cargo.lock +++ b/node/runtime/wasm/Cargo.lock @@ -1,5 +1,57 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aes-ctr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aes-soft" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aesni" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aio-limited" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayref" version = "0.3.5" @@ -7,49 +59,102 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arrayvec" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "asn1_der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "asn1_der_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base-x" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "base58" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bigint" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitmask" +version = "0.5.0" +source = "git+https://github.com/paritytech/bitmask#a84e147be602631617badd18b6b9af83391db4a9" + +[[package]] +name = "blake2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -69,7 +174,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-cipher-trait" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -81,6 +194,11 @@ dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bs58" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byte-tools" version = "0.2.0" @@ -93,26 +211,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.7" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -122,7 +245,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -130,7 +253,7 @@ name = "clear_on_drop" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -148,46 +271,105 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crossbeam" -version = "0.2.12" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "crossbeam-channel" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.6.2" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.6.1" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" -version = "0.6.2" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -209,18 +391,50 @@ dependencies = [ "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ctr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cuckoofilter" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "curve25519-dalek" -version = "1.0.3" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "data-encoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "digest" version = "0.6.2" @@ -237,21 +451,40 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ed25519-dalek" version = "1.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -259,7 +492,7 @@ dependencies = [ [[package]] name = "environmental" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -267,13 +500,28 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "fake-simd" @@ -285,10 +533,10 @@ name = "fixed-hash" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -311,6 +559,11 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -330,6 +583,15 @@ name = "futures" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "generic-array" version = "0.8.3" @@ -349,17 +611,26 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "heapsize" version = "0.4.2" @@ -368,9 +639,22 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hex-literal" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -378,127 +662,450 @@ dependencies = [ ] [[package]] -name = "hex-literal-impl" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "hex-literal-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac-drbg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "iovec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kvdb" +version = "0.1.0" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" +dependencies = [ + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", +] + +[[package]] +name = "lazy_static" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libp2p" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-core-derive 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-dns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-floodsub 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-kad 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-mdns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-mplex 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-noise 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-plaintext 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ratelimit 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-secio 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-tcp 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-uds 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-yamux 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-core" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-core-derive" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-dns" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-floodsub" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-identify" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-kad" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mdns" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mplex" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "hmac" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p-noise" +version = "0.3.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "hmac-drbg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p-ping" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "httparse" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p-plaintext" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "impl-codec" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p-ratelimit" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "impl-serde" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p-secio" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "integer-sqrt" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "iovec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p-tcp" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "itoa" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "libp2p-uds" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "kvdb" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" +name = "libp2p-yamux" +version = "0.5.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.48" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libsecp256k1" version = "0.2.2" @@ -507,7 +1114,7 @@ dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -526,7 +1133,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -534,6 +1141,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memoffset" version = "0.2.1" @@ -541,10 +1153,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memory-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -555,14 +1167,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "merlin" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -575,11 +1186,11 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -591,7 +1202,7 @@ dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -600,7 +1211,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -615,13 +1226,27 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "multistream-select" +version = "0.3.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -629,10 +1254,10 @@ dependencies = [ name = "node-primitives" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -642,13 +1267,13 @@ dependencies = [ name = "node-runtime" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 0.1.0", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -659,7 +1284,6 @@ dependencies = [ "srml-council 0.1.0", "srml-democracy 0.1.0", "srml-executive 0.1.0", - "srml-fees 0.1.0", "srml-finality-tracker 0.1.0", "srml-grandpa 0.1.0", "srml-indices 0.1.0", @@ -670,10 +1294,11 @@ dependencies = [ "srml-system 0.1.0", "srml-timestamp 0.1.0", "srml-treasury 0.1.0", - "srml-upgrade-key 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-authorities 0.1.0", "substrate-keyring 0.1.0", + "substrate-offchain-primitives 0.1.0", "substrate-primitives 0.1.0", ] @@ -689,6 +1314,11 @@ name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "nohash-hasher" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num-integer" version = "0.1.39" @@ -704,16 +1334,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "once_cell" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "opaque-debug" @@ -722,28 +1355,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.16" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.40" +version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "owning_ref" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" version = "0.4.0" @@ -759,12 +1401,12 @@ source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7 [[package]] name = "parity-codec" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -773,9 +1415,36 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multiaddr" +version = "0.2.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multihash" +version = "0.1.0" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -783,7 +1452,16 @@ name = "parity-wasm" version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -804,15 +1482,26 @@ dependencies = [ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -821,10 +1510,10 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -843,9 +1532,19 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -890,9 +1589,9 @@ name = "proc-macro-hack" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -902,90 +1601,116 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "protobuf" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pwasm-utils" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-error" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -993,7 +1718,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1001,46 +1726,119 @@ name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_pcg" -version = "0.1.1" +name = "rdrand" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_xorshift" -version = "0.1.0" +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "redox_syscall" -version = "0.1.43" +name = "regex-syntax" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "ring" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1056,6 +1854,16 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rw-stream-sink" +version = "0.1.1" +source = "git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20#e8e6ccec7409aa19939230d6720035e3ed28dfd6" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ryu" version = "0.2.7" @@ -1072,15 +1880,33 @@ dependencies = [ [[package]] name = "schnorrkel" version = "0.0.0" +source = "git+https://github.com/w3f/schnorrkel#3179838da9dd4896c12bb910e7c42477a3250641" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schnorrkel" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1090,6 +1916,16 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "secp256k1" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -1105,27 +1941,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.81" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.81" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.33" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1170,7 +2006,7 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1194,27 +2030,41 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "slog-scope" -version = "4.0.1" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "snow" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1228,19 +2078,19 @@ version = "0.1.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sr-io" version = "0.1.0" dependencies = [ - "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1256,9 +2106,9 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1268,7 +2118,7 @@ dependencies = [ name = "sr-sandbox" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1287,9 +2137,9 @@ name = "sr-version" version = "0.1.0" dependencies = [ "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", ] @@ -1298,9 +2148,9 @@ dependencies = [ name = "srml-aura" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-session 0.1.0", @@ -1315,10 +2165,10 @@ dependencies = [ name = "srml-balances" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", @@ -1330,10 +2180,10 @@ dependencies = [ name = "srml-consensus" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", @@ -1346,17 +2196,15 @@ dependencies = [ name = "srml-contract" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-sandbox 0.1.0", "sr-std 0.1.0", - "srml-balances 0.1.0", - "srml-fees 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "srml-timestamp 0.1.0", @@ -1367,10 +2215,10 @@ dependencies = [ name = "srml-council" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1384,11 +2232,11 @@ dependencies = [ name = "srml-democracy" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1400,43 +2248,25 @@ dependencies = [ name = "srml-executive" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", - "sr-primitives 0.1.0", - "sr-std 0.1.0", - "srml-support 0.1.0", - "srml-system 0.1.0", -] - -[[package]] -name = "srml-fees" -version = "0.1.0" -dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] name = "srml-finality-tracker" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-session 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "substrate-inherents 0.1.0", @@ -1446,11 +2276,12 @@ dependencies = [ name = "srml-grandpa" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", + "srml-consensus 0.1.0", "srml-finality-tracker 0.1.0", "srml-session 0.1.0", "srml-support 0.1.0", @@ -1463,11 +2294,11 @@ dependencies = [ name = "srml-indices" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1481,9 +2312,9 @@ dependencies = [ name = "srml-metadata" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", ] @@ -1492,11 +2323,11 @@ dependencies = [ name = "srml-session" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", @@ -1509,10 +2340,11 @@ dependencies = [ name = "srml-staking" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", @@ -1526,10 +2358,10 @@ dependencies = [ name = "srml-sudo" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", @@ -1541,12 +2373,13 @@ dependencies = [ name = "srml-support" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1559,11 +2392,11 @@ dependencies = [ name = "srml-support-procedural" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "srml-support-procedural-tools 0.1.0", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1571,30 +2404,30 @@ name = "srml-support-procedural-tools" version = "0.1.0" dependencies = [ "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "srml-support-procedural-tools-derive 0.1.0", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools-derive" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-system" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1606,12 +2439,11 @@ dependencies = [ name = "srml-timestamp" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-consensus 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "substrate-inherents 0.1.0", @@ -1621,10 +2453,10 @@ dependencies = [ name = "srml-treasury" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-balances 0.1.0", @@ -1632,19 +2464,6 @@ dependencies = [ "srml-system 0.1.0", ] -[[package]] -name = "srml-upgrade-key" -version = "0.1.0" -dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 0.1.0", - "sr-std 0.1.0", - "srml-consensus 0.1.0", - "srml-support 0.1.0", - "srml-system 0.1.0", -] - [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -1655,6 +2474,90 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "static_slice" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stdweb" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-macros 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stream-cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strum" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strum_macros" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-bip39" +version = "0.2.0" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" +dependencies = [ + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-client" version = "0.1.0" @@ -1662,12 +2565,12 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "sr-primitives 0.1.0", @@ -1687,39 +2590,55 @@ dependencies = [ name = "substrate-consensus-aura-primitives" version = "0.1.0" dependencies = [ + "sr-primitives 0.1.0", + "substrate-client 0.1.0", +] + +[[package]] +name = "substrate-consensus-authorities" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", + "srml-support 0.1.0", "substrate-client 0.1.0", + "substrate-primitives 0.1.0", ] [[package]] name = "substrate-consensus-common" version = "0.1.0" dependencies = [ - "crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", - "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-executor" version = "0.1.0" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", "substrate-panic-handler 0.1.0", @@ -1735,7 +2654,7 @@ dependencies = [ name = "substrate-finality-grandpa-primitives" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "substrate-client 0.1.0", @@ -1746,7 +2665,7 @@ dependencies = [ name = "substrate-inherents" version = "0.1.0" dependencies = [ - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1756,16 +2675,26 @@ dependencies = [ name = "substrate-keyring" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-offchain-primitives" +version = "0.1.0" +dependencies = [ + "sr-primitives 0.1.0", + "substrate-client 0.1.0", +] + [[package]] name = "substrate-panic-handler" version = "0.1.0" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1775,21 +2704,25 @@ version = "0.1.0" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1799,41 +2732,41 @@ dependencies = [ name = "substrate-serializer" version = "0.1.0" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-state-machine" version = "0.1.0" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-telemetry" version = "0.3.1" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1841,13 +2774,18 @@ dependencies = [ name = "substrate-trie" version = "0.4.0" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "subtle" version = "2.0.0" @@ -1855,11 +2793,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.26" +version = "0.15.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1873,19 +2822,33 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "time" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tiny-keccak" version = "1.4.2" @@ -1894,26 +2857,38 @@ dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tk-listen" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1921,101 +2896,125 @@ name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-dns-unofficial" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-tcp" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2023,30 +3022,30 @@ name = "tokio-udp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2054,26 +3053,36 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.11.0" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "twofish" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2081,7 +3090,7 @@ name = "twox-hash" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2089,12 +3098,17 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2110,7 +3124,15 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.7" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-segmentation" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2119,11 +3141,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "unreachable" -version = "1.0.0" +name = "unsigned-varint" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2141,6 +3164,11 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" version = "0.2.6" @@ -2156,7 +3184,7 @@ name = "wasmi" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2195,16 +3223,16 @@ name = "ws" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2217,59 +3245,124 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "x25519-dalek" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "yamux" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zeroize" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] +"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f10b352bc3fc08ae24dc5d2d3ddcac153678533986122dc283d747b12071000" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9893d63fc3b1c44231e667da6836a33f27d8b6b3bdc82f83da5dfd579d1b6528" +"checksum asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7f92edafad155aff997fa5b727c6429b91e996b5a5d62a2b0adbae1306b5fe" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d55aa264e822dbafa12db4d54767aff17c6ba55ea2d8559b3e17392c7d000e5d" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" +"checksum bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebecac13b3c745150d7b6c3ea7572d372f09d627c2077e893bf26c5c7f70d282" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)" = "" +"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" -"checksum crossbeam-channel 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8d4f5844607ce8da3fff431e7dba56cda8bfcc570aa50bee36adba8a32b8cad7" -"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3" -"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" -"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" "checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" -"checksum curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dae47cc3529cdab597dbc8b606e565707209b506e55848f3c15679214a56c956" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" +"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" +"checksum curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f8a6fc0376eb52dc18af94915cc04dfdf8353746c0e8c550ae683a0815e5c1" +"checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" "checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" "checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" -"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" -"checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" +"checksum environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c7464757b80de8930c91c9afe77ddce501826bf9d134a87db2c67d9dc177e2c" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" -"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" -"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hash-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07463834729d0ce8d475e7dd6d302e407093ad9a9c02d77eb07fb74b5373829d" +"checksum hash256-std-hasher 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1224388a21c88a80ae7087a2a245ca6d80acc97a9186b75789fb3eeefd0609af" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" "checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" +"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" "checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" @@ -2281,42 +3374,67 @@ dependencies = [ "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libp2p 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-core 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-core-derive 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-dns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-floodsub 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-identify 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-kad 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-mdns 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-mplex 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-noise 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-ping 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-plaintext 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-ratelimit 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-secio 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-tcp 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-uds 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum libp2p-yamux 0.5.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" +"checksum memory-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd87d4d64f7b86d8804bbb419f8ecb187cb8f40a50e91c72848075c604ba88d" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9e97b439f6d38cbe2a4a4aa93f6770c5305f62761b78b1851406c09c87ee2a" +"checksum merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "83c2dda19c01176e8e7148f7bdb88bbdf215a8db0641f89fc40e4b81736aeda5" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum multistream-select 0.3.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d138afcce92d219ccb6eb53d9b1e8a96ac0d633cfd3c53cd9856d96d1741bb8" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum once_cell 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d7ce3535d54560c937c1652ba4a0da66bfc63e0f8e07bed127483afb6e5ee925" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" -"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" -"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" +"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" +"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" +"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67a4d27831e31e27f1454d6e3d3bb34bcac6bf7ad7032eed0ad0070dc8cf55c1" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" "checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" +"checksum parity-multiaddr 0.2.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" +"checksum parity-multihash 0.1.0 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" +"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" "checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" @@ -2324,76 +3442,110 @@ dependencies = [ "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" -"checksum pwasm-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e9135bed7b452e20dbb395a2d519abaf0c46d60e7ecc02daeeab447d29bada1" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" -"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum protobuf 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24d5d73d2b88fddb8b8141f2730d950d88772c940ac4f8f3e93230b9a99d92df" +"checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" +"checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" -"checksum ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "148fc853f6d85f53f5f315d46701eaacc565cdfb3cb1959730c96e81e7e49999" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum rw-stream-sink 0.1.1 (git+https://github.com/tomaka/libp2p-rs?branch=substrate-tmp-2019-03-20)" = "" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe554f318830b48e5da8ab1ccb1ffd02b79228364dac7766b7cd1ec461ca5116" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" +"checksum schnorrkel 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a700659388785588c75b197cecda0f23c7112a9281ef703e8ffc651061ce014c" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum secp256k1 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4070f3906e65249228094cf97b04a90799fba04468190bbbcfa812309cf86e32" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c91eb5b0190ae87b4e2e39cbba6e3bed3ac6186935fe265f0426156c4c49961b" -"checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" -"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" -"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" "checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -"checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5a64f02fd208ef15bd2d1a65861df4707e416151e1272d02c8faafad1c138100" "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362" +"checksum stdweb 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a3edad410e603184d656e2abded5fd4d3d6e93d5763d21130dbaf99795db74eb" +"checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" +"checksum stdweb-internal-macros 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1635afd059cbfac7d5b1274f0c44cec110c1e013c48e8bbc22e07e52696cf887" +"checksum stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a2f4a2eb556337b2d1a302630bbddf989ae383c70393e89b48152b9896cbda" +"checksum stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8861bc80f649f5b4c9bd38b696ae9af74499d479dbfb327f0607de6b326a36bc" +"checksum strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1810e25f576e7ffce1ff5243b37066da5ded0310b3274c20baaeccb1145b2806" +"checksum strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "572a2f4e53dd4c3483fd79e5cc10ddd773a3acb1169bbfe8762365e107110579" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1415431cb2398d84da64173f8473c792808314427d4a6f2f3ea85ae67239fe3" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" -"checksum tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "a7817d4c98cc5be21360b3b37d6036fe9b7aefa5b7a201b7b16ff33423822f7d" +"checksum tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5462b0f968c0457efe38fcd2df7e487096b992419e4f5337b06775a614bbda4b" +"checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" -"checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75" -"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" -"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" -"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912" -"checksum tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "56c5556262383032878afad66943926a1d1f0967f17e94bd7764ceceb3b70e7f" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" +"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99ce87382f6c1a24b513a72c048b2c8efe66cb5161c9061d00bee510f08dc168" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" -"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" +"checksum trie-db 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f23230c31251bdbdba89cd9caa0cbe2aa9e4aa5f92a80e6eb6296bb290e9146" +"checksum trie-root 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e45632ecaf2b8b4a40b5208383cd659b4e66f58ccd40086467a4614b45781430" +"checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c64cdf40b4a9645534a943668681bcb219faf51874d4b65d2e0abda1b10a2ab" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" @@ -2404,3 +3556,6 @@ dependencies = [ "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4aca1ba6bec2719576bd20dfe5b24d9359552e616d10bff257e50cd85f745d17" +"checksum yamux 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "302defd1bed8a9a6d43b82f0e5a50510dfdfbbd02c270c93ff9d6f3f5e2dea89" +"checksum zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddfeb6eee2fb3b262ef6e0898a52b7563bb8e0d5955a313b3cf2f808246ea14" diff --git a/node/runtime/wasm/src/lib.rs b/node/runtime/wasm/src/lib.rs index 7364f0a4db0c44b381dff03a094f2118e4a87511..a87b3f7c79dbd94a34a14537822b8c94fc67fab7 100644 --- a/node/runtime/wasm/src/lib.rs +++ b/node/runtime/wasm/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm index 7c6e43a51622bdd2c89c0dc1f1c19f0efae79cd4..b27ac195d1309bcaf89c3d86f8bdf2fdbf841fe9 100644 Binary files a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm and b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm differ diff --git a/node/src/main.rs b/node/src/main.rs index 2df55bb852fdafa8b7d8236abcef6ba4fcf1f738..5ff0d7ff3b0e68fae90eca12154bd1409d866d80 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/scripts/gitlab/check_runtime.sh b/scripts/gitlab/check_runtime.sh index 61068e7eb8885d18ebaafd4511be1efcb48d45d0..fe8cbf450fc5964d0cfba26c6321366285471c4b 100755 --- a/scripts/gitlab/check_runtime.sh +++ b/scripts/gitlab/check_runtime.sh @@ -18,7 +18,7 @@ VERSIONS_FILE="node/runtime/src/lib.rs" github_label () { echo - echo "# run github-api job for labelling it ${1}" + echo "# run github-api job for labeling it ${1}" curl -sS -X POST \ -F "token=${CI_JOB_TOKEN}" \ -F "ref=master" \ diff --git a/scripts/init.sh b/scripts/init.sh index 5dde6d42418b58844640bd41214948ef329065aa..cf5ecf97926fea7a5e8fd2a91df96853f90e8ee7 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -2,7 +2,7 @@ set -e -echo "*** Initialising WASM build environment" +echo "*** Initializing WASM build environment" if [ -z $CI_PROJECT_NAME ] ; then rustup update nightly diff --git a/scripts/kubernetes/Chart.yaml b/scripts/kubernetes/Chart.yaml index 4dd133c860bb12f93af80182620b79a23877f565..8e000ae09f1c1ff77028ad561b752b407d06e993 100644 --- a/scripts/kubernetes/Chart.yaml +++ b/scripts/kubernetes/Chart.yaml @@ -1,5 +1,5 @@ name: substrate -version: 0.1 +version: 0.2 appVersion: 0.9.1 description: "Substrate: The platform for blockchain innovators" home: https://substrate.network/ diff --git a/scripts/kubernetes/templates/poddisruptionbudget.yaml b/scripts/kubernetes/templates/poddisruptionbudget.yaml index af40522842c2359b4bd69571a746c3bffece71d4..56958b1fbafd963896eeab25059380bb4e9547e2 100644 --- a/scripts/kubernetes/templates/poddisruptionbudget.yaml +++ b/scripts/kubernetes/templates/poddisruptionbudget.yaml @@ -1,10 +1,10 @@ apiVersion: policy/v1beta1 kind: PodDisruptionBudget metadata: - name: substrate + name: {{ .Values.GitlabEnvSlug | default .Values.app }} spec: selector: matchLabels: - app: substrate + app: {{ .Values.GitlabEnvSlug | default .Values.app }} maxUnavailable: 1 diff --git a/scripts/kubernetes/templates/secrets.yaml b/scripts/kubernetes/templates/secrets.yaml index e00738448258a59bdfd5612f3cb1eb2cfbaa58a6..97e73ae7ff03805c1bde9d7deb894eb94948f28b 100644 --- a/scripts/kubernetes/templates/secrets.yaml +++ b/scripts/kubernetes/templates/secrets.yaml @@ -2,9 +2,9 @@ apiVersion: v1 kind: Secret metadata: - name: substrate-secrets + name: {{ .Values.app }}-secrets labels: - app: substrate + app: {{ .Values.GitlabEnvSlug | default .Values.app }} type: Opaque data: secrets: {{ .Values.validator.keys | default "" }} diff --git a/scripts/kubernetes/templates/service.yaml b/scripts/kubernetes/templates/service.yaml index 27baa59dc4e0541f2c5f28e5777027136bb853a3..01ba9d5a567c57045b585aa7e1fa894d404cbf90 100644 --- a/scripts/kubernetes/templates/service.yaml +++ b/scripts/kubernetes/templates/service.yaml @@ -5,9 +5,7 @@ apiVersion: v1 kind: Service metadata: - name: substrate-rpc - labels: - app: substrate + name: {{ .Values.app }}-rpc spec: ports: - port: 9933 @@ -15,15 +13,16 @@ spec: - port: 9944 name: websocket-rpc selector: - app: substrate + app: {{ .Values.GitlabEnvSlug | default .Values.app }} sessionAffinity: None type: ClusterIP clusterIP: None --- +{{- if .Values.listen_node_port }} apiVersion: v1 kind: Service metadata: - name: substrate + name: {{ .Values.app }} spec: ports: - port: 30333 @@ -31,9 +30,25 @@ spec: nodePort: 30333 protocol: TCP selector: - app: substrate + app: {{ .Values.GitlabEnvSlug | default .Values.app }} sessionAffinity: None type: NodePort # don't route exteral traffic to non-local pods externalTrafficPolicy: Local - +{{- else if .Values.validator.keys }} +{{- $root := . -}} +{{- range until (int .Values.nodes.replicas) }} +--- +kind: Service +apiVersion: v1 +metadata: + name: {{ $root.Values.app }}-{{ . }} +spec: + selector: + statefulset.kubernetes.io/pod-name: {{ $root.Values.app }}-{{ . }} + ports: + - port: 30333 + targetPort: 30333 + protocol: TCP +{{- end }} +{{- end }} diff --git a/scripts/kubernetes/templates/serviceaccount.yaml b/scripts/kubernetes/templates/serviceaccount.yaml index 5a0018a121b9809fe4222e1ef970eb39d024ba8f..53d016bffedf988fad2fcd71c316f565bee683a7 100644 --- a/scripts/kubernetes/templates/serviceaccount.yaml +++ b/scripts/kubernetes/templates/serviceaccount.yaml @@ -5,6 +5,6 @@ apiVersion: v1 kind: ServiceAccount metadata: labels: - app: substrate + app: {{ .Values.GitlabEnvSlug | default .Values.app }} name: {{ .Values.rbac.name }} {{- end }} diff --git a/scripts/kubernetes/templates/statefulset.yaml b/scripts/kubernetes/templates/statefulset.yaml index ec491f63494a173cac3f6b81326db2d620fd12a5..0f34b3507a1d17e49334bca86792ac2964a6a618 100644 --- a/scripts/kubernetes/templates/statefulset.yaml +++ b/scripts/kubernetes/templates/statefulset.yaml @@ -3,12 +3,12 @@ apiVersion: apps/v1 kind: StatefulSet metadata: - name: substrate + name: {{ .Values.app }} spec: selector: matchLabels: - app: substrate - serviceName: substrate + app: {{ .Values.GitlabEnvSlug | default .Values.app }} + serviceName: {{ .Values.app }} replicas: {{ .Values.nodes.replicas }} updateStrategy: type: RollingUpdate @@ -16,7 +16,7 @@ spec: template: metadata: labels: - app: substrate + app: {{ .Values.GitlabEnvSlug | default .Values.app }} spec: {{- if .Values.rbac.enable }} serviceAccountName: {{ .Values.rbac.name }} @@ -32,6 +32,7 @@ spec: operator: In values: - substrate + {{- if .Values.listen_node_port }} podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: @@ -39,14 +40,15 @@ spec: - key: "app" operator: In values: - - substrate + - {{ .Values.app }} topologyKey: "kubernetes.io/hostname" + {{- end }} terminationGracePeriodSeconds: 300 {{- if .Values.validator.keys }} volumes: - - name: substrate-validator-secrets + - name: {{ .Values.app }}-validator-secrets secret: - secretName: substrate-secrets + secretName: {{ .Values.app }}-secrets initContainers: - name: prepare-secrets image: busybox @@ -54,7 +56,9 @@ spec: args: - -c - sed -n -r "s/^${POD_NAME}-key ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/key; - sed -n -r "s/^${POD_NAME}-node-key ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/node-key + sed -n -r "s/^${POD_NAME}-node-key ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/node-key; + sed -n -r "s/^${POD_NAME}-name ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/name; + test -s {{ .Values.image.basepath }}/name || echo "${POD_NAME}" > {{ .Values.image.basepath }}/name env: # from (workaround for hostname) # https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/ @@ -63,14 +67,14 @@ spec: fieldRef: fieldPath: metadata.name volumeMounts: - - name: substrate-validator-secrets + - name: {{ .Values.app }}-validator-secrets readOnly: true mountPath: "/etc/validator" - - name: substratedir + - name: {{ .Values.app }}dir mountPath: {{ .Values.image.basepath }} {{- end }} containers: - - name: substrate + - name: {{ .Values.app }} imagePullPolicy: "{{ .Values.image.pullPolicy }}" image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" {{- if .Values.resources }} @@ -91,13 +95,13 @@ spec: - -c - exec /usr/local/bin/substrate --base-path {{ .Values.image.basepath }} - --name $(POD_NAME) - {{- if .Values.validator.enable }} - --validator - {{- end }} {{- if .Values.validator.keys }} + --validator + --name $(cat {{ .Values.image.basepath }}/name) --key $(cat {{ .Values.image.basepath }}/key) --node-key $(cat {{ .Values.image.basepath }}/node-key) + {{- else }} + --name $(POD_NAME) {{- end }} {{- range .Values.nodes.args }} {{ . }} {{- end }} env: @@ -106,7 +110,7 @@ spec: fieldRef: fieldPath: metadata.name volumeMounts: - - name: substratedir + - name: {{ .Values.app }}dir mountPath: {{ .Values.image.basepath }} readinessProbe: httpGet: @@ -125,7 +129,7 @@ spec: fsGroup: 1000 volumeClaimTemplates: - metadata: - name: substratedir + name: {{ .Values.app }}dir spec: accessModes: [ "ReadWriteOnce" ] storageClassName: ssd diff --git a/scripts/kubernetes/values.yaml b/scripts/kubernetes/values.yaml index 213ccaebe476e0f749cdb85e36c6f4cfa8fce0eb..89a6445e00a2f59c6290ef8e4eafdc9fdd925832 100644 --- a/scripts/kubernetes/values.yaml +++ b/scripts/kubernetes/values.yaml @@ -12,6 +12,10 @@ rbac: name: substrate +# name of the statefulset +app: substrate +listen_node_port: true + nodes: replicas: 2 args: @@ -27,22 +31,24 @@ nodes: - --ws-external # - --log # - sub-libp2p=trace - -validator: - enable: True - # adds --validator commandline option + +validator: {} + # providing 'keys' string via --set commandline parameter will run the nodes + # in validator mode (--validator). # - # key and node-key can be given in a base64 encoded keyfile string (at + # name, key and node-key can be given in a base64 encoded keyfile string (at # validator.keys) which has the following format: # + # substrate-0-name # substrate-0-key # substrate-0-node-key + # substrate-1-name # substrate-1-key # substrate-1-node-key # - # pod names are canonical. changing these or providing different amount of - # keys than the replicas count will lead to behaviour noone ever has + # pod names are canonical. changing these or providing different amount of + # keys than the replicas count will lead to behavior noone ever has # experienced before. diff --git a/srml/assets/Cargo.toml b/srml/assets/Cargo.toml index 7dfc8fd04d02a7cd0de0ff55d1e2de1876e43e0c..129f884bd9cad954d7bc9b526debbda177227ead 100644 --- a/srml/assets/Cargo.toml +++ b/srml/assets/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false } -# Needed for various traits. In our case, `OnFinalise`. +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } +# Needed for various traits. In our case, `OnFinalize`. primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } # Needed for type-safe access to storage DB. srml-support = { path = "../support", default-features = false } @@ -23,7 +23,7 @@ runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] std = [ - "serde/std", + "serde", "parity-codec/std", "primitives/std", "srml-support/std", diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index ef01bb561ff1deeb9d42594e7c8143a9a626c4bf..a10456a46900d12944b736e605312a4ca6556cc0 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -284,7 +284,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; diff --git a/srml/aura/Cargo.toml b/srml/aura/Cargo.toml index 49c371cd45446c342ab049e04166068088d81891..9d1eda38c055fe18c1d3d67496bc4b654f8513bf 100644 --- a/srml/aura/Cargo.toml +++ b/srml/aura/Cargo.toml @@ -6,8 +6,9 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } -serde = { version = "1.0", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +parity-codec-derive = { version = "3.1", default-features = false } +serde = { version = "1.0", optional = true } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } @@ -27,7 +28,7 @@ consensus = { package = "srml-consensus", path = "../consensus" } [features] default = ["std"] std = [ - "serde/std", + "serde", "parity-codec/std", "rstd/std", "srml-support/std", diff --git a/srml/aura/src/lib.rs b/srml/aura/src/lib.rs index 26cfaf4299cd38628dfd7d74307cbcf0cfc1ddcc..344ea64869656aa79da8e696da59fef704954760 100644 --- a/srml/aura/src/lib.rs +++ b/srml/aura/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -165,7 +165,7 @@ impl Module { pub fn slot_duration() -> u64 { // we double the minimum block-period so each author can always propose within // the majority of their slot. - >::block_period().as_().saturating_mul(2) + >::minimum_period().as_().saturating_mul(2) } fn on_timestamp_set(now: T::Moment, slot_duration: T::Moment) { diff --git a/srml/aura/src/mock.rs b/srml/aura/src/mock.rs index 04b5d35efe1e2a01f6752a5ad5c29cde03e3b6d8..e72e25ef94080f84f1aa2d883695da56bd459a2b 100644 --- a/srml/aura/src/mock.rs +++ b/srml/aura/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -46,7 +46,7 @@ impl system::Trait for Test { type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; @@ -68,7 +68,7 @@ pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities{ - period: 1, + minimum_period: 1, }.build_storage().unwrap().0); t.into() } diff --git a/srml/aura/src/tests.rs b/srml/aura/src/tests.rs index 91f02259250a367968d6957766d8a81d0bb312f9..e74c7dace2ff3fd6179f755e05add387f1bc7f92 100644 --- a/srml/aura/src/tests.rs +++ b/srml/aura/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -73,18 +73,18 @@ fn aura_reports_offline() { } with_externalities(&mut new_test_ext(vec![0, 1, 2, 3]), || { - System::initialise(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default()); let slot_duration = Aura::slot_duration(); Aura::on_timestamp_set::(5 * slot_duration, slot_duration); - let header = System::finalise(); + let header = System::finalize(); // no slashing when last step was 0. assert_eq!(SLASH_COUNTS.lock().as_slice(), &[0, 0, 0, 0]); - System::initialise(&2, &header.hash(), &Default::default()); + System::initialize(&2, &header.hash(), &Default::default()); Aura::on_timestamp_set::(8 * slot_duration, slot_duration); - let _header = System::finalise(); + let _header = System::finalize(); // Steps 6 and 7 were skipped. assert_eq!(SLASH_COUNTS.lock().as_slice(), &[0, 0, 1, 1]); diff --git a/srml/balances/Cargo.toml b/srml/balances/Cargo.toml index 1cb75c94ed1092831f62698fa854c21a311924ff..43759643ddfad3b3b14efeace9967d6bf0b7c5dc 100644 --- a/srml/balances/Cargo.toml +++ b/srml/balances/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-keyring = { path = "../../core/keyring", optional = true } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } @@ -22,7 +22,7 @@ substrate-primitives = { path = "../../core/primitives" } [features] default = ["std"] std = [ - "serde/std", + "serde", "safe-mix/std", "substrate-keyring", "parity-codec/std", diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index f5168240a7b3e9a6104fd63d7fd731859177fe99..fa34bc43a09dee3ce6e586133df4c1bd985fc766 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,37 +14,187 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Balances: Handles setting and retrieval of free balance, -//! retrieving total balance, reserve and unreserve balance, -//! repatriating a reserved balance to a beneficiary account that exists, -//! transfering a balance between accounts (when not reserved), -//! slashing an account balance, account removal, rewards, -//! lookup of an index to reclaim an account (when not balance not reserved), -//! increasing total stake. +//! # Balances Module +//! +//! The balances module provides functionality for handling accounts and balances. To use the balances module, you need +//! to implement the [balances Trait](https://crates.parity.io/srml_balances/trait.Trait.html). Supported dispatchables +//! are documented in the [`Call` enum](https://crates.parity.io/srml_balances/enum.Call.html). +//! +//! ## Overview +//! +//! The balances module provides functions for: +//! +//! - Getting and setting free balances +//! - Retrieving total, reserved and unreserved balances +//! - Repatriating a reserved balance to a beneficiary account that exists +//! - Transferring a balance between accounts (when not reserved) +//! - Slashing an account balance +//! - Account creation and removal +//! - Lookup of an index to reclaim an account +//! - Managing total issuance +//! - Setting and managing locks +//! +//! ### Terminology +//! +//! - **Existential Deposit:** The minimum balance required to create or keep an account open. This prevents +//! "dust accounts" from filling storage. +//! - **Total Issuance:** The total amount of units in existence in a system. +//! - **Reaping an account:** The act of removing an account by resetting its nonce. Happens after its balance is set +//! to zero. +//! - **Free Balance:** The portion of a balance that is not reserved. The free balance is the only balance that matters +//! for most operations. When this balance falls below the existential deposit, most functionality of the account is +//! removed. When both it and the reserved balance are deleted, then the account is said to be dead. +//! - **Reserved Balance:** Reserved balance still belongs to the account holder, but is suspended. Reserved balance +//! can still be slashed, but only after all of free balance has been slashed. If the reserved balance falls below the +//! existential deposit then it and any related functionality will be deleted. When both it and the free balance are +//! deleted, then the account is said to be dead. +//! - **Imbalance:** A condition when some funds were created or deducted without equal and opposite accounting. +//! Functions that result in an imbalance will return an object of the `Imbalance` trait that must be handled. +//! - **Lock:** A freeze on a specified amount of an account's free balance until a specified block number. Multiple +//! locks always operate over the same funds, so they "overlay" rather than "stack". +//! - **Vesting:** Similar to a lock, this is another, but independent, liquidity restriction that reduces linearly +//! over time. +//! +//! ### Implementations +//! +//! The balances module provides implementations for the following traits. If these traits provide the functionality +//! that you need, then you can avoid coupling with the balances module. +//! +//! - [`Currency`](https://crates.parity.io/srml_support/traits/trait.Currency.html): Functions for dealing with a +//! fungible assets system. +//! - [`ReservableCurrency`](https://crates.parity.io/srml_support/traits/trait.ReservableCurrency.html): +//! Functions for dealing with assets that can be reserved from an account. +//! - [`LockableCurrency`](https://crates.parity.io/srml_support/traits/trait.LockableCurrency.html): Functions for +//! dealing with accounts that allow liquidity restrictions. +//! - [`Imbalance`](https://crates.parity.io/srml_support/traits/trait.Imbalance.html): Functions for handling +//! imbalances between total issuance in the system and account balances. Must be used when a function +//! creates new funds (e.g. a reward) or destroys some funds (e.g. a system fee). +//! - [`MakePayment`](https://crates.parity.io/srml_support/traits/trait.MakePayment.html): Simple trait designed +//! for hooking into a transaction payment. +//! - [`IsDeadAccount`](https://crates.parity.io/srml_system/trait.IsDeadAccount.html): Determiner to say whether a +//! given account is unused. +//! +//! Example of using the `Currency` trait from the treasury module: +//! +//! ```rust,ignore +//! pub trait Trait: system::Trait { +//! /// The staking balance. +//! type Currency: Currency; +//! } +//! ``` +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! The `Call` enum is documented [here](https://crates.parity.io/srml_balances/enum.Call.html). +//! +//! - `transfer` - Transfer some liquid free balance to another account. +//! - `set_balance` - Set the balances of a given account. The origin of this call must be root. +//! +//! ### Public Functions +//! +//! See the [module](https://crates.parity.io/srml_balances/struct.Module.html) for details on publicly available +//! functions. +//! +//! ## Usage +//! +//! The following examples show how to use the balances module in your custom module. +//! +//! ### Import and Balance Transfer +//! +//! Import the `balances` module and derive your module configuration trait with the balances trait. You can now call +//! functions from the module. +//! +//! ```rust,ignore +//! use support::{decl_module, dispatch::Result}; +//! use system::ensure_signed; +//! +//! pub trait Trait: balances::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! fn transfer_proxy(origin, to: T::AccountId, value: T::Balance) -> Result { +//! let sender = ensure_signed(origin)?; +//! >::make_transfer(&sender, &to, value)?; +//! +//! Ok(()) +//! } +//! } +//! } +//! ``` +//! +//! ### Real Use Example +//! +//! Use in the `contract` module (gas.rs): +//! +//! ```rust,ignore +//! pub fn refund_unused_gas( +//! transactor: &T::AccountId, +//! gas_meter: GasMeter, +//! imbalance: balances::NegativeImbalance, +//! ) { +//! let gas_spent = gas_meter.spent(); +//! let gas_left = gas_meter.gas_left(); +//! +//! // Increase total spent gas. +//! >::mutate(|block_gas_spent| *block_gas_spent += gas_spent); +//! +//! let refund = >::as_(gas_left) * gas_meter.gas_price; +//! // Refund gas using balances module +//! let refund_imbalance = >::deposit_creating(transactor, refund); +//! // Handle imbalance +//! if let Ok(imbalance) = imbalance.offset(refund_imbalance) { +//! T::GasPayment::on_unbalanced(imbalance); +//! } +//! } +//! ``` +//! +//! ## Genesis config +//! +//! The following storage items depend on the genesis config: +//! +//! - `TotalIssuance` +//! - `ExistentialDeposit` +//! - `TransferFee` +//! - `CreationFee` +//! - `Vesting` +//! - `FreeBalance` +//! - `TransactionBaseFee` +//! - `TransactionByteFee` +//! +//! ## Related Modules +//! +//! The balances module depends on the [`system`](https://crates.parity.io/srml_system/index.html) and +//! [`srml_support`](https://crates.parity.io/srml_support/index.html) modules as well as Substrate Core +//! libraries and the Rust standard library. #![cfg_attr(not(feature = "std"), no_std)] use rstd::prelude::*; use rstd::{cmp, result}; use parity_codec::{Codec, Encode, Decode}; -use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module, ensure}; +use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module}; use srml_support::traits::{ - UpdateBalanceOutcome, Currency, EnsureAccountLiquid, OnFreeBalanceZero, TransferAsset, WithdrawReason, ArithmeticType + UpdateBalanceOutcome, Currency, OnFreeBalanceZero, MakePayment, OnUnbalanced, + WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, + Imbalance, SignedImbalance, ReservableCurrency }; use srml_support::dispatch::Result; use primitives::traits::{ - Zero, SimpleArithmetic, As, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDebug + Zero, SimpleArithmetic, As, StaticLookup, Member, CheckedAdd, CheckedSub, + MaybeSerializeDebug, Saturating }; use system::{IsDeadAccount, OnNewAccount, ensure_signed}; mod mock; mod tests; -pub trait Trait: system::Trait { +pub trait Subtrait: system::Trait { /// The balance of an account. type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + As + As + MaybeSerializeDebug; - /// A function which is invoked when the free-balance has fallen below the existential deposit and + /// A function that is invoked when the free-balance has fallen below the existential deposit and /// has been reduced to zero. /// /// Gives a chance to clean up resources associated with the given account. @@ -52,22 +202,45 @@ pub trait Trait: system::Trait { /// Handler for when a new account is created. type OnNewAccount: OnNewAccount; +} + +pub trait Trait: system::Trait { + /// The balance of an account. + type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + As + As + MaybeSerializeDebug; - /// A function that returns true iff a given account can transfer its funds to another account. - type EnsureAccountLiquid: EnsureAccountLiquid; + /// A function that is invoked when the free-balance has fallen below the existential deposit and + /// has been reduced to zero. + /// + /// Gives a chance to clean up resources associated with the given account. + type OnFreeBalanceZero: OnFreeBalanceZero; + + /// Handler for when a new account is created. + type OnNewAccount: OnNewAccount; + + /// Handler for the unbalanced reduction when taking transaction fees. + type TransactionPayment: OnUnbalanced>; + + /// Handler for the unbalanced reduction when taking fees associated with balance + /// transfer (which may also include account creation). + type TransferPayment: OnUnbalanced>; + + /// Handler for the unbalanced reduction when removing a dust account. + type DustRemoval: OnUnbalanced>; /// The overarching event type. - type Event: From> + Into<::Event>; + type Event: From> + Into<::Event>; } -impl ArithmeticType for Module { - type Type = ::Balance; +impl, I: Instance> Subtrait for T { + type Balance = T::Balance; + type OnFreeBalanceZero = T::OnFreeBalanceZero; + type OnNewAccount = T::OnNewAccount; } decl_event!( - pub enum Event where + pub enum Event where ::AccountId, - ::Balance + >::Balance { /// A new account was created. NewAccount(AccountId, Balance), @@ -99,21 +272,34 @@ impl> VestingSchedule { } } +#[derive(Encode, Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct BalanceLock { + pub id: LockIdentifier, + pub amount: Balance, + pub until: BlockNumber, + pub reasons: WithdrawReasons, +} + decl_storage! { - trait Store for Module as Balances { - /// The total amount of stake on the system. - pub TotalIssuance get(total_issuance) build(|config: &GenesisConfig| { + trait Store for Module, I: Instance=DefaultInstance> as Balances { + /// The total units issued in the system. + pub TotalIssuance get(total_issuance) build(|config: &GenesisConfig| { config.balances.iter().fold(Zero::zero(), |acc: T::Balance, &(_, n)| acc + n) }): T::Balance; - /// The minimum amount allowed to keep an account open. + /// The minimum amount required to keep an account open. pub ExistentialDeposit get(existential_deposit) config(): T::Balance; /// The fee required to make a transfer. pub TransferFee get(transfer_fee) config(): T::Balance; - /// The fee required to create an account. At least as big as ReclaimRebate. + /// The fee required to create an account. pub CreationFee get(creation_fee) config(): T::Balance; + /// The fee to be paid for making a transaction; the base. + pub TransactionBaseFee get(transaction_base_fee) config(): T::Balance; + /// The fee to be paid for making a transaction; the per-byte portion. + pub TransactionByteFee get(transaction_byte_fee) config(): T::Balance; /// Information regarding the vesting of a given account. - pub Vesting get(vesting) build(|config: &GenesisConfig| { + pub Vesting get(vesting) build(|config: &GenesisConfig| { config.vesting.iter().filter_map(|&(ref who, begin, length)| { let begin: u64 = begin.as_(); let length: u64 = length.as_(); @@ -126,7 +312,7 @@ decl_storage! { // <= begin it should be >= balance // >= begin+length it should be <= 0 - let per_block = balance / length; + let per_block = balance / length.max(primitives::traits::One::one()); let offset = begin * per_block + balance; (who.clone(), VestingSchedule { offset, per_block }) @@ -136,42 +322,52 @@ decl_storage! { /// The 'free' balance of a given account. /// - /// This is the only balance that matters in terms of most operations on tokens. It is - /// alone used to determine the balance when in the contract execution environment. When this + /// This is the only balance that matters in terms of most operations on tokens. It + /// alone is used to determine the balance when in the contract execution environment. When this /// balance falls below the value of `ExistentialDeposit`, then the 'current account' is - /// deleted: specifically `FreeBalance`. Furthermore, `OnFreeBalanceZero` callback - /// is invoked, giving a chance to external modules to cleanup data associated with + /// deleted: specifically `FreeBalance`. Further, the `OnFreeBalanceZero` callback + /// is invoked, giving a chance to external modules to clean up data associated with /// the deleted account. /// /// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. - pub FreeBalance get(free_balance) build(|config: &GenesisConfig| config.balances.clone()): map T::AccountId => T::Balance; + pub FreeBalance get(free_balance) build(|config: &GenesisConfig| config.balances.clone()): map T::AccountId => T::Balance; /// The amount of the balance of a given account that is externally reserved; this can still get /// slashed, but gets slashed last of all. /// /// This balance is a 'reserve' balance that other subsystems use in order to set aside tokens - /// that are still 'owned' by the account holder, but which are suspendable. (This is different - /// and wholly unrelated to the `Bondage` system used in the staking module.) + /// that are still 'owned' by the account holder, but which are suspendable. /// /// When this balance falls below the value of `ExistentialDeposit`, then this 'reserve account' /// is deleted: specifically, `ReservedBalance`. /// /// `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets - /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. + /// collapsed to zero if it ever becomes less than `ExistentialDeposit`.) pub ReservedBalance get(reserved_balance): map T::AccountId => T::Balance; + + /// Any liquidity locks on some account balances. + pub Locks get(locks): map T::AccountId => Vec>; } add_extra_genesis { config(balances): Vec<(T::AccountId, T::Balance)>; config(vesting): Vec<(T::AccountId, T::BlockNumber, T::BlockNumber)>; // begin, length } + extra_genesis_skip_phantom_data_field; } decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + fn deposit_event() = default; - /// Transfer some liquid free balance to another staker. + /// Transfer some liquid free balance to another account. + /// + /// `transfer` will set the `FreeBalance` of the sender and receiver. + /// It will decrease the total issuance of the system by the `TransferFee`. + /// If the sender's account is below the existential deposit as a result + /// of the transfer, the account will be reaped. + /// + /// The dispatch origin for this call must be `Signed` by the transactor. pub fn transfer( origin, dest: ::Source, @@ -179,10 +375,17 @@ decl_module! { ) { let transactor = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - Self::make_transfer(&transactor, &dest, value)?; + >::transfer(&transactor, &dest, value)?; } /// Set the balances of a given account. + /// + /// This will alter `FreeBalance` and `ReservedBalance` in storage. + /// If the new free or reserved balance is below the existential deposit, + /// it will also decrease the total issuance of the system (`TotalIssuance`) + /// and reset the account nonce (`system::AccountNonce`). + /// + /// The dispatch origin for this call is `root`. fn set_balance( who: ::Source, #[compact] free: T::Balance, @@ -195,10 +398,11 @@ decl_module! { } } -// For funding methods, see Currency trait -impl Module { +impl, I: Instance> Module { - /// Get the amount that is currently being vested and cannot be transfered out of this account. + // PUBLIC IMMUTABLES + + /// Get the amount that is currently being vested and cannot be transferred out of this account. pub fn vesting_balance(who: &T::AccountId) -> T::Balance { if let Some(v) = Self::vesting(who) { Self::free_balance(who).min(v.locked_at(>::block_number())) @@ -207,128 +411,77 @@ impl Module { } } - /// Set the free balance of an account to some new value. + // PRIVATE MUTABLES + + /// Set the reserved balance of an account to some new value. Will enforce `ExistentialDeposit` + /// law, annulling the account as needed. + /// + /// Doesn't do any preparatory work for creating a new account, so should only be used when it + /// is known that the account already exists. /// - /// Will enforce ExistentialDeposit law, anulling the account as needed. - /// In that case it will return `AccountKilled`. - pub fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { if balance < Self::existential_deposit() { - >::insert(who, balance); + >::insert(who, balance); Self::on_reserved_too_low(who); UpdateBalanceOutcome::AccountKilled } else { - >::insert(who, balance); + >::insert(who, balance); UpdateBalanceOutcome::Updated } } - /// Set the free balance of an account to some new value. Will enforce ExistentialDeposit - /// law anulling the account as needed. + /// Set the free balance of an account to some new value. Will enforce `ExistentialDeposit` + /// law, annulling the account as needed. /// /// Doesn't do any preparatory work for creating a new account, so should only be used when it /// is known that the account already exists. /// - /// Returns if the account was successfully updated or update has led to killing of the account. - pub fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { - // Commented out for no - but consider it instructive. + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { + // Commented out for now - but consider it instructive. // assert!(!Self::total_balance(who).is_zero()); + // assert!(Self::free_balance(who) > Self::existential_deposit()); if balance < Self::existential_deposit() { - >::insert(who, balance); + >::insert(who, balance); Self::on_free_too_low(who); UpdateBalanceOutcome::AccountKilled } else { - >::insert(who, balance); + >::insert(who, balance); UpdateBalanceOutcome::Updated } } - /// Set the free balance on an account to some new value. - /// - /// Same as [`set_free_balance`], but will create a new account. - /// - /// Returns if the account was successfully updated or update has led to killing of the account. - /// - /// [`set_free_balance`]: #method.set_free_balance - pub fn set_free_balance_creating(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { - let ed = >::existential_deposit(); - // If the balance is too low, then the account is reaped. - // NOTE: There are two balances for every account: `reserved_balance` and - // `free_balance`. This contract subsystem only cares about the latter: whenever - // the term "balance" is used *here* it should be assumed to mean "free balance" - // in the rest of the module. - // Free balance can never be less than ED. If that happens, it gets reduced to zero - // and the account information relevant to this subsystem is deleted (i.e. the - // account is reaped). - // NOTE: This is orthogonal to the `Bondage` value that an account has, a high - // value of which makes even the `free_balance` unspendable. - if balance < ed { - Self::set_free_balance(who, balance); - UpdateBalanceOutcome::AccountKilled - } else { - if !>::exists(who) { - Self::new_account(&who, balance); - } - Self::set_free_balance(who, balance); - - UpdateBalanceOutcome::Updated - } - } - - /// Transfer some liquid free balance to another staker. - pub fn make_transfer(transactor: &T::AccountId, dest: &T::AccountId, value: T::Balance) -> Result { - let from_balance = Self::free_balance(transactor); - let to_balance = Self::free_balance(dest); - let would_create = to_balance.is_zero(); - let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; - let liability = match value.checked_add(&fee) { - Some(l) => l, - None => return Err("got overflow after adding a fee to value"), - }; - - let vesting_balance = Self::vesting_balance(transactor); - let new_from_balance = match from_balance.checked_sub(&liability) { - None => return Err("balance too low to send value"), - Some(b) if b < vesting_balance => return Err("vesting balance too high to send value"), - Some(b) => b, - }; - if would_create && value < Self::existential_deposit() { - return Err("value too low to create account"); - } - T::EnsureAccountLiquid::ensure_account_can_withdraw(transactor, value, WithdrawReason::Transfer)?; - - // NOTE: total stake being stored in the same type means that this could never overflow - // but better to be safe than sorry. - let new_to_balance = match to_balance.checked_add(&value) { - Some(b) => b, - None => return Err("destination balance too high to receive value"), - }; - - if transactor != dest { - Self::set_free_balance(transactor, new_from_balance); - Self::decrease_total_stake_by(fee); - Self::set_free_balance_creating(dest, new_to_balance); - Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); - } - - Ok(()) - } - - /// Register a new account (with existential balance). + /// + /// This just calls appropriate hooks. It doesn't (necessarily) make any state changes. fn new_account(who: &T::AccountId, balance: T::Balance) { T::OnNewAccount::on_new_account(&who); Self::deposit_event(RawEvent::NewAccount(who.clone(), balance.clone())); } + /// Unregister an account. + /// + /// This just removes the nonce and leaves an event. fn reap_account(who: &T::AccountId) { >::remove(who); Self::deposit_event(RawEvent::ReapedAccount(who.clone())); } - /// Kill an account's free portion. + /// Account's free balance has dropped below existential deposit. Kill its + /// free side and the account completely if its reserved size is already dead. + /// + /// Will maintain total issuance. fn on_free_too_low(who: &T::AccountId) { - Self::decrease_total_stake_by(Self::free_balance(who)); - >::remove(who); + let dust = >::take(who); + >::remove(who); + + // underflow should never happen, but if it does, there's not much we can do about it. + if !dust.is_zero() { + T::DustRemoval::on_unbalanced(NegativeImbalance(dust)); + } T::OnFreeBalanceZero::on_free_balance_zero(who); @@ -337,35 +490,170 @@ impl Module { } } - /// Kill an account's reserved portion. + /// Account's reserved balance has dropped below existential deposit. Kill its + /// reserved side and the account completely if its free size is already dead. + /// + /// Will maintain total issuance. fn on_reserved_too_low(who: &T::AccountId) { - Self::decrease_total_stake_by(Self::reserved_balance(who)); - >::remove(who); + let dust = >::take(who); + + // underflow should never happen, but it if does, there's nothing to be done here. + if !dust.is_zero() { + T::DustRemoval::on_unbalanced(NegativeImbalance(dust)); + } if Self::free_balance(who).is_zero() { Self::reap_account(who); } } +} + +/// Opaque, move-only struct with private fields that serves as a token denoting that +/// funds have been created without any equal and opposite accounting. +#[must_use] +pub struct PositiveImbalance, I: Instance=DefaultInstance>(T::Balance); + +/// Opaque, move-only struct with private fields that serves as a token denoting that +/// funds have been destroyed without any equal and opposite accounting. +#[must_use] +pub struct NegativeImbalance, I: Instance=DefaultInstance>(T::Balance); - /// Increase TotalIssuance by Value. - pub fn increase_total_stake_by(value: T::Balance) { - if let Some(v) = >::total_issuance().checked_add(&value) { - >::put(v); +impl, I: Instance> Imbalance for PositiveImbalance { + type Opposite = NegativeImbalance; + + fn zero() -> Self { + Self(Zero::zero()) + } + fn drop_zero(self) -> result::Result<(), Self> { + if self.0.is_zero() { + Ok(()) + } else { + Err(self) } } - /// Decrease TotalIssuance by Value. - pub fn decrease_total_stake_by(value: T::Balance) { - if let Some(v) = >::total_issuance().checked_sub(&value) { - >::put(v); + fn split(self, amount: T::Balance) -> (Self, Self) { + let first = self.0.min(amount); + let second = self.0 - first; + (Self(first), Self(second)) + } + fn merge(self, other: Self) -> Self { + Self(self.0.saturating_add(other.0)) + } + fn subsume(&mut self, other: Self) { + self.0 = self.0.saturating_add(other.0) + } + fn offset(self, other: Self::Opposite) -> result::Result { + if self.0 >= other.0 { + Ok(Self(self.0 - other.0)) + } else { + Err(NegativeImbalance(other.0 - self.0)) } } + fn peek(&self) -> T::Balance { + self.0.clone() + } } -impl Currency for Module +impl, I: Instance> Imbalance for NegativeImbalance { + type Opposite = PositiveImbalance; + + fn zero() -> Self { + Self(Zero::zero()) + } + fn drop_zero(self) -> result::Result<(), Self> { + if self.0.is_zero() { + Ok(()) + } else { + Err(self) + } + } + fn split(self, amount: T::Balance) -> (Self, Self) { + let first = self.0.min(amount); + let second = self.0 - first; + (Self(first), Self(second)) + } + fn merge(self, other: Self) -> Self { + Self(self.0.saturating_add(other.0)) + } + fn subsume(&mut self, other: Self) { + self.0 = self.0.saturating_add(other.0) + } + fn offset(self, other: Self::Opposite) -> result::Result { + if self.0 >= other.0 { + Ok(Self(self.0 - other.0)) + } else { + Err(PositiveImbalance(other.0 - self.0)) + } + } + fn peek(&self) -> T::Balance { + self.0.clone() + } +} + +// TODO: #2052 +// Somewhat ugly hack in order to gain access to module's `increase_total_issuance_by` +// using only the Subtrait (which defines only the types that are not dependent +// on Positive/NegativeImbalance). Subtrait must be used otherwise we end up with a +// circular dependency with Trait having some types be dependent on PositiveImbalance +// and PositiveImbalance itself depending back on Trait for its Drop impl (and thus +// its type declaration). +// This works as long as `increase_total_issuance_by` doesn't use the Imbalance +// types (basically for charging fees). +// This should eventually be refactored so that the three type items that do +// depend on the Imbalance type (TransactionPayment, TransferPayment, DustRemoval) +// are placed in their own SRML module. +struct ElevatedTrait, I: Instance>(T, I); +impl, I: Instance> Clone for ElevatedTrait { + fn clone(&self) -> Self { unimplemented!() } +} +impl, I: Instance> PartialEq for ElevatedTrait { + fn eq(&self, _: &Self) -> bool { unimplemented!() } +} +impl, I: Instance> Eq for ElevatedTrait {} +impl, I: Instance> system::Trait for ElevatedTrait { + type Origin = T::Origin; + type Index = T::Index; + type BlockNumber = T::BlockNumber; + type Hash = T::Hash; + type Hashing = T::Hashing; + type Digest = T::Digest; + type AccountId = T::AccountId; + type Lookup = T::Lookup; + type Header = T::Header; + type Event = (); + type Log = T::Log; +} +impl, I: Instance> Trait for ElevatedTrait { + type Balance = T::Balance; + type OnFreeBalanceZero = T::OnFreeBalanceZero; + type OnNewAccount = T::OnNewAccount; + type Event = (); + type TransactionPayment = (); + type TransferPayment = (); + type DustRemoval = (); +} + +impl, I: Instance> Drop for PositiveImbalance { + /// Basic drop handler will just square up the total issuance. + fn drop(&mut self) { + , I>>::mutate(|v| *v = v.saturating_add(self.0)); + } +} + +impl, I: Instance> Drop for NegativeImbalance { + /// Basic drop handler will just square up the total issuance. + fn drop(&mut self) { + , I>>::mutate(|v| *v = v.saturating_sub(self.0)); + } +} + +impl, I: Instance> Currency for Module where T::Balance: MaybeSerializeDebug { type Balance = T::Balance; + type PositiveImbalance = PositiveImbalance; + type NegativeImbalance = NegativeImbalance; fn total_balance(who: &T::AccountId) -> Self::Balance { Self::free_balance(who) + Self::reserved_balance(who) @@ -375,16 +663,8 @@ where Self::free_balance(who) >= value } - fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { - if T::EnsureAccountLiquid::ensure_account_can_withdraw(who, value, WithdrawReason::Reserve).is_ok() { - Self::free_balance(who) >= value - } else { - false - } - } - fn total_issuance() -> Self::Balance { - >::get() + >::get() } fn minimum_balance() -> Self::Balance { @@ -392,36 +672,196 @@ where } fn free_balance(who: &T::AccountId) -> Self::Balance { - >::get(who) + >::get(who) + } + + fn ensure_can_withdraw( + who: &T::AccountId, + _amount: T::Balance, + reason: WithdrawReason, + new_balance: T::Balance, + ) -> Result { + match reason { + WithdrawReason::Reserve | WithdrawReason::Transfer if Self::vesting_balance(who) > new_balance => + return Err("vesting balance too high to send value"), + _ => {} + } + let locks = Self::locks(who); + if locks.is_empty() { + return Ok(()) + } + let now = >::block_number(); + if Self::locks(who).into_iter() + .all(|l| now >= l.until || new_balance >= l.amount || !l.reasons.contains(reason)) + { + Ok(()) + } else { + Err("account liquidity restrictions prevent withdrawal") + } } - fn reserved_balance(who: &T::AccountId) -> Self::Balance { - >::get(who) + fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::Balance) -> Result { + let from_balance = Self::free_balance(transactor); + let to_balance = Self::free_balance(dest); + let would_create = to_balance.is_zero(); + let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; + let liability = match value.checked_add(&fee) { + Some(l) => l, + None => return Err("got overflow after adding a fee to value"), + }; + + let new_from_balance = match from_balance.checked_sub(&liability) { + None => return Err("balance too low to send value"), + Some(b) => b, + }; + if would_create && value < Self::existential_deposit() { + return Err("value too low to create account"); + } + Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer, new_from_balance)?; + + // NOTE: total stake being stored in the same type means that this could never overflow + // but better to be safe than sorry. + let new_to_balance = match to_balance.checked_add(&value) { + Some(b) => b, + None => return Err("destination balance too high to receive value"), + }; + + if transactor != dest { + Self::set_free_balance(transactor, new_from_balance); + if !>::exists(dest) { + Self::new_account(dest, new_to_balance); + } + Self::set_free_balance(dest, new_to_balance); + T::TransferPayment::on_unbalanced(NegativeImbalance(fee)); + Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); + } + + Ok(()) } - fn slash(who: &T::AccountId, value: Self::Balance) -> Option { + fn withdraw( + who: &T::AccountId, + value: Self::Balance, + reason: WithdrawReason, + liveness: ExistenceRequirement, + ) -> result::Result { + if let Some(new_balance) = Self::free_balance(who).checked_sub(&value) { + if liveness == ExistenceRequirement::KeepAlive && new_balance < Self::existential_deposit() { + return Err("payment would kill account") + } + Self::ensure_can_withdraw(who, value, reason, new_balance)?; + Self::set_free_balance(who, new_balance); + Ok(NegativeImbalance(value)) + } else { + Err("too few free funds in account") + } + } + + fn slash( + who: &T::AccountId, + value: Self::Balance + ) -> (Self::NegativeImbalance, Self::Balance) { let free_balance = Self::free_balance(who); let free_slash = cmp::min(free_balance, value); Self::set_free_balance(who, free_balance - free_slash); - Self::decrease_total_stake_by(free_slash); - if free_slash < value { - Self::slash_reserved(who, value - free_slash) + let remaining_slash = value - free_slash; + // NOTE: `slash()` prefers free balance, but assumes that reserve balance can be drawn + // from in extreme circumstances. `can_slash()` should be used prior to `slash()` is avoid having + // to draw from reserved funds, however we err on the side of punishment if things are inconsistent + // or `can_slash` wasn't used appropriately. + if !remaining_slash.is_zero() { + let reserved_balance = Self::reserved_balance(who); + let reserved_slash = cmp::min(reserved_balance, remaining_slash); + Self::set_reserved_balance(who, reserved_balance - reserved_slash); + (NegativeImbalance(free_slash + reserved_slash), remaining_slash - reserved_slash) } else { - None + (NegativeImbalance(value), Zero::zero()) } } - fn reward(who: &T::AccountId, value: Self::Balance) -> result::Result<(), &'static str> { + fn deposit_into_existing( + who: &T::AccountId, + value: Self::Balance + ) -> result::Result { if Self::total_balance(who).is_zero() { return Err("beneficiary account must pre-exist"); } Self::set_free_balance(who, Self::free_balance(who) + value); - Self::increase_total_stake_by(value); - Ok(()) + Ok(PositiveImbalance(value)) } - fn increase_free_balance_creating(who: &T::AccountId, value: Self::Balance) -> UpdateBalanceOutcome { - Self::set_free_balance_creating(who, Self::free_balance(who) + value) + fn deposit_creating( + who: &T::AccountId, + value: Self::Balance, + ) -> Self::PositiveImbalance { + let (imbalance, _) = Self::make_free_balance_be(who, Self::free_balance(who) + value); + if let SignedImbalance::Positive(p) = imbalance { + p + } else { + // Impossible, but be defensive. + Self::PositiveImbalance::zero() + } + } + + fn make_free_balance_be(who: &T::AccountId, balance: T::Balance) -> ( + SignedImbalance, + UpdateBalanceOutcome + ) { + let original = Self::free_balance(who); + if balance < Self::existential_deposit() && original.is_zero() { + // If we're attempting to set an existing account to less than ED, then + // bypass the entire operation. It's a no-op if you follow it through, but + // since this is an instance where we might account for a negative imbalance + // (in the dust cleaner of set_free_balance) before we account for its actual + // equal and opposite cause (returned as an Imbalance), then in the + // instance that there's no other accounts on the system at all, we might + // underflow the issuance and our arithmetic will be off. + return ( + SignedImbalance::Positive(Self::PositiveImbalance::zero()), + UpdateBalanceOutcome::AccountKilled, + ) + } + let imbalance = if original <= balance { + SignedImbalance::Positive(PositiveImbalance(balance - original)) + } else { + SignedImbalance::Negative(NegativeImbalance(original - balance)) + }; + // If the balance is too low, then the account is reaped. + // NOTE: There are two balances for every account: `reserved_balance` and + // `free_balance`. This contract subsystem only cares about the latter: whenever + // the term "balance" is used *here* it should be assumed to mean "free balance" + // in the rest of the module. + // Free balance can never be less than ED. If that happens, it gets reduced to zero + // and the account information relevant to this subsystem is deleted (i.e. the + // account is reaped). + let outcome = if balance < >::existential_deposit() { + Self::set_free_balance(who, balance); + UpdateBalanceOutcome::AccountKilled + } else { + if !>::exists(who) { + Self::new_account(&who, balance); + } + Self::set_free_balance(who, balance); + UpdateBalanceOutcome::Updated + }; + (imbalance, outcome) + } +} + +impl, I: Instance> ReservableCurrency for Module +where + T::Balance: MaybeSerializeDebug +{ + fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { + Self::free_balance(who) + .checked_sub(&value) + .map_or(false, |new_balance| + Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve, new_balance).is_ok() + ) + } + + fn reserved_balance(who: &T::AccountId) -> Self::Balance { + >::get(who) } fn reserve(who: &T::AccountId, value: Self::Balance) -> result::Result<(), &'static str> { @@ -429,41 +869,37 @@ where if b < value { return Err("not enough free funds") } - T::EnsureAccountLiquid::ensure_account_can_withdraw(who, value, WithdrawReason::Reserve)?; + let new_balance = b - value; + Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve, new_balance)?; Self::set_reserved_balance(who, Self::reserved_balance(who) + value); - Self::set_free_balance(who, b - value); + Self::set_free_balance(who, new_balance); Ok(()) } - fn unreserve(who: &T::AccountId, value: Self::Balance) -> Option { + fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance { let b = Self::reserved_balance(who); let actual = cmp::min(b, value); Self::set_free_balance(who, Self::free_balance(who) + actual); Self::set_reserved_balance(who, b - actual); - if actual == value { - None - } else { - Some(value - actual) - } + value - actual } - fn slash_reserved(who: &T::AccountId, value: Self::Balance) -> Option { + fn slash_reserved( + who: &T::AccountId, + value: Self::Balance + ) -> (Self::NegativeImbalance, Self::Balance) { let b = Self::reserved_balance(who); let slash = cmp::min(b, value); + // underflow should never happen, but it if does, there's nothing to be done here. Self::set_reserved_balance(who, b - slash); - Self::decrease_total_stake_by(slash); - if value == slash { - None - } else { - Some(value - slash) - } + (NegativeImbalance(slash), value - slash) } fn repatriate_reserved( slashed: &T::AccountId, beneficiary: &T::AccountId, - value: Self::Balance - ) -> result::Result, &'static str> { + value: Self::Balance, + ) -> result::Result { if Self::total_balance(beneficiary).is_zero() { return Err("beneficiary account must pre-exist"); } @@ -471,38 +907,100 @@ where let slash = cmp::min(b, value); Self::set_free_balance(beneficiary, Self::free_balance(beneficiary) + slash); Self::set_reserved_balance(slashed, b - slash); - if value == slash { - Ok(None) - } else { - Ok(Some(value - slash)) - } + Ok(value - slash) } } -impl TransferAsset for Module { - type Amount = T::Balance; - - fn transfer(from: &T::AccountId, to: &T::AccountId, amount: T::Balance) -> Result { - Self::make_transfer(from, to, amount) - } - - fn withdraw(who: &T::AccountId, value: T::Balance, reason: WithdrawReason) -> Result { - T::EnsureAccountLiquid::ensure_account_can_withdraw(who, value, reason)?; - let b = Self::free_balance(who); - ensure!(b >= value, "account has too few funds"); - Self::set_free_balance(who, b - value); - Self::decrease_total_stake_by(value); - Ok(()) +impl, I: Instance> LockableCurrency for Module +where + T::Balance: MaybeSerializeDebug +{ + type Moment = T::BlockNumber; + + fn set_lock( + id: LockIdentifier, + who: &T::AccountId, + amount: T::Balance, + until: T::BlockNumber, + reasons: WithdrawReasons, + ) { + let now = >::block_number(); + let mut new_lock = Some(BalanceLock { id, amount, until, reasons }); + let mut locks = Self::locks(who).into_iter().filter_map(|l| + if l.id == id { + new_lock.take() + } else if l.until > now { + Some(l) + } else { + None + }).collect::>(); + if let Some(lock) = new_lock { + locks.push(lock) + } + >::insert(who, locks); + } + + fn extend_lock( + id: LockIdentifier, + who: &T::AccountId, + amount: T::Balance, + until: T::BlockNumber, + reasons: WithdrawReasons, + ) { + let now = >::block_number(); + let mut new_lock = Some(BalanceLock { id, amount, until, reasons }); + let mut locks = Self::locks(who).into_iter().filter_map(|l| + if l.id == id { + new_lock.take().map(|nl| { + BalanceLock { + id: l.id, + amount: l.amount.max(nl.amount), + until: l.until.max(nl.until), + reasons: l.reasons | nl.reasons, + } + }) + } else if l.until > now { + Some(l) + } else { + None + }).collect::>(); + if let Some(lock) = new_lock { + locks.push(lock) + } + >::insert(who, locks); + } + + fn remove_lock( + id: LockIdentifier, + who: &T::AccountId, + ) { + let now = >::block_number(); + let locks = Self::locks(who).into_iter().filter_map(|l| + if l.until > now && l.id != id { + Some(l) + } else { + None + }).collect::>(); + >::insert(who, locks); } +} - fn deposit(who: &T::AccountId, value: T::Balance) -> Result { - Self::set_free_balance_creating(who, Self::free_balance(who) + value); - Self::increase_total_stake_by(value); +impl, I: Instance> MakePayment for Module { + fn make_payment(transactor: &T::AccountId, encoded_len: usize) -> Result { + let encoded_len = >::sa(encoded_len as u64); + let transaction_fee = Self::transaction_base_fee() + Self::transaction_byte_fee() * encoded_len; + let imbalance = Self::withdraw( + transactor, + transaction_fee, + WithdrawReason::TransactionPayment, + ExistenceRequirement::KeepAlive + )?; + T::TransactionPayment::on_unbalanced(imbalance); Ok(()) } } -impl IsDeadAccount for Module +impl, I: Instance> IsDeadAccount for Module where T::Balance: MaybeSerializeDebug { @@ -510,3 +1008,4 @@ where Self::total_balance(who).is_zero() } } + diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index 6dcff18c6eb492d5768d6641b07737a02fac6a55..db20efc47566aec3e05e4e9e34b74627f8b30ae4 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -40,7 +40,7 @@ impl system::Trait for Runtime { type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; @@ -49,11 +49,15 @@ impl Trait for Runtime { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); - type EnsureAccountLiquid = (); type Event = (); + type TransactionPayment = (); + type DustRemoval = (); + type TransferPayment = (); } pub struct ExtBuilder { + transaction_base_fee: u64, + transaction_byte_fee: u64, existential_deposit: u64, transfer_fee: u64, creation_fee: u64, @@ -63,6 +67,8 @@ pub struct ExtBuilder { impl Default for ExtBuilder { fn default() -> Self { Self { + transaction_base_fee: 0, + transaction_byte_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, @@ -85,8 +91,16 @@ impl ExtBuilder { self.creation_fee = creation_fee; self } + pub fn transaction_fees(mut self, base_fee: u64, byte_fee: u64) -> Self { + self.transaction_base_fee = base_fee; + self.transaction_byte_fee = byte_fee; + self + } pub fn monied(mut self, monied: bool) -> Self { self.monied = monied; + if self.existential_deposit == 0 { + self.existential_deposit = 1; + } self } pub fn vesting(mut self, vesting: bool) -> Self { @@ -95,16 +109,13 @@ impl ExtBuilder { } pub fn build(self) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; - let balance_factor = if self.existential_deposit > 0 { - 256 - } else { - 1 - }; t.extend(GenesisConfig:: { + transaction_base_fee: self.transaction_base_fee, + transaction_byte_fee: self.transaction_byte_fee, balances: if self.monied { - vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] + vec![(1, 10 * self.existential_deposit), (2, 20 * self.existential_deposit), (3, 30 * self.existential_deposit), (4, 40 * self.existential_deposit)] } else { - vec![(10, balance_factor), (20, balance_factor)] + vec![] }, existential_deposit: self.existential_deposit, transfer_fee: self.transfer_fee, diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 272e4f5f10d363b620a58aa77be7846803e72966..89491fe5f80fc99b673d2c0643c355a03ca61d5f 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,7 +21,137 @@ use super::*; use mock::{Balances, ExtBuilder, Runtime, System}; use runtime_io::with_externalities; -use srml_support::{assert_noop, assert_ok, assert_err}; +use srml_support::{ + assert_noop, assert_ok, assert_err, + traits::{LockableCurrency, LockIdentifier, WithdrawReason, WithdrawReasons, + Currency, MakePayment, ReservableCurrency} +}; + +const ID_1: LockIdentifier = *b"1 "; +const ID_2: LockIdentifier = *b"2 "; +const ID_3: LockIdentifier = *b"3 "; + +#[test] +fn basic_locking_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + assert_eq!(Balances::free_balance(&1), 10); + Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 5), "account liquidity restrictions prevent withdrawal"); + }); +} + +#[test] +fn partial_locking_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn lock_removal_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); + Balances::remove_lock(ID_1, &1); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn lock_replacement_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn double_locking_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + Balances::set_lock(ID_2, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn combination_locking_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, u64::max_value(), 0, WithdrawReasons::none()); + Balances::set_lock(ID_2, &1, 0, u64::max_value(), WithdrawReasons::none()); + Balances::set_lock(ID_3, &1, 0, 0, WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn lock_value_extension_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 2, u64::max_value(), WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 8, u64::max_value(), WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 3), "account liquidity restrictions prevent withdrawal"); + }); +} + +#[test] +fn lock_reasons_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).transaction_fees(0, 1).build(), || { + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into()); + assert_noop!(>::transfer(&1, &2, 1), "account liquidity restrictions prevent withdrawal"); + assert_ok!(>::reserve(&1, 1)); + assert_ok!(>::make_payment(&1, 1)); + + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Reserve.into()); + assert_ok!(>::transfer(&1, &2, 1)); + assert_noop!(>::reserve(&1, 1), "account liquidity restrictions prevent withdrawal"); + assert_ok!(>::make_payment(&1, 1)); + + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::TransactionPayment.into()); + assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::reserve(&1, 1)); + assert_noop!(>::make_payment(&1, 1), "account liquidity restrictions prevent withdrawal"); + }); +} + +#[test] +fn lock_block_number_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 1), "account liquidity restrictions prevent withdrawal"); + + System::set_block_number(2); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn lock_block_number_extension_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 10, 1, WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + System::set_block_number(2); + Balances::extend_lock(ID_1, &1, 10, 8, WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 3), "account liquidity restrictions prevent withdrawal"); + }); +} + +#[test] +fn lock_reasons_extension_should_work() { + with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReasons::none()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReason::Reserve.into()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + }); +} #[test] fn default_indexing_on_new_accounts_should_not_work2() { @@ -39,7 +169,7 @@ fn default_indexing_on_new_accounts_should_not_work2() { "value too low to create account" ); assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist - assert_eq!(Balances::free_balance(&1), 256 * 10); + assert_eq!(Balances::free_balance(&1), 100); }, ); } @@ -67,7 +197,7 @@ fn reserved_balance_should_prevent_reclaim_count() { assert_eq!(Balances::total_balance(&5), 256 * 1 + 0x69); assert_eq!(Balances::is_dead_account(&5), false); - assert_eq!(Balances::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed + assert!(Balances::slash(&2, 256 * 18 + 2).1.is_zero()); // account 2 gets slashed assert_eq!(Balances::total_balance(&2), 0); // "reserve" account reduced to 255 (below ED) so account deleted assert_eq!(System::account_nonce(&2), 0); // nonce zero assert_eq!(Balances::is_dead_account(&2), true); @@ -84,7 +214,7 @@ fn reserved_balance_should_prevent_reclaim_count() { fn reward_should_work() { with_externalities(&mut ExtBuilder::default().monied(true).build(), || { assert_eq!(Balances::total_balance(&1), 10); - assert_ok!(Balances::reward(&1, 10)); + assert_ok!(Balances::deposit_into_existing(&1, 10).map(drop)); assert_eq!(Balances::total_balance(&1), 20); assert_eq!(>::get(), 110); }); @@ -94,17 +224,17 @@ fn reward_should_work() { fn dust_account_removal_should_work() { with_externalities( &mut ExtBuilder::default() - .existential_deposit(256 * 10) + .existential_deposit(100) .monied(true) .build(), || { System::inc_account_nonce(&2); assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Balances::total_balance(&2), 256 * 20); + assert_eq!(Balances::total_balance(&2), 2000); - assert_ok!(Balances::transfer(Some(2).into(), 5, 256 * 10 + 1)); // index 1 (account 2) becomes zombie + assert_ok!(Balances::transfer(Some(2).into(), 5, 1901)); // index 1 (account 2) becomes zombie assert_eq!(Balances::total_balance(&2), 0); - assert_eq!(Balances::total_balance(&5), 256 * 10 + 1); + assert_eq!(Balances::total_balance(&5), 1901); assert_eq!(System::account_nonce(&2), 0); }, ); @@ -114,17 +244,17 @@ fn dust_account_removal_should_work() { fn dust_account_removal_should_work2() { with_externalities( &mut ExtBuilder::default() - .existential_deposit(256 * 10) + .existential_deposit(100) .creation_fee(50) .monied(true) .build(), || { System::inc_account_nonce(&2); assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Balances::total_balance(&2), 256 * 20); - assert_ok!(Balances::transfer(Some(2).into(), 5, 256 * 10)); // index 1 (account 2) becomes zombie for 256*10 + 50(fee) < 256 * 10 (ext_deposit) + assert_eq!(Balances::total_balance(&2), 2000); + assert_ok!(Balances::transfer(Some(2).into(), 5, 1851)); // index 1 (account 2) becomes zombie for 256*10 + 50(fee) < 256 * 10 (ext_deposit) assert_eq!(Balances::total_balance(&2), 0); - assert_eq!(Balances::total_balance(&5), 256 * 10); + assert_eq!(Balances::total_balance(&5), 1851); assert_eq!(System::account_nonce(&2), 0); }, ); @@ -133,7 +263,7 @@ fn dust_account_removal_should_work2() { #[test] fn balance_works() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 42); + let _ = Balances::deposit_creating(&1, 42); assert_eq!(Balances::free_balance(&1), 42); assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!(Balances::total_balance(&1), 42); @@ -146,8 +276,7 @@ fn balance_works() { #[test] fn balance_transfer_works() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); - Balances::increase_total_stake_by(111); + let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::transfer(Some(1).into(), 2, 69)); assert_eq!(Balances::total_balance(&1), 42); assert_eq!(Balances::total_balance(&2), 69); @@ -157,7 +286,7 @@ fn balance_transfer_works() { #[test] fn reserving_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); + let _ = Balances::deposit_creating(&1, 111); assert_eq!(Balances::total_balance(&1), 111); assert_eq!(Balances::free_balance(&1), 111); @@ -174,7 +303,7 @@ fn reserving_balance_should_work() { #[test] fn balance_transfer_when_reserved_should_not_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); + let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 69)); assert_noop!(Balances::transfer(Some(1).into(), 2, 69), "balance too low to send value"); }); @@ -183,7 +312,7 @@ fn balance_transfer_when_reserved_should_not_work() { #[test] fn deducting_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); + let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 69)); assert_eq!(Balances::free_balance(&1), 42); }); @@ -192,7 +321,7 @@ fn deducting_balance_should_work() { #[test] fn refunding_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 42); + let _ = Balances::deposit_creating(&1, 42); Balances::set_reserved_balance(&1, 69); Balances::unreserve(&1, 69); assert_eq!(Balances::free_balance(&1), 111); @@ -203,33 +332,31 @@ fn refunding_balance_should_work() { #[test] fn slashing_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); - Balances::increase_total_stake_by(111); + let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 69)); - assert!(Balances::slash(&1, 69).is_none()); + assert!(Balances::slash(&1, 69).1.is_zero()); assert_eq!(Balances::free_balance(&1), 0); assert_eq!(Balances::reserved_balance(&1), 42); - assert_eq!(>::get(), 44); + assert_eq!(>::get(), 42); }); } #[test] fn slashing_incomplete_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 42); - Balances::increase_total_stake_by(42); + let _ = Balances::deposit_creating(&1, 42); assert_ok!(Balances::reserve(&1, 21)); - assert!(Balances::slash(&1, 69).is_some()); + assert_eq!(Balances::slash(&1, 69).1, 27); assert_eq!(Balances::free_balance(&1), 0); assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(>::get(), 2); + assert_eq!(>::get(), 0); }); } #[test] fn unreserving_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); + let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 111)); Balances::unreserve(&1, 42); assert_eq!(Balances::reserved_balance(&1), 69); @@ -240,36 +367,34 @@ fn unreserving_balance_should_work() { #[test] fn slashing_reserved_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); - Balances::increase_total_stake_by(111); + let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 111)); - assert!(Balances::slash_reserved(&1, 42).is_none()); + assert_eq!(Balances::slash_reserved(&1, 42).1, 0); assert_eq!(Balances::reserved_balance(&1), 69); assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(>::get(), 71); + assert_eq!(>::get(), 69); }); } #[test] fn slashing_incomplete_reserved_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); - Balances::increase_total_stake_by(111); + let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 42)); - assert!(Balances::slash_reserved(&1, 69).is_some()); + assert_eq!(Balances::slash_reserved(&1, 69).1, 27); assert_eq!(Balances::free_balance(&1), 69); assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(>::get(), 71); + assert_eq!(>::get(), 69); }); } #[test] fn transferring_reserved_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 110); - Balances::set_free_balance(&2, 1); + let _ = Balances::deposit_creating(&1, 110); + let _ = Balances::deposit_creating(&2, 1); assert_ok!(Balances::reserve(&1, 110)); - assert_ok!(Balances::repatriate_reserved(&1, &2, 41), None); + assert_ok!(Balances::repatriate_reserved(&1, &2, 41), 0); assert_eq!(Balances::reserved_balance(&1), 69); assert_eq!(Balances::free_balance(&1), 0); assert_eq!(Balances::reserved_balance(&2), 0); @@ -280,7 +405,7 @@ fn transferring_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_to_nonexistent_should_fail() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); + let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 111)); assert_noop!(Balances::repatriate_reserved(&1, &2, 42), "beneficiary account must pre-exist"); }); @@ -289,10 +414,10 @@ fn transferring_reserved_balance_to_nonexistent_should_fail() { #[test] fn transferring_incomplete_reserved_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 110); - Balances::set_free_balance(&2, 1); + let _ = Balances::deposit_creating(&1, 110); + let _ = Balances::deposit_creating(&2, 1); assert_ok!(Balances::reserve(&1, 41)); - assert!(Balances::repatriate_reserved(&1, &2, 69).unwrap().is_some()); + assert_ok!(Balances::repatriate_reserved(&1, &2, 69), 28); assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!(Balances::free_balance(&1), 69); assert_eq!(Balances::reserved_balance(&2), 0); @@ -316,32 +441,62 @@ fn transferring_too_high_value_should_not_panic() { }); } +#[test] +fn account_create_on_free_too_low_with_other() { + with_externalities( + &mut ExtBuilder::default().existential_deposit(100).build(), + || { + let _ = Balances::deposit_creating(&1, 100); + assert_eq!(>::get(), 100); + + // No-op. + let _ = Balances::deposit_creating(&2, 50); + assert_eq!(Balances::free_balance(&2), 0); + assert_eq!(>::get(), 100); + } + ) +} + + +#[test] +fn account_create_on_free_too_low() { + with_externalities( + &mut ExtBuilder::default().existential_deposit(100).build(), + || { + // No-op. + let _ = Balances::deposit_creating(&2, 50); + assert_eq!(Balances::free_balance(&2), 0); + assert_eq!(>::get(), 0); + } + ) +} + #[test] fn account_removal_on_free_too_low() { with_externalities( &mut ExtBuilder::default().existential_deposit(100).build(), || { - // Setup two accounts with free balance above the exsistential threshold. - { - Balances::set_free_balance(&1, 110); - Balances::increase_total_stake_by(110); + assert_eq!(>::get(), 0); - Balances::set_free_balance(&2, 110); - Balances::increase_total_stake_by(110); + // Setup two accounts with free balance above the existential threshold. + let _ = Balances::deposit_creating(&1, 110); + let _ = Balances::deposit_creating(&2, 110); - assert_eq!(>::get(), 732); - } + assert_eq!(Balances::free_balance(&1), 110); + assert_eq!(Balances::free_balance(&2), 110); + assert_eq!(>::get(), 220); // Transfer funds from account 1 of such amount that after this transfer - // the balance of account 1 will be below the exsistential threshold. + // the balance of account 1 will be below the existential threshold. // This should lead to the removal of all balance of this account. assert_ok!(Balances::transfer(Some(1).into(), 2, 20)); // Verify free balance removal of account 1. assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::free_balance(&2), 130); // Verify that TotalIssuance tracks balance removal when free balance is too low. - assert_eq!(>::get(), 642); + assert_eq!(>::get(), 130); }, ); } @@ -366,7 +521,7 @@ fn transfer_overflow_isnt_exploitable() { fn check_vesting_status() { with_externalities( &mut ExtBuilder::default() - .existential_deposit(10) + .existential_deposit(256) .monied(true) .vesting(true) .build(), @@ -416,10 +571,10 @@ fn unvested_balance_should_not_transfer() { || { assert_eq!(System::block_number(), 1); let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance - assert_eq!(Balances::vesting_balance(&1), user1_free_balance - 256); // Account 1 has only 256 units vested at block 1 + assert_eq!(user1_free_balance, 100); // Account 1 has free balance + assert_eq!(Balances::vesting_balance(&1), 90); // Account 1 has only 10 units vested at block 1 assert_noop!( - Balances::transfer(Some(1).into(), 2, 256 * 2), + Balances::transfer(Some(1).into(), 2, 11), "vesting balance too high to send value" ); // Account 1 cannot send more than vested amount } @@ -435,13 +590,11 @@ fn vested_balance_should_transfer() { .vesting(true) .build(), || { - System::set_block_number(5); - assert_eq!(System::block_number(), 5); + assert_eq!(System::block_number(), 1); let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance - - assert_eq!(Balances::vesting_balance(&1), user1_free_balance - 256 * 5); // Account 1 has 256 * 5 units vested at block 5 - assert_ok!(Balances::transfer(Some(1).into(), 2, 256 * 2)); // Account 1 can now send vested value + assert_eq!(user1_free_balance, 100); // Account 1 has free balance + assert_eq!(Balances::vesting_balance(&1), 90); // Account 1 has only 10 units vested at block 1 + assert_ok!(Balances::transfer(Some(1).into(), 2, 10)); } ); } @@ -456,12 +609,12 @@ fn extra_balance_should_transfer() { .build(), || { assert_eq!(System::block_number(), 1); - assert_ok!(Balances::transfer(Some(3).into(), 1, 256 * 10)); + assert_ok!(Balances::transfer(Some(3).into(), 1, 100)); let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 256 * 20); // Account 1 has 2560 more free balance than normal + assert_eq!(user1_free_balance, 200); // Account 1 has 100 more free balance than normal - assert_eq!(Balances::vesting_balance(&1), 256 * 10 - 256); // Account 1 has 256 units vested at block 1 - assert_ok!(Balances::transfer(Some(1).into(), 2, 256 * 5)); // Account 1 can send extra units gained + assert_eq!(Balances::vesting_balance(&1), 90); // Account 1 has 90 units vested at block 1 + assert_ok!(Balances::transfer(Some(1).into(), 2, 105)); // Account 1 can send extra units gained } ); -} \ No newline at end of file +} diff --git a/srml/consensus/Cargo.toml b/srml/consensus/Cargo.toml index 075980fc5f158dcfb356a392112615d918d0d0b8..6adeb90d0248cd34f5701e46509a8e4e8dc38ea2 100644 --- a/srml/consensus/Cargo.toml +++ b/srml/consensus/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../../core/primitives", default-features = false } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } @@ -22,7 +22,7 @@ runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] std = [ - "serde/std", + "serde", "serde_derive", "parity-codec/std", "substrate-primitives/std", diff --git a/srml/consensus/src/lib.rs b/srml/consensus/src/lib.rs index a99a37064281eb47275068ca70147eb677f045ed..4c2a57b83c1de5d7d3f27cdb6a599221e25e9ab1 100644 --- a/srml/consensus/src/lib.rs +++ b/srml/consensus/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,7 +14,105 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Consensus module for runtime; manages the authority set ready for the native code. +//! # Consensus Module +//! +//! ## Overview +//! +//! The consensus module manages the authority set for the native code. It provides support for reporting offline +//! behavior among validators and logging changes in the validator authority set. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! - `report_misbehavior` - Report some misbehavior. The origin of this call must be signed. +//! - `note_offline` - Note that the previous block's validator missed its opportunity to propose a block. +//! The origin of this call must be an inherent. +//! - `remark` - Make some on-chain remark. The origin of this call must be signed. +//! - `set_heap_pages` - Set the number of pages in the WebAssembly environment's heap. +//! - `set_code` - Set the new code. +//! - `set_storage` - Set some items of storage. +//! +//! Please refer to the [`Call`](./enum.Call.html) enum and its associated variants for documentation on each function. +//! +//! ### Public Functions +//! +//! See the [module](./struct.Module.html) for details on publicly available functions. +//! +//! ## Usage +//! +//! ### Prerequisites +//! +//! To use functionality from the consensus module, implement the specific Trait or function that you are invoking +//! from the module: +//! +//! ```rust,ignore +//! impl for consensus::SomeTrait for Module { +//! /// required functions and types for trait included here +//! /// more comprehensive example included below +//! } +//! ``` +//! +//! Alternatively, to set the authorities: +//! +//! ```rust,ignore +//! consensus::set_authorities(&[]) // example included below +//! ``` +//! +//! ### Simple Code Snippet +//! +//! Set authorities: +//! +//! ```rust,ignore +//! >::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]) +//! ``` +//! +//! Log changes in the authorities set: +//! +//! ```rust,ignore +//! >::on_finalise(5); // finalize UintAuthorityId(5) +//! ``` +//! +//! ### Example from SRML +//! +//! In the staking module, the `consensus::OnOfflineReport` is implemented to monitor offline +//! reporting among validators: +//! +//! ```rust,ignore +//! impl consensus::OnOfflineReport> for Module { +//! fn handle_report(reported_indices: Vec) { +//! for validator_index in reported_indices { +//! let v = >::validators()[validator_index as usize].clone(); +//! Self::on_offline_validator(v, 1); +//! } +//! } +//! } +//! ``` +//! +//! In the GRANDPA module, we use `srml-consensus` to get the set of `next_authorities` before changing +//! this set according to the consensus algorithm (which does not rotate sessions in the *normal* way): +//! +//! ```rust,ignore +//! let next_authorities = >::authorities() +//! .into_iter() +//! .map(|key| (key, 1)) // evenly-weighted. +//! .collect::::SessionKey, u64)>>(); +//! ``` +//! +//! ## Related Modules +//! +//! - [`staking`](../srml_staking/index.html): This module uses `srml-consensus` to monitor offline +//! reporting among validators. +//! - [`aura`](../srml_aura/index.html): This module does not relate directly to `srml-consensus`, +//! but serves to manage offline reporting for the Aura consensus algorithm with its own `handle_report` method. +//! - [`grandpa`](../srml_grandpa/index.html): Although GRANDPA does its own voter-set management, +//! it has a mode where it can track `consensus`, if desired. +//! +//! ## References +//! +//! If you're interested in hacking on this module, it is useful to understand the interaction with +//! `substrate/core/inherents/src/lib.rs` and, specifically, the required implementation of `ProvideInherent` +//! to create and check inherents. #![cfg_attr(not(feature = "std"), no_std)] @@ -34,7 +132,7 @@ use inherents::{ }; #[cfg(any(feature = "std", test))] -use substrate_primitives::Ed25519AuthorityId; +use substrate_primitives::ed25519::Public as AuthorityId; mod mock; mod tests; @@ -51,6 +149,7 @@ impl StorageVec for AuthorityStorageVec { const PREFIX: &'static [u8] = well_known_keys::AUTHORITY_PREFIX; } +pub type Key = Vec; pub type KeyValue = (Vec, Vec); /// Handling offline validator reports in a generic way. @@ -87,9 +186,9 @@ impl InherentOfflineReport for () { } } -/// A variant of the `OfflineReport` which is useful for instant-finality blocks. +/// A variant of the `OfflineReport` that is useful for instant-finality blocks. /// -/// This assumes blocks are only finalized +/// This assumes blocks are only finalized. pub struct InstantFinalityReportVec(::rstd::marker::PhantomData); impl>> InherentOfflineReport for InstantFinalityReportVec { @@ -116,7 +215,7 @@ pub type Log = RawLog< ::SessionKey, >; -/// A logs in this module. +/// Logs in this module. #[cfg_attr(feature = "std", derive(Serialize, Debug))] #[derive(Encode, Decode, PartialEq, Eq, Clone)] pub enum RawLog { @@ -135,7 +234,7 @@ impl RawLog { // Implementation for tests outside of this crate. #[cfg(any(feature = "std", test))] -impl From> for primitives::testing::DigestItem where N: Into { +impl From> for primitives::testing::DigestItem where N: Into { fn from(log: RawLog) -> primitives::testing::DigestItem { match log { RawLog::AuthoritiesChange(authorities) => @@ -158,7 +257,7 @@ pub trait Trait: system::Trait { decl_storage! { trait Store for Module as Consensus { - // Authorities set actual at the block execution start. IsSome only if + // Actual authorities set at the block execution start. Is `Some` iff // the set has been changed. OriginalAuthorities: Option>; } @@ -182,12 +281,12 @@ decl_storage! { decl_module! { pub struct Module for enum Call where origin: T::Origin { - /// Report some misbehaviour. + /// Report some misbehavior. fn report_misbehavior(origin, _report: Vec) { ensure_signed(origin)?; } - /// Note the previous block's validator missed their opportunity to propose a block. + /// Note that the previous block's validator missed its opportunity to propose a block. fn note_offline(origin, offline: ::Inherent) { ensure_inherent(origin)?; @@ -216,7 +315,14 @@ decl_module! { } } - fn on_finalise() { + /// Kill some items from storage. + fn kill_storage(keys: Vec) { + for key in &keys { + storage::unhashed::kill(&key); + } + } + + fn on_finalize() { if let Some(original_authorities) = >::take() { let current_authorities = AuthorityStorageVec::::items(); if current_authorities != original_authorities { @@ -235,7 +341,7 @@ impl Module { /// Set the current set of authorities' session keys. /// - /// Called by `next_session` only. + /// Called by `rotate_session` only. pub fn set_authorities(authorities: &[T::SessionKey]) { let current_authorities = AuthorityStorageVec::::items(); if current_authorities != authorities { @@ -244,6 +350,12 @@ impl Module { } } + /// Set a single authority by index. + pub fn set_authority_count(count: u32) { + Self::save_original_authorities(None); + AuthorityStorageVec::::set_count(count); + } + /// Set a single authority by index. pub fn set_authority(index: u32, key: &T::SessionKey) { let current_authority = AuthorityStorageVec::::item(index); @@ -270,11 +382,16 @@ impl Module { } } +/// Implementing `ProvideInherent` enables this module to create and check inherents. impl ProvideInherent for Module { + /// The call type of the module. type Call = Call; + /// The error returned by `check_inherent`. type Error = MakeFatalError; + /// The inherent identifier used by this inherent. const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + /// Creates an inherent from the `InherentData`. fn create_inherent(data: &InherentData) -> Option { if let Ok(Some(data)) = data.get_data::<::Inherent>( @@ -291,6 +408,7 @@ impl ProvideInherent for Module { } } + /// Verify the validity of the given inherent. fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> { let offline = match call { Call::note_offline(ref offline) => offline, diff --git a/srml/consensus/src/mock.rs b/srml/consensus/src/mock.rs index 0cdf4ef2c615aa519714de92a03f0581e7fa3437..85e6dc365411608c348732950756d77626d165d3 100644 --- a/srml/consensus/src/mock.rs +++ b/srml/consensus/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -44,7 +44,7 @@ impl system::Trait for Test { type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; diff --git a/srml/consensus/src/tests.rs b/srml/consensus/src/tests.rs index d883a897f113b8d2692a5c5b76a40f71d90bb867..bf8b3a09f37686ba3b47979cdb45e8bd1b589486 100644 --- a/srml/consensus/src/tests.rs +++ b/srml/consensus/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ #![cfg(test)] -use primitives::{generic, testing::{self, UintAuthorityId}, traits::OnFinalise}; +use primitives::{generic, testing::{self, UintAuthorityId}, traits::OnFinalize}; use runtime_io::with_externalities; use crate::mock::{Consensus, System, new_test_ext}; use inherents::{InherentData, ProvideInherent}; @@ -26,10 +26,10 @@ use inherents::{InherentData, ProvideInherent}; #[test] fn authorities_change_logged() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialise(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default()); Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]); - Consensus::on_finalise(1); - let header = System::finalise(); + Consensus::on_finalize(1); + let header = System::finalize(); assert_eq!(header.digest, testing::Digest { logs: vec![ generic::DigestItem::AuthoritiesChange( @@ -44,12 +44,33 @@ fn authorities_change_logged() { }); } +#[test] +fn partial_authorities_change_logged() { + with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { + System::initialize(&2, &Default::default(), &Default::default()); + Consensus::set_authorities(&[UintAuthorityId(2), UintAuthorityId(4), UintAuthorityId(5)]); + Consensus::on_finalize(2); + let header = System::finalize(); + assert_eq!(header.digest, testing::Digest { + logs: vec![ + generic::DigestItem::AuthoritiesChange( + vec![ + UintAuthorityId(2).into(), + UintAuthorityId(4).into(), + UintAuthorityId(5).into() + ] + ), + ], + }); + }); +} + #[test] fn authorities_change_is_not_logged_when_not_changed() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialise(&1, &Default::default(), &Default::default()); - Consensus::on_finalise(1); - let header = System::finalise(); + System::initialize(&1, &Default::default(), &Default::default()); + Consensus::on_finalize(1); + let header = System::finalize(); assert_eq!(header.digest, testing::Digest { logs: vec![], }); @@ -59,11 +80,11 @@ fn authorities_change_is_not_logged_when_not_changed() { #[test] fn authorities_change_is_not_logged_when_changed_back_to_original() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialise(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default()); Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]); Consensus::set_authorities(&[UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - Consensus::on_finalise(1); - let header = System::finalise(); + Consensus::on_finalize(1); + let header = System::finalize(); assert_eq!(header.digest, testing::Digest { logs: vec![], }); @@ -73,7 +94,7 @@ fn authorities_change_is_not_logged_when_changed_back_to_original() { #[test] fn offline_report_can_be_excluded() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialise(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default()); assert!(Consensus::create_inherent(&InherentData::new()).is_none()); let offline_report: Vec = vec![0]; @@ -83,3 +104,28 @@ fn offline_report_can_be_excluded() { assert!(Consensus::create_inherent(&data).is_some()); }); } + +#[test] +fn set_and_kill_storage_work() { + use srml_support::storage; + + with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { + System::initialize(&1, &Default::default(), &Default::default()); + + let item = (vec![42u8], vec![42u8]); + + Consensus::set_storage(vec![item.clone()]).unwrap(); + + assert_eq!( + storage::unhashed::get_raw(&item.0), + Some(item.1), + ); + + Consensus::kill_storage(vec![item.0.clone()]).unwrap(); + + assert_eq!( + storage::unhashed::get_raw(&item.0), + None, + ); + }); +} diff --git a/srml/contract/Cargo.toml b/srml/contract/Cargo.toml index 05d9a8e6169a523523028bb3d8b215f95699b9bc..ae91f6632d69b0be8ca269efcebc2515bab0cbd4 100644 --- a/srml/contract/Cargo.toml +++ b/srml/contract/Cargo.toml @@ -5,10 +5,10 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } pwasm-utils = { version = "0.6.1", default-features = false } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } parity-wasm = { version = "0.31", default-features = false } substrate-primitives = { path = "../../core/primitives", default-features = false } runtime-primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } @@ -17,32 +17,29 @@ rstd = { package = "sr-std", path = "../../core/sr-std", default-features = fals sandbox = { package = "sr-sandbox", path = "../../core/sr-sandbox", default-features = false } srml-support = { path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } -balances = { package = "srml-balances", path = "../balances", default-features = false } timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } -fees = { package = "srml-fees", path = "../fees", default-features = false } [dev-dependencies] wabt = "~0.7.4" assert_matches = "1.1" hex-literal = "0.1.0" consensus = { package = "srml-consensus", path = "../consensus" } +balances = { package = "srml-balances", path = "../balances" } [features] default = ["std"] std = [ - "serde/std", + "serde", "serde_derive", "parity-codec/std", "substrate-primitives/std", "runtime-primitives/std", "runtime-io/std", "rstd/std", - "balances/std", "sandbox/std", "srml-support/std", "system/std", "timestamp/std", "parity-wasm/std", "pwasm-utils/std", - "fees/std", ] diff --git a/srml/contract/src/account_db.rs b/srml/contract/src/account_db.rs index 17249f7db39a7d53fd4668951c86e4235d92d592..6b5142b6c82ed658aedb97d5812bc1a85a17ce26 100644 --- a/srml/contract/src/account_db.rs +++ b/srml/contract/src/account_db.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,15 +16,18 @@ //! Auxilliaries to help with managing partial changes to accounts state. -use super::{CodeHash, CodeHashOf, StorageOf, Trait}; -use {balances, system}; +use super::{CodeHash, CodeHashOf, Trait, AccountInfo, TrieId, AccountInfoOf, BalanceOf}; +use system; use rstd::cell::RefCell; +use rstd::rc::Rc; use rstd::collections::btree_map::{BTreeMap, Entry}; use rstd::prelude::*; -use srml_support::{StorageMap, StorageDoubleMap, traits::UpdateBalanceOutcome}; +use runtime_primitives::traits::Zero; +use srml_support::{StorageMap, traits::{UpdateBalanceOutcome, + SignedImbalance, Currency, Imbalance}, storage::child}; pub struct ChangeEntry { - balance: Option, + balance: Option>, /// In the case the outer option is None, the code_hash remains untouched, while providing `Some(None)` signifies a removing of the code in question code: Option>>, storage: BTreeMap, Option>>, @@ -43,33 +46,87 @@ impl Default for ChangeEntry { pub type ChangeSet = BTreeMap<::AccountId, ChangeEntry>; +#[derive(Clone, Default)] +pub struct AccountTrieIdMapping { + to_account: BTreeMap, + to_key: BTreeMap, + // this lock is related to the way overlaydb stack + // if set it must be unset at the lower level + lock: bool, +} + +impl AccountTrieIdMapping { + + pub fn new() -> Self { + AccountTrieIdMapping { + to_account: BTreeMap::new(), + to_key: BTreeMap::new(), + lock: false, + } + } + + pub fn lock(&mut self) { + self.lock = true; + } + pub fn unlock(&mut self) { + self.lock = false; + } + pub fn insert(&mut self, account: A, ks: TrieId) { + self.to_account.insert(ks.clone(), account.clone()); + self.to_key.insert(account, ks); + } + pub fn get_trieid(&self, account: &A) -> Option<&TrieId> { + if self.lock { return None } + self.to_key.get(account) + } + pub fn get_account(&self, ks: &TrieId) -> Option<&A> { + if self.lock { return None } + self.to_account.get(ks) + } + +} + pub trait AccountDb { - fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option>; + fn get_account_info(&self, account: &T::AccountId) -> Option; + fn get_or_create_trieid(&self, account: &T::AccountId) -> TrieId; + fn get_storage(&self, trie_id: &TrieId, location: &[u8]) -> Option>; fn get_code(&self, account: &T::AccountId) -> Option>; - fn get_balance(&self, account: &T::AccountId) -> T::Balance; + fn get_balance(&self, account: &T::AccountId) -> BalanceOf; fn commit(&mut self, change_set: ChangeSet); } pub struct DirectAccountDb; impl AccountDb for DirectAccountDb { - fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { - >::get(account, &location.to_vec()) + fn get_account_info(&self, account: &T::AccountId) -> Option { + let res: Option = AccountInfoOf::::get(account); + res + } + fn get_or_create_trieid(&self, account: &T::AccountId) -> TrieId { + use super::TrieIdGenerator; + >::get_account_info(self, account) + .map(|s|s.trie_id) + .unwrap_or_else(||::TrieIdGenerator::trie_id(account)) + } + fn get_storage(&self, trie_id: &TrieId, location: &[u8]) -> Option> { + child::get_raw(trie_id, location) } fn get_code(&self, account: &T::AccountId) -> Option> { >::get(account) } - fn get_balance(&self, account: &T::AccountId) -> T::Balance { - balances::Module::::free_balance(account) + fn get_balance(&self, account: &T::AccountId) -> BalanceOf { + T::Currency::free_balance(account) } fn commit(&mut self, s: ChangeSet) { + let mut total_imbalance = SignedImbalance::zero(); for (address, changed) in s.into_iter() { + let trieid = >::get_or_create_trieid(&self, &address); if let Some(balance) = changed.balance { - if let UpdateBalanceOutcome::AccountKilled = - balances::Module::::set_free_balance_creating(&address, balance) - { + let (imbalance, outcome) = T::Currency::make_free_balance_be(&address, balance); + total_imbalance = total_imbalance.merge(imbalance); + if let UpdateBalanceOutcome::AccountKilled = outcome { // Account killed. This will ultimately lead to calling `OnFreeBalanceZero` callback - // which will make removal of CodeHashOf and StorageOf for this account. + // which will make removal of CodeHashOf and AccountStorage for this account. // In order to avoid writing over the deleted properties we `continue` here. continue; } @@ -83,27 +140,48 @@ impl AccountDb for DirectAccountDb { } for (k, v) in changed.storage.into_iter() { if let Some(value) = v { - >::insert(&address, &k, value); + child::put_raw(&trieid[..], &k, &value[..]); } else { - >::remove(&address, &k); + child::kill(&trieid[..], &k); } } } + + match total_imbalance { + // If we've detected a positive imbalance as a result of our contract-level machinations + // then it's indicative of a buggy contracts system. + // Panicking is far from ideal as it opens up a DoS attack on block validators, however + // it's a less bad option than allowing arbitrary value to be created. + SignedImbalance::Positive(ref p) if !p.peek().is_zero() => + panic!("contract subsystem resulting in positive imbalance!"), + _ => {} + } } } - pub struct OverlayAccountDb<'a, T: Trait + 'a> { local: RefCell>, + trie_account: Rc::AccountId>>>, + trie_account_cache: bool, underlying: &'a AccountDb, } impl<'a, T: Trait> OverlayAccountDb<'a, T> { - pub fn new(underlying: &'a AccountDb) -> OverlayAccountDb<'a, T> { + pub fn new( + underlying: &'a AccountDb, + trie_account: Rc::AccountId>>>, + trie_account_cache: bool, + ) -> OverlayAccountDb<'a, T> { OverlayAccountDb { local: RefCell::new(ChangeSet::new()), + trie_account, + trie_account_cache, underlying, } } + pub fn reg_cache_new_rc(&self) -> Rc::AccountId>>> { + self.trie_account.clone() + } + pub fn into_change_set(self) -> ChangeSet { self.local.into_inner() } @@ -114,13 +192,13 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { location: Vec, value: Option>, ) { - self.local - .borrow_mut() + self.local.borrow_mut() .entry(account.clone()) .or_insert(Default::default()) .storage .insert(location, value); } + pub fn set_code(&mut self, account: &T::AccountId, code: Option>) { self.local .borrow_mut() @@ -128,7 +206,7 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { .or_insert(Default::default()) .code = Some(code); } - pub fn set_balance(&mut self, account: &T::AccountId, balance: T::Balance) { + pub fn set_balance(&mut self, account: &T::AccountId, balance: BalanceOf) { self.local .borrow_mut() .entry(account.clone()) @@ -138,13 +216,39 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { } impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { - fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { - self.local + fn get_account_info(&self, account: &T::AccountId) -> Option { + let v = self.underlying.get_account_info(account); + if self.trie_account_cache { + v.as_ref().map(|v|self.trie_account.as_ref().borrow_mut().insert(account.clone(), v.trie_id.clone())); + } + v + } + fn get_or_create_trieid(&self, account: &T::AccountId) -> TrieId { + if self.trie_account_cache { + let mut ka_mut = self.trie_account.as_ref().borrow_mut(); + if let Some(v) = ka_mut.get_trieid(account) { + v.clone() + } else { + ka_mut.unlock(); + let v = self.underlying.get_or_create_trieid(account); + ka_mut.insert(account.clone(), v.clone()); + v + } + } else { + let res = self.trie_account.as_ref().borrow().get_trieid(account).map(|v|v.clone()); + res.unwrap_or_else(|| { + self.trie_account.as_ref().borrow_mut().lock(); + self.underlying.get_or_create_trieid(account) + }) + } + } + fn get_storage(&self, ks: &TrieId, location: &[u8]) -> Option> { + self.trie_account.as_ref().borrow().get_account(ks).and_then(|account| self.local .borrow() - .get(account) + .get(&account) .and_then(|a| a.storage.get(location)) .cloned() - .unwrap_or_else(|| self.underlying.get_storage(account, location)) + .unwrap_or_else(|| self.underlying.get_storage(ks, location))) } fn get_code(&self, account: &T::AccountId) -> Option> { self.local @@ -153,7 +257,7 @@ impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { .and_then(|a| a.code.clone()) .unwrap_or_else(|| self.underlying.get_code(account)) } - fn get_balance(&self, account: &T::AccountId) -> T::Balance { + fn get_balance(&self, account: &T::AccountId) -> BalanceOf { self.local .borrow() .get(account) diff --git a/srml/contract/src/exec.rs b/srml/contract/src/exec.rs index 046d1075337aa48bc6905b85bccd648e7511687b..afd5159fced8489ff6b931d69513565d81c85030 100644 --- a/srml/contract/src/exec.rs +++ b/srml/contract/src/exec.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,16 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use super::{CodeHash, Config, ContractAddressFor, Event, RawEvent, Trait}; -use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}; +use super::{CodeHash, Config, ContractAddressFor, Event, RawEvent, Trait, TrieId, BalanceOf}; +use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb, AccountTrieIdMapping}; use crate::gas::{GasMeter, Token, approx_gas_for_balance}; use rstd::prelude::*; +use rstd::cell::RefCell; +use rstd::rc::Rc; use runtime_primitives::traits::{CheckedAdd, CheckedSub, Zero}; +use srml_support::traits::{WithdrawReason, Currency}; use timestamp; -use srml_support::traits::EnsureAccountLiquid; -pub type BalanceOf = ::Balance; pub type AccountIdOf = ::AccountId; pub type CallOf = ::Call; pub type MomentOf = ::Moment; @@ -43,7 +44,7 @@ pub struct CallReceipt { /// An interface that provides access to the external environment in which the /// smart-contract is executed. /// -/// This interface is specialised to an account of the executing code, so all +/// This interface is specialized to an account of the executing code, so all /// operations are implicitly performed on that account. pub trait Ext { type T: Trait; @@ -225,6 +226,7 @@ impl Token for ExecFeeToken { pub struct ExecutionContext<'a, T: Trait + 'a, V, L> { pub self_account: T::AccountId, + pub self_trieid: TrieId, pub overlay: OverlayAccountDb<'a, T>, pub depth: usize, pub events: Vec>, @@ -244,9 +246,11 @@ where /// /// The specified `origin` address will be used as `sender` for pub fn top_level(origin: T::AccountId, cfg: &'a Config, vm: &'a V, loader: &'a L) -> Self { - let overlay = OverlayAccountDb::::new(&DirectAccountDb); + let overlay = OverlayAccountDb::::new(&DirectAccountDb, Rc::new(RefCell::new(AccountTrieIdMapping::new())), true); + let self_trieid = overlay.get_or_create_trieid(&origin); ExecutionContext { self_account: origin, + self_trieid, depth: 0, overlay, events: Vec::new(), @@ -258,9 +262,11 @@ where } fn nested(&self, overlay: OverlayAccountDb<'a, T>, dest: T::AccountId) -> Self { + let self_trieid = overlay.get_or_create_trieid(&dest); ExecutionContext { - overlay: overlay, + overlay, self_account: dest, + self_trieid, depth: self.depth + 1, events: Vec::new(), calls: Vec::new(), @@ -274,7 +280,7 @@ where pub fn call( &mut self, dest: T::AccountId, - value: T::Balance, + value: BalanceOf, gas_meter: &mut GasMeter, input_data: &[u8], empty_output_buf: EmptyOutputBuf, @@ -295,11 +301,11 @@ where let (change_set, events, calls) = { let mut nested = self.nested( - OverlayAccountDb::new(&self.overlay), + OverlayAccountDb::new(&self.overlay, self.overlay.reg_cache_new_rc(), false), dest.clone() ); - if value > T::Balance::zero() { + if value > BalanceOf::::zero() { transfer( gas_meter, TransferCause::Call, @@ -342,7 +348,7 @@ where pub fn instantiate( &mut self, - endowment: T::Balance, + endowment: BalanceOf, gas_meter: &mut GasMeter, code_hash: &CodeHash, input_data: &[u8], @@ -370,7 +376,8 @@ where } let (change_set, events, calls) = { - let mut overlay = OverlayAccountDb::new(&self.overlay); + let mut overlay = OverlayAccountDb::new(&self.overlay, self.overlay.reg_cache_new_rc(), false); + overlay.set_code(&dest, Some(code_hash.clone())); let mut nested = self.nested(overlay, dest.clone()); @@ -431,7 +438,7 @@ pub struct TransferFeeToken { gas_price: Balance, } -impl Token for TransferFeeToken { +impl Token for TransferFeeToken> { type Metadata = Config; #[inline] @@ -460,7 +467,7 @@ enum TransferCause { /// (transfering endowment) or because of a transfer via `call`. This /// is specified using the `cause` parameter. /// -/// NOTE: that the fee is denominated in `T::Balance` units, but +/// NOTE: that the fee is denominated in `BalanceOf` units, but /// charged in `T::Gas` from the provided `gas_meter`. This means /// that the actual amount charged might differ. /// @@ -472,7 +479,7 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( cause: TransferCause, transactor: &T::AccountId, dest: &T::AccountId, - value: T::Balance, + value: BalanceOf, ctx: &mut ExecutionContext<'a, T, V, L>, ) -> Result<(), &'static str> { use self::TransferCause::*; @@ -520,7 +527,7 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( if would_create && value < ctx.config.existential_deposit { return Err("value too low to create account"); } - ::EnsureAccountLiquid::ensure_account_liquid(transactor)?; + T::Currency::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer, new_from_balance)?; let new_to_balance = match to_balance.checked_add(&value) { Some(b) => b, @@ -540,7 +547,7 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( struct CallContext<'a, 'b: 'a, T: Trait + 'b, V: Vm + 'b, L: Loader> { ctx: &'a mut ExecutionContext<'b, T, V, L>, caller: T::AccountId, - value_transferred: T::Balance, + value_transferred: BalanceOf, timestamp: T::Moment, random_seed: T::Hash, } @@ -554,7 +561,7 @@ where type T = T; fn get_storage(&self, key: &[u8]) -> Option> { - self.ctx.overlay.get_storage(&self.ctx.self_account, key) + self.ctx.overlay.get_storage(&self.ctx.self_trieid, key) } fn set_storage(&mut self, key: &[u8], value: Option>) { @@ -566,7 +573,7 @@ where fn instantiate( &mut self, code_hash: &CodeHash, - endowment: T::Balance, + endowment: BalanceOf, gas_meter: &mut GasMeter, input_data: &[u8], ) -> Result>, &'static str> { @@ -576,7 +583,7 @@ where fn call( &mut self, to: &T::AccountId, - value: T::Balance, + value: BalanceOf, gas_meter: &mut GasMeter, input_data: &[u8], empty_output_buf: EmptyOutputBuf, @@ -600,11 +607,11 @@ where &self.caller } - fn balance(&self) -> T::Balance { + fn balance(&self) -> BalanceOf { self.ctx.overlay.get_balance(&self.ctx.self_account) } - fn value_transferred(&self) -> T::Balance { + fn value_transferred(&self) -> BalanceOf { self.value_transferred } @@ -639,9 +646,9 @@ mod tests { use crate::{CodeHash, Config}; use runtime_io::with_externalities; use std::cell::RefCell; + use std::rc::Rc; use std::collections::HashMap; use std::marker::PhantomData; - use std::rc::Rc; use assert_matches::assert_matches; const ALICE: u64 = 1; diff --git a/srml/contract/src/gas.rs b/srml/contract/src/gas.rs index 0c9b422a67ba2a9205797e631cb80c55494ca92d..54199042bccb8ff9507d73b065c595c5c406c89f 100644 --- a/srml/contract/src/gas.rs +++ b/srml/contract/src/gas.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,11 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::{GasSpent, Module, Trait}; -use balances; +use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf}; use runtime_primitives::BLOCK_FULL; use runtime_primitives::traits::{As, CheckedMul, CheckedSub, Zero}; -use srml_support::StorageValue; +use srml_support::{StorageValue, traits::{OnUnbalanced, ExistenceRequirement, WithdrawReason, Currency, Imbalance}}; #[cfg(test)] use std::{any::Any, fmt::Debug}; @@ -83,14 +82,14 @@ pub struct GasMeter { limit: T::Gas, /// Amount of gas left from initial gas limit. Can reach zero. gas_left: T::Gas, - gas_price: T::Balance, + gas_price: BalanceOf, #[cfg(test)] tokens: Vec, } impl GasMeter { #[cfg(test)] - pub fn with_limit(gas_limit: T::Gas, gas_price: T::Balance) -> GasMeter { + pub fn with_limit(gas_limit: T::Gas, gas_price: BalanceOf) -> GasMeter { GasMeter { limit: gas_limit, gas_left: gas_limit, @@ -175,7 +174,7 @@ impl GasMeter { } } - pub fn gas_price(&self) -> T::Balance { + pub fn gas_price(&self) -> BalanceOf { self.gas_price } @@ -202,7 +201,7 @@ impl GasMeter { pub fn buy_gas( transactor: &T::AccountId, gas_limit: T::Gas, -) -> Result, &'static str> { +) -> Result<(GasMeter, NegativeImbalanceOf), &'static str> { // Check if the specified amount of gas is available in the current block. // This cannot underflow since `gas_spent` is never greater than `block_gas_limit`. let gas_available = >::block_gas_limit() - >::gas_spent(); @@ -213,47 +212,54 @@ pub fn buy_gas( // Buy the specified amount of gas. let gas_price = >::gas_price(); - let b = >::free_balance(transactor); - let cost = >::as_(gas_limit.clone()) + let cost = >>::as_(gas_limit.clone()) .checked_mul(&gas_price) .ok_or("overflow multiplying gas limit by price")?; - let new_balance = b.checked_sub(&cost); - if new_balance < Some(>::existential_deposit()) { - return Err("not enough funds for transaction fee"); - } + let imbalance = T::Currency::withdraw( + transactor, + cost, + WithdrawReason::Fee, + ExistenceRequirement::KeepAlive + )?; - >::set_free_balance(transactor, b - cost); - >::decrease_total_stake_by(cost); - Ok(GasMeter { + Ok((GasMeter { limit: gas_limit, gas_left: gas_limit, gas_price, + #[cfg(test)] tokens: Vec::new(), - }) + }, imbalance)) } /// Refund the unused gas. -pub fn refund_unused_gas(transactor: &T::AccountId, gas_meter: GasMeter) { +pub fn refund_unused_gas( + transactor: &T::AccountId, + gas_meter: GasMeter, + imbalance: NegativeImbalanceOf, +) { + let gas_spent = gas_meter.spent(); + let gas_left = gas_meter.gas_left(); + // Increase total spent gas. // This cannot overflow, since `gas_spent` is never greater than `block_gas_limit`, which // also has T::Gas type. - let gas_spent = >::gas_spent() + gas_meter.spent(); - >::put(gas_spent); + >::mutate(|block_gas_spent| *block_gas_spent += gas_spent); // Refund gas left by the price it was bought. - let b = >::free_balance(transactor); - let refund = >::as_(gas_meter.gas_left) * gas_meter.gas_price; - >::set_free_balance(transactor, b + refund); - >::increase_total_stake_by(refund); + let refund = >>::as_(gas_left) * gas_meter.gas_price; + let refund_imbalance = T::Currency::deposit_creating(transactor, refund); + if let Ok(imbalance) = imbalance.offset(refund_imbalance) { + T::GasPayment::on_unbalanced(imbalance); + } } /// A little handy utility for converting a value in balance units into approximitate value in gas units /// at the given gas price. -pub fn approx_gas_for_balance(gas_price: T::Balance, balance: T::Balance) -> T::Gas { - let amount_in_gas: T::Balance = balance / gas_price; - >::sa(amount_in_gas) +pub fn approx_gas_for_balance(gas_price: BalanceOf, balance: BalanceOf) -> T::Gas { + let amount_in_gas: BalanceOf = balance / gas_price; + >>::sa(amount_in_gas) } /// A simple utility macro that helps to match against a diff --git a/srml/contract/src/lib.rs b/srml/contract/src/lib.rs index 0fa88400e6367e65656503ee2965f19d4f8fd396..da3fe4dbf0be3edb46dec4cd130428ce54dcdccc 100644 --- a/srml/contract/src/lib.rs +++ b/srml/contract/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,41 +14,71 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Smart-contract module for runtime; Allows deployment and execution of smart-contracts -//! expressed in WebAssembly. +//! # Contract Module //! -//! This module provides an ability to create smart-contract accounts and send them messages. -//! A smart-contract is an account with associated code and storage. When such an account receives a message, -//! the code associated with that account gets executed. +//! The contract module provides functionality for the runtime to deploy and execute WebAssembly smart-contracts. +//! The supported dispatchable functions are documented as part of the [`Call`](./enum.Call.html) enum. //! -//! The code is allowed to alter the storage entries of the associated account, -//! create smart-contracts or send messages to existing smart-contracts. +//! ## Overview //! -//! For any actions invoked by the smart-contracts fee must be paid. The fee is paid in gas. -//! Gas is bought upfront up to the, specified in transaction, limit. Any unused gas is refunded -//! after the transaction (regardless of the execution outcome). If all gas is used, -//! then changes made for the specific call or create are reverted (including balance transfers). +//! This module extends accounts (see `Balances` module) to have smart-contract functionality. +//! These "smart-contract accounts" have the ability to create smart-contracts and make calls to other contract +//! and non-contract accounts. //! -//! Failures are typically not cascading. That, for example, means that if contract A calls B and B errors -//! somehow, then A can decide if it should proceed or error. +//! The smart-contract code is stored once in a `code_cache`, and later retrievable via its `code_hash`. +//! This means that multiple smart-contracts can be instantiated from the same `code_cache`, without replicating +//! the code each time. //! -//! # Interaction with the system +//! When a smart-contract is called, its associated code is retrieved via the code hash and gets executed. +//! This call can alter the storage entries of the smart-contract account, create new smart-contracts, +//! or call other smart-contracts. //! -//! ## Finalization +//! Finally, when the `Balances` module determines an account is dead (i.e. account balance fell below the +//! existential deposit), it reaps the account. This will delete the associated code and storage of the +//! smart-contract account. //! -//! This module requires performing some finalization steps at the end of the block. If not performed -//! the module will have incorrect behavior. +//! ### Gas //! -//! Thus [`Module::on_finalise`] must be called at the end of the block. The order in relation to -//! the other module doesn't matter. +//! Senders must specify a gas limit with every call, as all instructions invoked by the smart-contract require gas. +//! Unused gas is refunded after the call, regardless of the execution outcome. //! -//! ## Account killing +//! If the gas limit is reached, then all calls and state changes (including balance transfers) are only +//! reverted at the current call's contract level. For example, if contract A calls B and B runs out of gas mid-call, +//! then all of B's calls are reverted. Assuming correct error handling by contract A, A's other calls and state +//! changes still persist. //! -//! When `staking` module determines that account is dead (e.g. account's balance fell below -//! exsistential deposit) then it reaps the account. That will lead to deletion of the associated -//! code and storage of the account. +//! ### Notable Scenarios +//! +//! Contract call failures are not always cascading. When failures occur in a sub-call, they do not "bubble up", +//! and the call will only revert at the specific contract level. For example, if contract A calls contract B, and B +//! fails, A can decide how to handle that failure, either proceeding or reverting A's changes. +//! +//! ## Interface +//! +//! ### Dispatchable functions +//! +//! * `put_code` - Stores the given binary Wasm code into the chains storage and returns its `code_hash`. +//! +//! * `create` - Deploys a new contract from the given `code_hash`, optionally transferring some balance. +//! This creates a new smart contract account and calls its contract deploy handler to initialize the contract. +//! +//! * `call` - Makes a call to an account, optionally transferring some balance. +//! +//! ### Public functions +//! +//! See the [module](./struct.Module.html) for details on publicly available functions. +//! +//! ## Usage +//! +//! The contract module is a work in progress. The following examples show how this contract module can be +//! used to create and call contracts. +//! +//! * [`pDSL`](https://github.com/Robbepop/pdsl) is a domain specific language which enables writing +//! WebAssembly based smart contracts in the Rust programming language. This is a work in progress. +//! +//! ## Related Modules +//! * [`Balances`](https://crates.parity.io/srml_balances/index.html) //! -//! [`Module::on_finalise`]: struct.Module.html#impl-OnFinalise #![cfg_attr(not(feature = "std"), no_std)] @@ -63,26 +93,26 @@ mod wasm; mod tests; use crate::exec::ExecutionContext; -use crate::account_db::AccountDb; +use crate::account_db::{AccountDb, DirectAccountDb}; #[cfg(feature = "std")] use serde_derive::{Serialize, Deserialize}; +use substrate_primitives::crypto::UncheckedFrom; use rstd::prelude::*; use rstd::marker::PhantomData; use parity_codec::{Codec, Encode, Decode}; use runtime_primitives::traits::{Hash, As, SimpleArithmetic,Bounded, StaticLookup}; use srml_support::dispatch::{Result, Dispatchable}; -use srml_support::{Parameter, StorageMap, StorageValue, StorageDoubleMap, decl_module, decl_event, decl_storage}; -use srml_support::traits::OnFreeBalanceZero; +use srml_support::{Parameter, StorageMap, StorageValue, decl_module, decl_event, decl_storage, storage::child}; +use srml_support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency}; use system::{ensure_signed, RawOrigin}; -use runtime_io::{blake2_256, twox_128}; use timestamp; -use fees; pub type CodeHash = ::Hash; +pub type TrieId = Vec; /// A function that generates an `AccountId` for a contract upon instantiation. -pub trait ContractAddressFor { +pub trait ContractAddressFor { fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &AccountId) -> AccountId; } @@ -91,7 +121,54 @@ pub trait ComputeDispatchFee { fn compute_dispatch_fee(call: &Call) -> Balance; } -pub trait Trait: fees::Trait + balances::Trait + timestamp::Trait { +#[derive(Encode,Decode,Clone,Debug)] +/// Information for managing an acocunt and its sub trie abstraction. +/// This is the required info to cache for an account +pub struct AccountInfo { + /// unique ID for the subtree encoded as a byte + pub trie_id: TrieId, + /// the size of stored value in octet + pub current_mem_stored: u64, +} + +/// Get a trie id (trie id must be unique and collision resistant depending upon its context) +/// Note that it is different than encode because trie id should have collision resistance +/// property (being a proper uniqueid). +pub trait TrieIdGenerator { + /// get a trie id for an account, using reference to parent account trie id to ensure + /// uniqueness of trie id + /// The implementation must ensure every new trie id is unique: two consecutive call with the + /// same parameter needs to return different trie id values. + fn trie_id(account_id: &AccountId) -> TrieId; +} + +/// Get trie id from `account_id` +pub struct TrieIdFromParentCounter(PhantomData); + +/// This generator use inner counter for account id and apply hash over `AccountId + +/// accountid_counter` +impl TrieIdGenerator for TrieIdFromParentCounter +where + T::AccountId: AsRef<[u8]> +{ + fn trie_id(account_id: &T::AccountId) -> TrieId { + // note that skipping a value due to error is not an issue here. + // we only need uniqueness, not sequence. + let new_seed = >::mutate(|v| v.wrapping_add(1)); + + let mut buf = Vec::new(); + buf.extend_from_slice(account_id.as_ref()); + buf.extend_from_slice(&new_seed.to_le_bytes()[..]); + T::Hashing::hash(&buf[..]).as_ref().into() + } +} + +pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: timestamp::Trait { + type Currency: Currency; + /// The outer call dispatch type. type Call: Parameter + Dispatchable::Origin>; @@ -99,7 +176,7 @@ pub trait Trait: fees::Trait + balances::Trait + timestamp::Trait { type Event: From> + Into<::Event>; // As is needed for wasm-utils - type Gas: Parameter + Default + Codec + SimpleArithmetic + Bounded + Copy + As + As + As; + type Gas: Parameter + Default + Codec + SimpleArithmetic + Bounded + Copy + As> + As + As; /// A function type to get the contract address given the creator. type DetermineContractAddress: ContractAddressFor, Self::AccountId>; @@ -108,7 +185,13 @@ pub trait Trait: fees::Trait + balances::Trait + timestamp::Trait { /// /// It is recommended (though not required) for this function to return a fee that would be taken /// by executive module for regular dispatch. - type ComputeDispatchFee: ComputeDispatchFee::Balance>; + type ComputeDispatchFee: ComputeDispatchFee>; + + /// trieid id generator + type TrieIdGenerator: TrieIdGenerator; + + /// Handler for the unbalanced reduction when making a gas payment. + type GasPayment: OnUnbalanced>; } /// Simple contract address determintator. @@ -120,7 +203,7 @@ pub trait Trait: fees::Trait + balances::Trait + timestamp::Trait { pub struct SimpleAddressDeterminator(PhantomData); impl ContractAddressFor, T::AccountId> for SimpleAddressDeterminator where - T::AccountId: From + AsRef<[u8]> + T::AccountId: UncheckedFrom + AsRef<[u8]> { fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &T::AccountId) -> T::AccountId { let data_hash = T::Hashing::hash(data); @@ -130,19 +213,19 @@ where buf.extend_from_slice(data_hash.as_ref()); buf.extend_from_slice(origin.as_ref()); - T::Hashing::hash(&buf[..]).into() + UncheckedFrom::unchecked_from(T::Hashing::hash(&buf[..])) } } /// The default dispatch fee computor computes the fee in the same way that -/// implementation of `ChargeBytesFee` for fees module does. +/// implementation of `MakePayment` for balances module does. pub struct DefaultDispatchFeeComputor(PhantomData); -impl ComputeDispatchFee for DefaultDispatchFeeComputor { - fn compute_dispatch_fee(call: &T::Call) -> T::Balance { +impl ComputeDispatchFee> for DefaultDispatchFeeComputor { + fn compute_dispatch_fee(call: &T::Call) -> BalanceOf { let encoded_len = call.using_encoded(|encoded| encoded.len()); - let base_fee = >::transaction_base_fee(); - let byte_fee = >::transaction_byte_fee(); - >::sa(base_fee.as_() + byte_fee.as_() * encoded_len as u64) + let base_fee = >::transaction_base_fee(); + let byte_fee = >::transaction_byte_fee(); + base_fee + byte_fee * as As>::sa(encoded_len as u64) } } @@ -165,7 +248,8 @@ decl_module! { Ok(()) } - /// Stores code in the storage. You can instantiate contracts only with stored code. + /// Stores the given binary Wasm code into the chains storage and returns its `codehash`. + /// You can instantiate contracts only with stored code. fn put_code( origin, #[compact] gas_limit: T::Gas, @@ -174,23 +258,29 @@ decl_module! { let origin = ensure_signed(origin)?; let schedule = >::current_schedule(); - let mut gas_meter = gas::buy_gas::(&origin, gas_limit)?; + let (mut gas_meter, imbalance) = gas::buy_gas::(&origin, gas_limit)?; let result = wasm::save_code::(code, &mut gas_meter, &schedule); if let Ok(code_hash) = result { Self::deposit_event(RawEvent::CodeStored(code_hash)); } - gas::refund_unused_gas::(&origin, gas_meter); + gas::refund_unused_gas::(&origin, gas_meter, imbalance); result.map(|_| ()) } - /// Make a call to a specified account, optionally transferring some balance. + /// Makes a call to an account, optionally transferring some balance. + /// + /// * If the account is a smart-contract account, the associated code will be + /// executed and any value will be transferred. + /// * If the account is a regular account, any value will be transferred. + /// * If no account exists and the call value is not less than `existential_deposit`, + /// a regular account will be created and any value will be transferred. fn call( origin, dest: ::Source, - #[compact] value: T::Balance, + #[compact] value: BalanceOf, #[compact] gas_limit: T::Gas, data: Vec ) -> Result { @@ -201,7 +291,7 @@ decl_module! { // // NOTE: it is very important to avoid any state changes before // paying for the gas. - let mut gas_meter = gas::buy_gas::(&origin, gas_limit)?; + let (mut gas_meter, imbalance) = gas::buy_gas::(&origin, gas_limit)?; let cfg = Config::preload(); let vm = crate::wasm::WasmVm::new(&cfg.schedule); @@ -212,7 +302,7 @@ decl_module! { if let Ok(_) = result { // Commit all changes that made it thus far into the persistant storage. - account_db::DirectAccountDb.commit(ctx.overlay.into_change_set()); + DirectAccountDb.commit(ctx.overlay.into_change_set()); // Then deposit all events produced. ctx.events.into_iter().for_each(Self::deposit_event); @@ -222,7 +312,7 @@ decl_module! { // // NOTE: this should go after the commit to the storage, since the storage changes // can alter the balance of the caller. - gas::refund_unused_gas::(&origin, gas_meter); + gas::refund_unused_gas::(&origin, gas_meter, imbalance); // Dispatch every recorded call with an appropriate origin. ctx.calls.into_iter().for_each(|(who, call)| { @@ -233,29 +323,30 @@ decl_module! { result.map(|_| ()) } - /// Create a new contract, optionally transfering some balance to the created account. + /// Creates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance. /// /// Creation is executed as follows: /// /// - the destination address is computed based on the sender and hash of the code. - /// - account is created at the computed address. + /// - the smart-contract account is created at the computed address. /// - the `ctor_code` is executed in the context of the newly created account. Buffer returned /// after the execution is saved as the `code` of the account. That code will be invoked - /// upon any message received by this account. + /// upon any call received by this account. + /// - The contract is initialized. fn create( origin, - #[compact] endowment: T::Balance, + #[compact] endowment: BalanceOf, #[compact] gas_limit: T::Gas, code_hash: CodeHash, data: Vec ) -> Result { let origin = ensure_signed(origin)?; - // Pay for the gas upfront. + // Commit the gas upfront. // // NOTE: it is very important to avoid any state changes before // paying for the gas. - let mut gas_meter = gas::buy_gas::(&origin, gas_limit)?; + let (mut gas_meter, imbalance) = gas::buy_gas::(&origin, gas_limit)?; let cfg = Config::preload(); let vm = crate::wasm::WasmVm::new(&cfg.schedule); @@ -265,7 +356,7 @@ decl_module! { if let Ok(_) = result { // Commit all changes that made it thus far into the persistant storage. - account_db::DirectAccountDb.commit(ctx.overlay.into_change_set()); + DirectAccountDb.commit(ctx.overlay.into_change_set()); // Then deposit all events produced. ctx.events.into_iter().for_each(Self::deposit_event); @@ -275,7 +366,7 @@ decl_module! { // // NOTE: this should go after the commit to the storage, since the storage changes // can alter the balance of the caller. - gas::refund_unused_gas::(&origin, gas_meter); + gas::refund_unused_gas::(&origin, gas_meter, imbalance); // Dispatch every recorded call with an appropriate origin. ctx.calls.into_iter().for_each(|(who, call)| { @@ -286,7 +377,7 @@ decl_module! { result.map(|_| ()) } - fn on_finalise() { + fn on_finalize() { >::kill(); } } @@ -295,11 +386,11 @@ decl_module! { decl_event! { pub enum Event where - ::Balance, + Balance = BalanceOf, ::AccountId, ::Hash { - /// Transfer happened `from` -> `to` with given `value` as part of a `message-call` or `create`. + /// Transfer happened `from` to `to` with given `value` as part of a `call` or `create`. Transfer(AccountId, AccountId, Balance), /// Contract deployed by address at the specified address. @@ -319,14 +410,22 @@ decl_event! { decl_storage! { trait Store for Module as Contract { - /// The fee required to create a contract. At least as big as staking's ReclaimRebate. - ContractFee get(contract_fee) config(): T::Balance = T::Balance::sa(21); - /// The fee charged for a call into a contract. + /// The fee required to make a transfer. + TransferFee get(transfer_fee) config(): BalanceOf; + /// The fee required to create an account. + CreationFee get(creation_fee) config(): BalanceOf; + /// The fee to be paid for making a transaction; the base. + TransactionBaseFee get(transaction_base_fee) config(): BalanceOf; + /// The fee to be paid for making a transaction; the per-byte portion. + TransactionByteFee get(transaction_byte_fee) config(): BalanceOf; + /// The fee required to create a contract instance. + ContractFee get(contract_fee) config(): BalanceOf = BalanceOf::::sa(21); + /// The base fee charged for calling into a contract. CallBaseFee get(call_base_fee) config(): T::Gas = T::Gas::sa(135); - /// The fee charged for a create of a contract. + /// The base fee charged for creating a contract. CreateBaseFee get(create_base_fee) config(): T::Gas = T::Gas::sa(175); /// The price of one unit of gas. - GasPrice get(gas_price) config(): T::Balance = T::Balance::sa(1); + GasPrice get(gas_price) config(): BalanceOf = BalanceOf::::sa(1); /// The maximum nesting level of a call/create stack. MaxDepth get(max_depth) config(): u32 = 100; /// The maximum amount of gas that could be expended per block. @@ -341,34 +440,19 @@ decl_storage! { pub PristineCode: map CodeHash => Option>; /// A mapping between an original code hash and instrumented wasm code, ready for the execution. pub CodeStorage: map CodeHash => Option; - } -} - -/// The storage items associated with an account/key. -/// -pub(crate) struct StorageOf(rstd::marker::PhantomData); -impl StorageDoubleMap for StorageOf { - const PREFIX: &'static [u8] = b"con:sto:"; - type Key1 = T::AccountId; - type Key2 = Vec; - type Value = Vec; - - /// Hashed by XX - fn derive_key1(key1_data: Vec) -> Vec { - twox_128(&key1_data).to_vec() - } - - /// Blake2 is used for `Key2` is because it will be used as a key for contract's storage and - /// thus will be susceptible for a untrusted input. - fn derive_key2(key2_data: Vec) -> Vec { - blake2_256(&key2_data).to_vec() + /// The subtrie counter + pub AccountCounter: u64 = 0; + /// The code associated with a given account. + pub AccountInfoOf: map T::AccountId => Option; } } impl OnFreeBalanceZero for Module { fn on_free_balance_zero(who: &T::AccountId) { >::remove(who); - >::remove_prefix(who); + >::get_account_info(&DirectAccountDb, who).map(|subtrie| { + child::kill_storage(&subtrie.trie_id); + }); } } @@ -378,11 +462,11 @@ impl OnFreeBalanceZero for Module { /// course of transaction execution. pub struct Config { pub schedule: Schedule, - pub existential_deposit: T::Balance, + pub existential_deposit: BalanceOf, pub max_depth: u32, - pub contract_account_instantiate_fee: T::Balance, - pub account_create_fee: T::Balance, - pub transfer_fee: T::Balance, + pub contract_account_instantiate_fee: BalanceOf, + pub account_create_fee: BalanceOf, + pub transfer_fee: BalanceOf, pub call_base_fee: T::Gas, pub instantiate_base_fee: T::Gas, } @@ -391,11 +475,11 @@ impl Config { fn preload() -> Config { Config { schedule: >::current_schedule(), - existential_deposit: >::existential_deposit(), + existential_deposit: T::Currency::minimum_balance(), max_depth: >::max_depth(), contract_account_instantiate_fee: >::contract_fee(), - account_create_fee: >::creation_fee(), - transfer_fee: >::transfer_fee(), + account_create_fee: >::creation_fee(), + transfer_fee: >::transfer_fee(), call_base_fee: >::call_base_fee(), instantiate_base_fee: >::create_base_fee(), } diff --git a/srml/contract/src/tests.rs b/srml/contract/src/tests.rs index 1d1141c2f4acf8b93d005cf2414c2b07f4b17472..1c18329bf2e67a7f3639d890d9db0c5f2abc28a2 100644 --- a/srml/contract/src/tests.rs +++ b/srml/contract/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,17 +24,21 @@ use runtime_primitives::testing::{Digest, DigestItem, H256, Header, UintAuthorit use runtime_primitives::traits::{BlakeTwo256, IdentityLookup}; use runtime_primitives::BuildStorage; use runtime_io; -use srml_support::{StorageMap, StorageDoubleMap, assert_ok, impl_outer_event, impl_outer_dispatch, impl_outer_origin}; -use substrate_primitives::{Blake2Hasher}; +use srml_support::{storage::child, StorageMap, assert_ok, impl_outer_event, impl_outer_dispatch, + impl_outer_origin, traits::Currency}; +use substrate_primitives::Blake2Hasher; use system::{self, Phase, EventRecord}; -use fees; use {wabt, balances, consensus}; use hex_literal::*; use assert_matches::assert_matches; use crate::{ - ContractAddressFor, GenesisConfig, Module, RawEvent, StorageOf, - Trait, ComputeDispatchFee + ContractAddressFor, GenesisConfig, Module, RawEvent, + Trait, ComputeDispatchFee, TrieIdGenerator, TrieId, + AccountInfo, AccountInfoOf, }; +use substrate_primitives::storage::well_known_keys; +use parity_codec::{Encode, Decode, KeyedVec}; +use std::sync::atomic::{AtomicUsize, Ordering}; mod contract { // Re-export contents of the root. This basically @@ -45,7 +49,7 @@ mod contract { } impl_outer_event! { pub enum MetaEvent for Test { - balances, contract, fees, + balances, contract, } } impl_outer_origin! { @@ -68,7 +72,7 @@ impl system::Trait for Test { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; type Log = DigestItem; @@ -77,8 +81,10 @@ impl balances::Trait for Test { type Balance = u64; type OnFreeBalanceZero = Contract; type OnNewAccount = (); - type EnsureAccountLiquid = (); type Event = MetaEvent; + type TransactionPayment = (); + type DustRemoval = (); + type TransferPayment = (); } impl timestamp::Trait for Test { type Moment = u64; @@ -89,16 +95,15 @@ impl consensus::Trait for Test { type SessionKey = UintAuthorityId; type InherentOfflineReport = (); } -impl fees::Trait for Test { - type Event = MetaEvent; - type TransferAsset = Balances; -} impl Trait for Test { + type Currency = Balances; type Call = Call; type Gas = u64; type DetermineContractAddress = DummyContractAddressFor; type Event = MetaEvent; type ComputeDispatchFee = DummyComputeDispatchFee; + type TrieIdGenerator = DummyTrieIdGenerator; + type GasPayment = (); } type Balances = balances::Module; @@ -112,6 +117,17 @@ impl ContractAddressFor for DummyContractAddressFor { } } +static KEY_COUNTER: AtomicUsize = AtomicUsize::new(0); + +pub struct DummyTrieIdGenerator; +impl TrieIdGenerator for DummyTrieIdGenerator { + fn trie_id(account_id: &u64) -> TrieId { + let mut res = KEY_COUNTER.fetch_add(1, Ordering::Relaxed).to_le_bytes().to_vec(); + res.extend_from_slice(&account_id.to_le_bytes()); + res + } +} + pub struct DummyComputeDispatchFee; impl ComputeDispatchFee for DummyComputeDispatchFee { fn compute_dispatch_fee(call: &Call) -> u64 { @@ -169,6 +185,8 @@ impl ExtBuilder { .0; t.extend( balances::GenesisConfig:: { + transaction_base_fee: 0, + transaction_byte_fee: 0, balances: vec![], existential_deposit: self.existential_deposit, transfer_fee: self.transfer_fee, @@ -181,6 +199,10 @@ impl ExtBuilder { ); t.extend( GenesisConfig:: { + transaction_base_fee: 0, + transaction_byte_fee: 0, + transfer_fee: self.transfer_fee, + creation_fee: self.creation_fee, contract_fee: 21, call_base_fee: 135, create_base_fee: 175, @@ -200,8 +222,7 @@ impl ExtBuilder { #[test] fn refunds_unused_gas() { with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); + Balances::deposit_creating(&0, 100_000_000); assert_ok!(Contract::call( Origin::signed(0), @@ -217,24 +238,33 @@ fn refunds_unused_gas() { #[test] fn account_removal_removes_storage() { + let unique_id1 = b"unique_id1"; + let unique_id2 = b"unique_id2"; with_externalities( &mut ExtBuilder::default().existential_deposit(100).build(), || { - // Setup two accounts with free balance above than exsistential threshold. + // Set up two accounts with free balance above the existential threshold. { - Balances::set_free_balance(&1, 110); - Balances::increase_total_stake_by(110); - >::insert(&1, &b"foo".to_vec(), b"1".to_vec()); - >::insert(&1, &b"bar".to_vec(), b"2".to_vec()); - - Balances::set_free_balance(&2, 110); - Balances::increase_total_stake_by(110); - >::insert(&2, &b"hello".to_vec(), b"3".to_vec()); - >::insert(&2, &b"world".to_vec(), b"4".to_vec()); + Balances::deposit_creating(&1, 110); + AccountInfoOf::::insert(1, &AccountInfo { + trie_id: unique_id1.to_vec(), + current_mem_stored: 0, + }); + child::put(&unique_id1[..], &b"foo".to_vec(), &b"1".to_vec()); + assert_eq!(child::get(&unique_id1[..], &b"foo".to_vec()), Some(b"1".to_vec())); + child::put(&unique_id1[..], &b"bar".to_vec(), &b"2".to_vec()); + + Balances::deposit_creating(&2, 110); + AccountInfoOf::::insert(2, &AccountInfo { + trie_id: unique_id2.to_vec(), + current_mem_stored: 0, + }); + child::put(&unique_id2[..], &b"hello".to_vec(), &b"3".to_vec()); + child::put(&unique_id2[..], &b"world".to_vec(), &b"4".to_vec()); } // Transfer funds from account 1 of such amount that after this transfer - // the balance of account 1 is will be below than exsistential threshold. + // the balance of account 1 will be below the existential threshold. // // This should lead to the removal of all storage associated with this account. assert_ok!(Balances::transfer(Origin::signed(1), 2, 20)); @@ -242,15 +272,15 @@ fn account_removal_removes_storage() { // Verify that all entries from account 1 is removed, while // entries from account 2 is in place. { - assert_eq!(>::get(&1, &b"foo".to_vec()), None); - assert_eq!(>::get(&1, &b"bar".to_vec()), None); + assert_eq!(child::get_raw(&unique_id1[..], &b"foo".to_vec()), None); + assert_eq!(child::get_raw(&unique_id1[..], &b"bar".to_vec()), None); assert_eq!( - >::get(&2, &b"hello".to_vec()), + child::get(&unique_id2[..], &b"hello".to_vec()), Some(b"3".to_vec()) ); assert_eq!( - >::get(&2, &b"world".to_vec()), + child::get(&unique_id2[..], &b"world".to_vec()), Some(b"4".to_vec()) ); } @@ -289,8 +319,7 @@ fn instantiate_and_call() { with_externalities( &mut ExtBuilder::default().existential_deposit(100).build(), || { - Balances::set_free_balance(&ALICE, 1_000_000); - Balances::increase_total_stake_by(1_000_000); + Balances::deposit_creating(&ALICE, 1_000_000); assert_ok!(Contract::put_code( Origin::signed(ALICE), @@ -307,6 +336,10 @@ fn instantiate_and_call() { )); assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + }, EventRecord { phase: Phase::ApplyExtrinsic(0), event: MetaEvent::contract(RawEvent::CodeStored(HASH_RETURN_FROM_START_FN.into())), @@ -360,8 +393,7 @@ fn dispatch_call() { with_externalities( &mut ExtBuilder::default().existential_deposit(50).build(), || { - Balances::set_free_balance(&ALICE, 1_000_000); - Balances::increase_total_stake_by(1_000_000); + Balances::deposit_creating(&ALICE, 1_000_000); assert_ok!(Contract::put_code( Origin::signed(ALICE), @@ -372,6 +404,10 @@ fn dispatch_call() { // Let's keep this assert even though it's redundant. If you ever need to update the // wasm source this test will fail and will show you the actual hash. assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + }, EventRecord { phase: Phase::ApplyExtrinsic(0), event: MetaEvent::contract(RawEvent::CodeStored(HASH_DISPATCH_CALL.into())), @@ -395,6 +431,10 @@ fn dispatch_call() { )); assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + }, EventRecord { phase: Phase::ApplyExtrinsic(0), event: MetaEvent::contract(RawEvent::CodeStored(HASH_DISPATCH_CALL.into())), diff --git a/srml/contract/src/wasm/code_cache.rs b/srml/contract/src/wasm/code_cache.rs index 195da157451528237abd6cae111e1d21b4cc41ea..dab8c4bfa4b04a7ab931688affb74ff807e24af2 100644 --- a/srml/contract/src/wasm/code_cache.rs +++ b/srml/contract/src/wasm/code_cache.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/contract/src/wasm/env_def/macros.rs b/srml/contract/src/wasm/env_def/macros.rs index 27485d55ce9c7c9f099473cccad572f7cd3b3a39..0b112a825858d06b45760ec6c60c67821486fdc5 100644 --- a/srml/contract/src/wasm/env_def/macros.rs +++ b/srml/contract/src/wasm/env_def/macros.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/contract/src/wasm/env_def/mod.rs b/srml/contract/src/wasm/env_def/mod.rs index 65e9e14e6796209e4aff9615b5df0b7e8c95fc01..d51a157910d5c2c46470913ada843d0dd19f881c 100644 --- a/srml/contract/src/wasm/env_def/mod.rs +++ b/srml/contract/src/wasm/env_def/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/contract/src/wasm/mod.rs b/srml/contract/src/wasm/mod.rs index 4b4df900ace0434b5e10705ed4d3d398cb975ce9..04428280d05bb3f3f4af9068b79d52190f5aa396 100644 --- a/srml/contract/src/wasm/mod.rs +++ b/srml/contract/src/wasm/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -580,7 +580,7 @@ mod tests { /// calls `ext_caller`, loads the address from the scratch buffer and /// compares it with the constant 42. - const CODE_CALLER: &'static str = r#" + const CODE_CALLER: &str = r#" (module (import "env" "ext_caller" (func $ext_caller)) (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) @@ -645,7 +645,7 @@ mod tests { /// calls `ext_address`, loads the address from the scratch buffer and /// compares it with the constant 69. - const CODE_ADDRESS: &'static str = r#" + const CODE_ADDRESS: &str = r#" (module (import "env" "ext_address" (func $ext_address)) (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) diff --git a/srml/contract/src/wasm/prepare.rs b/srml/contract/src/wasm/prepare.rs index 12f4c7d2838cc971e80ea2b07f5495b91e3a779c..52f1580aa9fecb4c71c13a37d017f20e71e46f05 100644 --- a/srml/contract/src/wasm/prepare.rs +++ b/srml/contract/src/wasm/prepare.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/contract/src/wasm/runtime.rs b/srml/contract/src/wasm/runtime.rs index 9f515ee84e4a6910a005eb74833d2fe183ebd6c6..b4a963f93192e891f16577f8f063aa2ac03787c9 100644 --- a/srml/contract/src/wasm/runtime.rs +++ b/srml/contract/src/wasm/runtime.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,8 +16,8 @@ //! Environment definition of the wasm smart-contract runtime. -use crate::{Schedule, Trait, CodeHash, ComputeDispatchFee}; -use crate::exec::{Ext, BalanceOf, VmExecResult, OutputBuf, EmptyOutputBuf, CallReceipt, InstantiateReceipt}; +use crate::{Schedule, Trait, CodeHash, ComputeDispatchFee, BalanceOf}; +use crate::exec::{Ext, VmExecResult, OutputBuf, EmptyOutputBuf, CallReceipt, InstantiateReceipt}; use crate::gas::{GasMeter, Token, GasMeterResult, approx_gas_for_balance}; use sandbox; use system; diff --git a/srml/council/Cargo.toml b/srml/council/Cargo.toml index 3e6f41d2a9977c189b9941a70998dec0008b8016..e26003a73e4f13c62e9c9ab85891cb1d22a2fd79 100644 --- a/srml/council/Cargo.toml +++ b/srml/council/Cargo.toml @@ -5,9 +5,9 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "3.1", default-features = false } +parity-codec = { version = "3.2", default-features = false } parity-codec-derive = { version = "3.1", default-features = false } substrate-primitives = { path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } @@ -29,6 +29,7 @@ std = [ "parity-codec-derive/std", "substrate-primitives/std", "rstd/std", + "serde", "runtime_io/std", "srml-support/std", "primitives/std", diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 20c95b2bd9ff4d196211be83ba06ce437ac7cc37..a13eb7e28067ac66a8ac95ee5c8d2a63f5d85ff1 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -67,7 +67,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = Event; type Log = DigestItem; @@ -76,8 +76,10 @@ mod tests { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); - type EnsureAccountLiquid = (); type Event = Event; + type TransactionPayment = (); + type TransferPayment = (); + type DustRemoval = (); } impl democracy::Trait for Test { type Currency = balances::Module; @@ -86,6 +88,8 @@ mod tests { } impl seats::Trait for Test { type Event = Event; + type BadPresentation = (); + type BadReaper = (); } impl motions::Trait for Test { type Origin = Origin; @@ -99,6 +103,8 @@ mod tests { pub fn new_test_ext(with_council: bool) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(balances::GenesisConfig::{ + transaction_base_fee: 0, + transaction_byte_fee: 0, balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], existential_deposit: 0, transfer_fee: 0, diff --git a/srml/council/src/motions.rs b/srml/council/src/motions.rs index a2636c728a3f517deec27c5279d2f4813b5ec317..3bbe463780c46f910947209e0b45e66f23391e74 100644 --- a/srml/council/src/motions.rs +++ b/srml/council/src/motions.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -47,7 +47,6 @@ pub enum Origin { Members(u32), } -/// Event for this module. decl_event!( pub enum Event where ::Hash, ::AccountId { /// A motion (given hash) has been proposed (by given account) with a threshold (given u32). diff --git a/srml/council/src/seats.rs b/srml/council/src/seats.rs index 27a22bbf471339a3a59ebfe198fae992e7c19f7f..9ace6227da636a3aecdb0b1fb5031e120edb6dd0 100644 --- a/srml/council/src/seats.rs +++ b/srml/council/src/seats.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,7 +19,10 @@ use rstd::prelude::*; use primitives::traits::{Zero, One, As, StaticLookup}; use runtime_io::print; -use srml_support::{StorageValue, StorageMap, dispatch::Result, traits::Currency, decl_storage, decl_event, ensure}; +use srml_support::{ + StorageValue, StorageMap, dispatch::Result, decl_storage, decl_event, ensure, + traits::{Currency, ReservableCurrency, OnUnbalanced} +}; use democracy; use system::{self, ensure_signed}; @@ -77,14 +80,21 @@ use system::{self, ensure_signed}; // after each vote as all but K entries are cleared. newly registering candidates must use cleared // entries before they increase the capacity. -use srml_support::{decl_module, traits::ArithmeticType}; +use srml_support::decl_module; pub type VoteIndex = u32; -type BalanceOf = <::Currency as ArithmeticType>::Type; +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; pub trait Trait: democracy::Trait { type Event: From> + Into<::Event>; + + /// Handler for the unbalanced reduction when slashing a validator. + type BadPresentation: OnUnbalanced>; + + /// Handler for the unbalanced reduction when slashing an invalid reaping attempt. + type BadReaper: OnUnbalanced>; } decl_module! { @@ -93,31 +103,16 @@ decl_module! { /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots /// are registered. - fn set_approvals(origin, votes: Vec, #[compact] index: VoteIndex) { + fn set_approvals(origin, votes: Vec, #[compact] index: VoteIndex) -> Result { let who = ensure_signed(origin)?; - let candidates = Self::candidates(); + Self::do_set_approvals(who, votes, index) + } - ensure!(!Self::presentation_active(), "no approval changes during presentation period"); - ensure!(index == Self::vote_index(), "incorrect vote index"); - ensure!(!candidates.len().is_zero(), "amount of candidates to receive approval votes should be non-zero"); - // Prevent a vote from voters that provide a list of votes that exceeds the candidates length - // since otherise an attacker may be able to submit a very long list of `votes` that far exceeds - // the amount of candidates and waste more computation than a reasonable voting bond would cover. - ensure!(candidates.len() >= votes.len(), "amount of candidate approval votes cannot exceed amount of candidates"); - - if !>::exists(&who) { - // not yet a voter - deduct bond. - // NOTE: this must be the last potential bailer, since it changes state. - T::Currency::reserve(&who, Self::voting_bond())?; - - >::put({ - let mut v = Self::voters(); - v.push(who.clone()); - v - }); - } - >::insert(&who, index); - >::insert(&who, votes); + /// Set candidate approvals from a proxy. Approval slots stay valid as long as candidates in those slots + /// are registered. + fn proxy_set_approvals(origin, votes: Vec, #[compact] index: VoteIndex) -> Result { + let who = >::proxy(ensure_signed(origin)?).ok_or("not a proxy")?; + Self::do_set_approvals(who, votes, index) } /// Remove a voter. For it not to be a bond-consuming no-op, all approved candidate indices @@ -167,7 +162,8 @@ decl_module! { T::Currency::repatriate_reserved(&who, &reporter, Self::voting_bond())?; Self::deposit_event(RawEvent::VoterReaped(who, reporter)); } else { - T::Currency::slash_reserved(&reporter, Self::voting_bond()); + let imbalance = T::Currency::slash_reserved(&reporter, Self::voting_bond()).0; + T::BadReaper::on_unbalanced(imbalance); Self::deposit_event(RawEvent::BadReaperSlashed(reporter)); } } @@ -231,7 +227,7 @@ decl_module! { let candidate = T::Lookup::lookup(candidate)?; ensure!(index == Self::vote_index(), "index not current"); - let (_, _, expiring) = Self::next_finalise().ok_or("cannot present outside of presentation period")?; + let (_, _, expiring) = Self::next_finalize().ok_or("cannot present outside of presentation period")?; let stakes = Self::snapshoted_stakes(); let voters = Self::voters(); let bad_presentation_punishment = Self::present_slash_per_voter() * BalanceOf::::sa(voters.len() as u64); @@ -266,7 +262,8 @@ decl_module! { } else { // we can rest assured it will be Ok since we checked `can_slash` earlier; still // better safe than sorry. - let _ = T::Currency::slash(&who, bad_presentation_punishment); + let imbalance = T::Currency::slash(&who, bad_presentation_punishment).0; + T::BadPresentation::on_unbalanced(imbalance); Err(if dupe { "duplicate presentation" } else { "incorrect total" }) } } @@ -291,18 +288,18 @@ decl_module! { } /// Set the presentation duration. If there is currently a vote being presented for, will - /// invoke `finalise_vote`. + /// invoke `finalize_vote`. fn set_presentation_duration(#[compact] count: T::BlockNumber) { >::put(count); } /// Set the presentation duration. If there is current a vote being presented for, will - /// invoke `finalise_vote`. + /// invoke `finalize_vote`. fn set_term_duration(#[compact] count: T::BlockNumber) { >::put(count); } - fn on_finalise(n: T::BlockNumber) { + fn on_finalize(n: T::BlockNumber) { if let Err(e) = Self::end_block(n) { print("Guru meditation"); print(e); @@ -335,7 +332,7 @@ decl_storage! { /// Number of accounts that should be sitting on the council. pub DesiredSeats get(desired_seats) config(): u32; - // permanent state (always relevant, changes only at the finalisation of voting) + // permanent state (always relevant, changes only at the finalization of voting) /// The current council. When there's a vote going on, this should still be used for executive /// matters. The block number (second element in the tuple) is the block that their position is /// active until (calculated by the sum of the block number when the council member was elected @@ -359,9 +356,9 @@ decl_storage! { pub Candidates get(candidates): Vec; // has holes pub CandidateCount get(candidate_count): u32; - // temporary state (only relevant during finalisation/presentation) + // temporary state (only relevant during finalization/presentation) /// The accounts holding the seats that will become free on the next tally. - pub NextFinalise get(next_finalise): Option<(T::BlockNumber, u32, Vec)>; + pub NextFinalize get(next_finalize): Option<(T::BlockNumber, u32, Vec)>; /// The stakes as they were at the point that the vote ended. pub SnapshotedStakes get(snapshoted_stakes): Vec>; /// Get the leaderboard if we;re in the presentation phase. @@ -370,7 +367,6 @@ decl_storage! { } decl_event!( - /// An event in this module. pub enum Event where ::AccountId { /// reaped voter, reaper VoterReaped(AccountId, AccountId), @@ -379,7 +375,7 @@ decl_event!( /// A tally (for approval votes of council seat(s)) has started. TallyStarted(u32), /// A tally (for approval votes of council seat(s)) has ended (with one or more new members). - TallyFinalised(Vec, Vec), + TallyFinalized(Vec, Vec), } ); @@ -388,7 +384,7 @@ impl Module { /// True if we're currently in a presentation period. pub fn presentation_active() -> bool { - >::exists() + >::exists() } /// If `who` a candidate at the moment? @@ -411,7 +407,7 @@ impl Module { } else { let c = Self::active_council(); let (next_possible, count, coming) = - if let Some((tally_end, comers, leavers)) = Self::next_finalise() { + if let Some((tally_end, comers, leavers)) = Self::next_finalize() { // 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 { @@ -442,9 +438,9 @@ impl Module { } } } - if let Some((number, _, _)) = Self::next_finalise() { + if let Some((number, _, _)) = Self::next_finalize() { if block_number == number { - Self::finalise_tally()? + Self::finalize_tally()? } } Ok(()) @@ -457,6 +453,31 @@ impl Module { >::remove(voter); } + // Actually do the voting. + fn do_set_approvals(who: T::AccountId, votes: Vec, index: VoteIndex) -> Result { + let candidates = Self::candidates(); + + ensure!(!Self::presentation_active(), "no approval changes during presentation period"); + ensure!(index == Self::vote_index(), "incorrect vote index"); + ensure!(!candidates.is_empty(), "amount of candidates to receive approval votes should be non-zero"); + // Prevent a vote from voters that provide a list of votes that exceeds the candidates length + // since otherwise an attacker may be able to submit a very long list of `votes` that far exceeds + // the amount of candidates and waste more computation than a reasonable voting bond would cover. + ensure!(candidates.len() >= votes.len(), "amount of candidate approval votes cannot exceed amount of candidates"); + + if !>::exists(&who) { + // not yet a voter - deduct bond. + // NOTE: this must be the last potential bailer, since it changes state. + T::Currency::reserve(&who, Self::voting_bond())?; + + >::mutate(|v| v.push(who.clone())); + } + >::insert(&who, index); + >::insert(&who, votes); + + Ok(()) + } + /// 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(); @@ -466,13 +487,13 @@ impl Module { let retaining_seats = active_council.len() - expiring.len(); if retaining_seats < desired_seats { let empty_seats = desired_seats - retaining_seats; - >::put((number + Self::presentation_duration(), empty_seats as u32, expiring)); + >::put((number + Self::presentation_duration(), empty_seats as u32, expiring)); let voters = Self::voters(); let votes = voters.iter().map(T::Currency::total_balance).collect::>(); >::put(votes); - // initialise leaderboard. + // initialize leaderboard. let leaderboard_size = empty_seats + Self::carry_count() as usize; >::put(vec![(BalanceOf::::zero(), T::AccountId::default()); leaderboard_size]); @@ -480,14 +501,14 @@ impl Module { } } - /// Finalise the vote, removing each of the `removals` and inserting `seats` of the most approved + /// Finalize 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() -> Result { + fn finalize_tally() -> Result { >::kill(); let (_, coming, expiring): (T::BlockNumber, u32, Vec) = - >::take().ok_or("finalise can only be called after a tally is started.")?; + >::take().ok_or("finalize can only be called after a tally is started.")?; let leaderboard: Vec<(BalanceOf, T::AccountId)> = >::take().unwrap_or_default(); let new_expiry = >::block_number() + Self::term_duration(); @@ -537,7 +558,7 @@ impl Module { new_candidates.truncate(last_index + 1); } - Self::deposit_event(RawEvent::TallyFinalised(incoming, outgoing)); + Self::deposit_event(RawEvent::TallyFinalized(incoming, outgoing)); >::put(new_candidates); >::put(count); @@ -573,7 +594,7 @@ mod tests { 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::next_finalize(), None); assert_eq!(Council::candidates(), Vec::::new()); assert_eq!(Council::is_a_candidate(&1), false); @@ -730,6 +751,40 @@ mod tests { }); } + #[test] + fn proxy_voting_should_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + + Democracy::force_proxy(1, 11); + Democracy::force_proxy(2, 12); + Democracy::force_proxy(3, 13); + Democracy::force_proxy(4, 14); + + assert_ok!(Council::proxy_set_approvals(Origin::signed(11), vec![true], 0)); + assert_ok!(Council::proxy_set_approvals(Origin::signed(14), 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]); + + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + + assert_ok!(Council::proxy_set_approvals(Origin::signed(12), vec![false, true, true], 0)); + assert_ok!(Council::proxy_set_approvals(Origin::signed(13), 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 setting_any_approval_vote_count_without_any_candidate_count_should_not_work() { with_externalities(&mut new_test_ext(false), || { diff --git a/srml/council/src/voting.rs b/srml/council/src/voting.rs index 29168c161782d4079fb7cd5bb5c3d72b3e115f74..37c1444a74ee8c2f48e94fee5f94dfc20d7f6a4e 100644 --- a/srml/council/src/voting.rs +++ b/srml/council/src/voting.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -102,7 +102,7 @@ decl_module! { >::put(blocks); } - fn on_finalise(n: T::BlockNumber) { + fn on_finalize(n: T::BlockNumber) { if let Err(e) = Self::end_block(n) { print("Guru meditation"); print(e); @@ -125,7 +125,6 @@ decl_storage! { } } -/// An event in this module. decl_event!( pub enum Event where ::Hash { /// A voting tally has happened for a referendum cancellation vote. diff --git a/srml/democracy/Cargo.toml b/srml/democracy/Cargo.toml index 23ca4221cfb3d789e9e48d633c894e186dbe31d9..890882c485a1022ac0bb76920a3c85c45fd0b8c0 100644 --- a/srml/democracy/Cargo.toml +++ b/srml/democracy/Cargo.toml @@ -6,10 +6,10 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } @@ -23,7 +23,7 @@ balances = { package = "srml-balances", path = "../balances" } [features] default = ["std"] std = [ - "serde/std", + "serde", "serde_derive", "safe-mix/std", "parity-codec/std", diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index e421fdeb0a8ff446914f2ae32b440d84383e528f..4bd7ad60aa1b6fe11cc7c0a346c49aad1b19bd08 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,17 +20,20 @@ use rstd::prelude::*; use rstd::result; -use primitives::traits::{Zero, As}; +use primitives::traits::{Zero, As, Bounded}; use parity_codec::{Encode, Decode}; -use srml_support::{StorageValue, StorageMap, Parameter, Dispatchable, IsSubType}; +use srml_support::{StorageValue, StorageMap, Parameter, Dispatchable, IsSubType, EnumerableStorageMap}; use srml_support::{decl_module, decl_storage, decl_event, ensure}; -use srml_support::traits::{Currency, OnFreeBalanceZero, EnsureAccountLiquid, WithdrawReason, ArithmeticType}; +use srml_support::traits::{Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, + OnFreeBalanceZero}; use srml_support::dispatch::Result; use system::ensure_signed; mod vote_threshold; pub use vote_threshold::{Approved, VoteThreshold}; +const DEMOCRACY_ID: LockIdentifier = *b"democrac"; + /// A proposal index. pub type PropIndex = u32; /// A referendum index. @@ -38,6 +41,8 @@ pub type ReferendumIndex = u32; /// A number of lock periods. pub type LockPeriods = i8; +const MAX_RECURSION_LIMIT: u32 = 16; + /// A number of lock periods, plus a vote, one way or the other. #[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Default)] #[cfg_attr(feature = "std", derive(Debug))] @@ -65,10 +70,10 @@ impl Vote { } } -type BalanceOf = <::Currency as ArithmeticType>::Type; +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; pub trait Trait: system::Trait + Sized { - type Currency: ArithmeticType + Currency<::AccountId, Balance=BalanceOf>; + type Currency: ReservableCurrency + LockableCurrency; type Proposal: Parameter + Dispatchable + IsSubType>; @@ -115,16 +120,16 @@ decl_module! { /// Vote in a referendum. If `vote.is_aye()`, the vote is to enact the proposal; /// otherwise it is a vote to keep the status quo. - fn vote(origin, #[compact] ref_index: ReferendumIndex, vote: Vote) { + fn vote(origin, #[compact] ref_index: ReferendumIndex, vote: Vote) -> Result { let who = ensure_signed(origin)?; - ensure!(vote.multiplier() <= Self::max_lock_periods(), "vote has too great a strength"); - ensure!(Self::is_active_referendum(ref_index), "vote given for invalid referendum."); - ensure!(!T::Currency::total_balance(&who).is_zero(), - "transactor must have balance to signal approval."); - if !>::exists(&(ref_index, who.clone())) { - >::mutate(ref_index, |voters| voters.push(who.clone())); - } - >::insert(&(ref_index, who), vote); + Self::do_vote(who, ref_index, vote) + } + + /// Vote in a referendum on behalf of a stash. If `vote.is_aye()`, the vote is to enact the proposal; + /// otherwise it is a vote to keep the status quo. + fn proxy_vote(origin, #[compact] ref_index: ReferendumIndex, vote: Vote) -> Result { + let who = Self::proxy(ensure_signed(origin)?).ok_or("not a proxy")?; + Self::do_vote(who, ref_index, vote) } /// Start a referendum. @@ -143,17 +148,58 @@ decl_module! { } /// Cancel a proposal queued for enactment. - pub fn cancel_queued(#[compact] when: T::BlockNumber, #[compact] which: u32) -> Result { + pub fn cancel_queued(#[compact] when: T::BlockNumber, #[compact] which: u32) { let which = which as usize; >::mutate(when, |items| if items.len() > which { items[which] = None }); - Ok(()) } - fn on_finalise(n: T::BlockNumber) { + fn on_finalize(n: T::BlockNumber) { if let Err(e) = Self::end_block(n) { runtime_io::print(e); } } + + /// Specify a proxy. Called by the stash. + fn set_proxy(origin, proxy: T::AccountId) { + let who = ensure_signed(origin)?; + ensure!(!>::exists(&proxy), "already a proxy"); + >::insert(proxy, who) + } + + /// Clear the proxy. Called by the proxy. + fn resign_proxy(origin) { + let who = ensure_signed(origin)?; + >::remove(who); + } + + /// Clear the proxy. Called by the stash. + fn remove_proxy(origin, proxy: T::AccountId) { + let who = ensure_signed(origin)?; + ensure!(&Self::proxy(&proxy).ok_or("not a proxy")? == &who, "wrong proxy"); + >::remove(proxy); + } + + /// Delegate vote. + pub fn delegate(origin, to: T::AccountId, lock_periods: LockPeriods) { + let who = ensure_signed(origin)?; + >::insert(who.clone(), (to.clone(), lock_periods.clone())); + // Currency is locked indefinitely as long as it's delegated. + T::Currency::extend_lock(DEMOCRACY_ID, &who, Bounded::max_value(), T::BlockNumber::max_value(), WithdrawReason::Transfer.into()); + Self::deposit_event(RawEvent::Delegated(who, to)); + } + + /// Undelegate vote. + fn undelegate(origin) { + let who = ensure_signed(origin)?; + ensure!(>::exists(&who), "not delegated"); + let d = >::take(&who); + // Indefinite lock is reduced to the maximum voting lock that could be possible. + let lock_period = Self::public_delay(); + let now = >::block_number(); + let locked_until = now + lock_period * T::BlockNumber::sa(d.1 as u64); + T::Currency::set_lock(DEMOCRACY_ID, &who, Bounded::max_value(), locked_until, WithdrawReason::Transfer.into()); + Self::deposit_event(RawEvent::Undelegated(who)); + } } } @@ -208,9 +254,6 @@ decl_storage! { /// Queue of successful referenda to be dispatched. pub DispatchQueue get(dispatch_queue): map T::BlockNumber => Vec>; - /// The block at which the `who`'s funds become liquid. - pub Bondage get(bondage): map T::AccountId => T::BlockNumber; - /// Get the voters for the current proposal. pub VotersFor get(voters_for): map ReferendumIndex => Vec; @@ -218,11 +261,16 @@ decl_storage! { /// voter when called with the referendum (you'll get the default `Vote` value otherwise). If you don't want to check /// `voters_for`, then you can also check for simple existence with `VoteOf::exists` first. pub VoteOf get(vote_of): map (ReferendumIndex, T::AccountId) => Vote; + + /// Who is able to vote for whom. Value is the fund-holding account, key is the vote-transaction-sending account. + pub Proxy get(proxy): map T::AccountId => Option; + + /// Get the account (and lock periods) to which another account is delegating vote. + pub Delegations get(delegations): linked_map T::AccountId => (T::AccountId, LockPeriods); } } decl_event!( - /// An event in this module. pub enum Event where Balance = BalanceOf, ::AccountId { Proposed(PropIndex, Balance), Tabled(PropIndex, Balance, Vec), @@ -231,6 +279,8 @@ decl_event!( NotPassed(ReferendumIndex), Cancelled(ReferendumIndex), Executed(ReferendumIndex, bool), + Delegated(AccountId, AccountId), + Undelegated(AccountId), } ); @@ -269,10 +319,9 @@ impl Module { /// Get the voters for the current proposal. pub fn tally(ref_index: ReferendumIndex) -> (BalanceOf, BalanceOf, BalanceOf) { - Self::voters_for(ref_index).iter() + let (approve, against, capital): (BalanceOf, BalanceOf, BalanceOf) = Self::voters_for(ref_index).iter() .map(|voter| ( - T::Currency::total_balance(voter), - Self::vote_of((ref_index, voter.clone())), + T::Currency::total_balance(voter), Self::vote_of((ref_index, voter.clone())) )) .map(|(bal, vote)| if vote.is_aye() { @@ -280,11 +329,51 @@ impl Module { } else { (Zero::zero(), bal * BalanceOf::::sa(vote.multiplier() as u64), bal) } - ).fold((Zero::zero(), Zero::zero(), Zero::zero()), |(a, b, c), (d, e, f)| (a + d, b + e, c + f)) + ).fold((Zero::zero(), Zero::zero(), Zero::zero()), |(a, b, c), (d, e, f)| (a + d, b + e, c + f)); + let (del_approve, del_against, del_capital) = Self::tally_delegation(ref_index); + (approve + del_approve, against + del_against, capital + del_capital) + } + + /// Get the delegated voters for the current proposal. + /// I think this goes into a worker once https://github.com/paritytech/substrate/issues/1458 is done. + fn tally_delegation(ref_index: ReferendumIndex) -> (BalanceOf, BalanceOf, BalanceOf) { + Self::voters_for(ref_index).iter() + .fold((Zero::zero(), Zero::zero(), Zero::zero()), |(approve_acc, against_acc, capital_acc), voter| { + let vote = Self::vote_of((ref_index, voter.clone())); + let (votes, balance) = Self::delegated_votes(ref_index, voter.clone(), vote.multiplier(), MAX_RECURSION_LIMIT); + if vote.is_aye() { + (approve_acc + votes, against_acc, capital_acc + balance) + } else { + (approve_acc, against_acc + votes, capital_acc + balance) + } + }) + } + + fn delegated_votes( + ref_index: ReferendumIndex, + to: T::AccountId, + min_lock_periods: LockPeriods, + recursion_limit: u32, + ) -> (BalanceOf, BalanceOf) { + if recursion_limit == 0 { return (Zero::zero(), Zero::zero()); } + >::enumerate() + .filter(|(delegator, (delegate, _))| *delegate == to && !>::exists(&(ref_index, delegator.clone()))) + .fold((Zero::zero(), Zero::zero()), |(votes_acc, balance_acc), (delegator, (_delegate, periods))| { + let lock_periods = if min_lock_periods <= periods { min_lock_periods } else { periods }; + let balance = T::Currency::total_balance(&delegator); + let votes = T::Currency::total_balance(&delegator) * BalanceOf::::sa(lock_periods as u64); + let (del_votes, del_balance) = Self::delegated_votes(ref_index, delegator, lock_periods, recursion_limit - 1); + (votes_acc + votes + del_votes, balance_acc + balance + del_balance) + }) } // Exposed mutables. + #[cfg(feature = "std")] + pub fn force_proxy(stash: T::AccountId, proxy: T::AccountId) { + >::insert(proxy, stash) + } + /// Start a referendum. Can be called directly by the council. pub fn internal_start_referendum(proposal: T::Proposal, threshold: VoteThreshold, delay: T::BlockNumber) -> result::Result { >::inject_referendum(>::block_number() + >::voting_period(), proposal, threshold, delay) @@ -298,6 +387,17 @@ impl Module { // private. + /// Actually enact a vote, if legit. + fn do_vote(who: T::AccountId, ref_index: ReferendumIndex, vote: Vote) -> Result { + ensure!(vote.multiplier() <= Self::max_lock_periods(), "vote has too great a strength"); + ensure!(Self::is_active_referendum(ref_index), "vote given for invalid referendum."); + if !>::exists(&(ref_index, who.clone())) { + >::mutate(ref_index, |voters| voters.push(who.clone())); + } + >::insert(&(ref_index, who), vote); + Ok(()) + } + /// Start a referendum fn inject_referendum( end: T::BlockNumber, @@ -371,7 +471,7 @@ impl Module { // lock should they win... let locked_until = now + lock_period * T::BlockNumber::sa((vote.multiplier()) as u64); // ...extend their bondage until at least then. - >::mutate(a, |b| if *b < locked_until { *b = locked_until }); + T::Currency::extend_lock(DEMOCRACY_ID, &a, Bounded::max_value(), locked_until, WithdrawReason::Transfer.into()); } Self::clear_referendum(index); @@ -411,30 +511,7 @@ impl Module { impl OnFreeBalanceZero for Module { fn on_free_balance_zero(who: &T::AccountId) { - >::remove(who); - } -} - -impl EnsureAccountLiquid> for Module { - fn ensure_account_liquid(who: &T::AccountId) -> Result { - if Self::bondage(who) > >::block_number() { - Err("stash accounts are not liquid") - } else { - Ok(()) - } - } - fn ensure_account_can_withdraw( - who: &T::AccountId, - _value: BalanceOf, - reason: WithdrawReason, - ) -> Result { - if reason == WithdrawReason::TransactionPayment - || Self::bondage(who) <= >::block_number() - { - Ok(()) - } else { - Err("cannot transfer voting funds") - } + >::remove(who) } } @@ -447,6 +524,7 @@ mod tests { use primitives::BuildStorage; use primitives::traits::{BlakeTwo256, IdentityLookup}; use primitives::testing::{Digest, DigestItem, Header}; + use balances::BalanceLock; const AYE: Vote = Vote(-1); const NAY: Vote = Vote(0); @@ -473,7 +551,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; @@ -482,8 +560,10 @@ mod tests { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); - type EnsureAccountLiquid = (); type Event = (); + type TransactionPayment = (); + type TransferPayment = (); + type DustRemoval = (); } impl Trait for Test { type Currency = balances::Module; @@ -498,6 +578,8 @@ mod tests { fn new_test_ext_with_public_delay(public_delay: u64) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(balances::GenesisConfig::{ + transaction_base_fee: 0, + transaction_byte_fee: 0, balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], existential_deposit: 0, transfer_fee: 0, @@ -595,6 +677,210 @@ mod tests { assert_eq!(Democracy::vote_of((r, 1)), AYE); assert_eq!(Democracy::tally(r), (10, 0, 10)); + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn proxy_should_work() { + with_externalities(&mut new_test_ext(), || { + assert_eq!(Democracy::proxy(10), None); + assert_ok!(Democracy::set_proxy(Origin::signed(1), 10)); + assert_eq!(Democracy::proxy(10), Some(1)); + + // Can't set when already set. + assert_noop!(Democracy::set_proxy(Origin::signed(2), 10), "already a proxy"); + + // But this works because 11 isn't proxying. + assert_ok!(Democracy::set_proxy(Origin::signed(2), 11)); + assert_eq!(Democracy::proxy(10), Some(1)); + assert_eq!(Democracy::proxy(11), Some(2)); + + // 2 cannot fire 1's proxy: + assert_noop!(Democracy::remove_proxy(Origin::signed(2), 10), "wrong proxy"); + + // 1 fires his proxy: + assert_ok!(Democracy::remove_proxy(Origin::signed(1), 10)); + assert_eq!(Democracy::proxy(10), None); + assert_eq!(Democracy::proxy(11), Some(2)); + + // 11 resigns: + assert_ok!(Democracy::resign_proxy(Origin::signed(11))); + assert_eq!(Democracy::proxy(10), None); + assert_eq!(Democracy::proxy(11), None); + }); + } + + #[test] + fn single_proposal_should_work_with_proxy() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + assert_ok!(propose_set_balance(1, 2, 1)); + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + + System::set_block_number(2); + let r = 0; + assert_ok!(Democracy::set_proxy(Origin::signed(1), 10)); + assert_ok!(Democracy::proxy_vote(Origin::signed(10), r, AYE)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + assert_eq!(Democracy::tally(r), (10, 0, 10)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn single_proposal_should_work_with_delegation() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + + assert_ok!(propose_set_balance(1, 2, 1)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + System::set_block_number(2); + let r = 0; + + // Delegate vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, 100)); + + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + + // Delegated vote is counted. + assert_eq!(Democracy::tally(r), (30, 0, 30)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn single_proposal_should_work_with_cyclic_delegation() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + + assert_ok!(propose_set_balance(1, 2, 1)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + System::set_block_number(2); + let r = 0; + + // Check behavior with cycle. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, 100)); + assert_ok!(Democracy::delegate(Origin::signed(3), 2, 100)); + assert_ok!(Democracy::delegate(Origin::signed(1), 3, 100)); + + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1]); + + // Delegated vote is counted. + assert_eq!(Democracy::tally(r), (60, 0, 60)); + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + /// If transactor already voted, delegated vote is overwriten. + fn single_proposal_should_work_with_vote_and_delegation() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + + assert_ok!(propose_set_balance(1, 2, 1)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + System::set_block_number(2); + let r = 0; + + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + // Vote. + assert_ok!(Democracy::vote(Origin::signed(2), r, AYE)); + + // Delegate vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, 100)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1, 2]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + + // Delegated vote is not counted. + assert_eq!(Democracy::tally(r), (30, 0, 30)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn single_proposal_should_work_with_undelegation() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + + assert_ok!(propose_set_balance(1, 2, 1)); + + // Delegate and undelegate vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, 100)); + assert_ok!(Democracy::undelegate(Origin::signed(2))); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + System::set_block_number(2); + let r = 0; + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + + // Delegated vote is not counted. + assert_eq!(Democracy::tally(r), (10, 0, 10)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + /// If transactor voted, delegated vote is overwriten. + fn single_proposal_should_work_with_delegation_and_vote() { + with_externalities(&mut new_test_ext(), || { + System::set_block_number(1); + + assert_ok!(propose_set_balance(1, 2, 1)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + System::set_block_number(2); + let r = 0; + + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + // Delegate vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, 100)); + + // Vote. + assert_ok!(Democracy::vote(Origin::signed(2), r, AYE)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1, 2]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + + // Delegated vote is not counted. + assert_eq!(Democracy::tally(r), (30, 0, 30)); + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); assert_eq!(Balances::free_balance(&42), 2); @@ -790,12 +1076,35 @@ mod tests { assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - assert_eq!(Democracy::bondage(1), 0); - assert_eq!(Democracy::bondage(2), 6); - assert_eq!(Democracy::bondage(3), 5); - assert_eq!(Democracy::bondage(4), 4); - assert_eq!(Democracy::bondage(5), 3); - assert_eq!(Democracy::bondage(6), 0); + assert_eq!(Balances::locks(1), vec![]); + assert_eq!(Balances::locks(2), vec![BalanceLock { id: DEMOCRACY_ID, amount: u64::max_value(), until: 6, reasons: WithdrawReason::Transfer.into() }]); + assert_eq!(Balances::locks(3), vec![BalanceLock { id: DEMOCRACY_ID, amount: u64::max_value(), until: 5, reasons: WithdrawReason::Transfer.into() }]); + assert_eq!(Balances::locks(4), vec![BalanceLock { id: DEMOCRACY_ID, amount: u64::max_value(), until: 4, reasons: WithdrawReason::Transfer.into() }]); + assert_eq!(Balances::locks(5), vec![BalanceLock { id: DEMOCRACY_ID, amount: u64::max_value(), until: 3, reasons: WithdrawReason::Transfer.into() }]); + assert_eq!(Balances::locks(6), vec![]); + + System::set_block_number(2); + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn lock_voting_should_work_with_delegation() { + with_externalities(&mut new_test_ext_with_public_delay(1), || { + System::set_block_number(1); + let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); + assert_ok!(Democracy::vote(Origin::signed(1), r, Vote::new(false, 6))); + assert_ok!(Democracy::vote(Origin::signed(2), r, Vote::new(true, 5))); + assert_ok!(Democracy::vote(Origin::signed(3), r, Vote::new(true, 4))); + assert_ok!(Democracy::vote(Origin::signed(4), r, Vote::new(true, 3))); + assert_ok!(Democracy::delegate(Origin::signed(5), 2, 2)); + assert_ok!(Democracy::vote(Origin::signed(6), r, Vote::new(false, 1))); + + assert_eq!(Democracy::tally(r), (440, 120, 210)); + + assert_eq!(Democracy::end_block(System::block_number()), Ok(())); System::set_block_number(2); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); diff --git a/srml/democracy/src/vote_threshold.rs b/srml/democracy/src/vote_threshold.rs index 2166b8dd063cd274072a5c4fe48d2e336bcc1ddf..5d9b2b742e679e5a8c58ad39c64c717023e5d937 100644 --- a/srml/democracy/src/vote_threshold.rs +++ b/srml/democracy/src/vote_threshold.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -37,7 +37,7 @@ pub enum VoteThreshold { 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. + /// overall outcome is in favor of approval. fn approved(&self, approve: Balance, against: Balance, voters: Balance, electorate: Balance) -> bool; } @@ -72,7 +72,7 @@ fn compare_rationals + Div + Rem + Mul + Div + Rem + Copy> Approved for VoteThreshold { /// Given `approve` votes for and `against` votes against from a total electorate size of /// `electorate` of whom `voters` voted (`electorate - voters` are abstainers) then returns true if the - /// overall outcome is in favour of approval. + /// overall outcome is in favor of approval. /// /// We assume each *voter* may cast more than one *vote*, hence `voters` is not necessarily equal to /// `approve + against`. diff --git a/srml/example/Cargo.toml b/srml/example/Cargo.toml index beaafbeb21529f8a836e42a3917a541092a8db10..57abe374c9b131887c6dc420a562a5d8481d4d5b 100644 --- a/srml/example/Cargo.toml +++ b/srml/example/Cargo.toml @@ -6,8 +6,8 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } srml-support = { path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } balances = { package = "srml-balances", path = "../balances", default-features = false } @@ -20,7 +20,7 @@ sr-primitives = { path = "../../core/sr-primitives" } [features] default = ["std"] std = [ - "serde/std", + "serde", "parity-codec/std", "sr-primitives/std", "srml-support/std", diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index 4f4e0b96a0b6249da09b02c56d5fe5d8408fd971..8ba83bfd88d51583b5c3b2424b712f4866b190ab 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -66,16 +66,15 @@ decl_storage! { // A map that has enumerable entries. Bar get(bar) config(): linked_map T::AccountId => T::Balance; - // this one uses the default, we'll demonstrate the usage of 'mutate' API. Foo get(foo) config(): T::Balance; } } -/// An event in this module. Events are simple means of reporting specific conditions and -/// circumstances that have happened that users, Dapps and/or chain explorers would find -/// interesting and otherwise difficult to detect. decl_event!( + /// Events are a simple means of reporting specific conditions and + /// circumstances that have happened that users, Dapps and/or chain explorers would find + /// interesting and otherwise difficult to detect. pub enum Event where B = ::Balance { // Just a normal `enum`, here's a dummy event to ensure it compiles. /// Dummy event, just here so there's a generic type that's used. @@ -202,18 +201,27 @@ decl_module! { >::put(new_value); } - // The signature could also look like: `fn on_initialise()` - fn on_initialise(_n: T::BlockNumber) { + // The signature could also look like: `fn on_initialize()` + fn on_initialize(_n: T::BlockNumber) { // Anything that needs to be done at the start of the block. // We don't do anything here. } - // The signature could also look like: `fn on_finalise()` - fn on_finalise(_n: T::BlockNumber) { + // The signature could also look like: `fn on_finalize()` + fn on_finalize(_n: T::BlockNumber) { // Anything that needs to be done at the end of the block. // We just kill our dummy storage item. >::kill(); } + + // A runtime code run after every block and have access to extended set of APIs. + // + // For instance you can generate extrinsics for the upcoming produced block. + fn offchain_worker(_n: T::BlockNumber) { + // We don't do anything here. + // but we could dispatch extrinsic (transaction/inherent) using + // runtime_io::submit_extrinsic + } } } @@ -250,7 +258,7 @@ mod tests { // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. use sr_primitives::{ - BuildStorage, traits::{BlakeTwo256, OnInitialise, OnFinalise, IdentityLookup}, + BuildStorage, traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup}, testing::{Digest, DigestItem, Header} }; @@ -271,7 +279,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; @@ -280,8 +288,10 @@ mod tests { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); - type EnsureAccountLiquid = (); type Event = (); + type TransactionPayment = (); + type TransferPayment = (); + type DustRemoval = (); } impl Trait for Test { type Event = (); @@ -313,12 +323,12 @@ mod tests { assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); assert_eq!(Example::dummy(), Some(69)); - // Check that finalising the block removes Dummy from storage. - >::on_finalise(1); + // Check that finalizing the block removes Dummy from storage. + >::on_finalize(1); assert_eq!(Example::dummy(), None); // Check that accumulate works when we Dummy has None in it. - >::on_initialise(2); + >::on_initialize(2); assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); assert_eq!(Example::dummy(), Some(42)); }); diff --git a/srml/executive/Cargo.toml b/srml/executive/Cargo.toml index fe195acc21e39940e327bbcde47d509509bf2e07..31ca69fa55b3a2ffc7de57f10f9161ad5f0313dd 100644 --- a/srml/executive/Cargo.toml +++ b/srml/executive/Cargo.toml @@ -5,8 +5,8 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } @@ -18,7 +18,6 @@ hex-literal = "0.1.0" substrate-primitives = { path = "../../core/primitives" } srml-indices = { path = "../indices" } balances = { package = "srml-balances", path = "../balances" } -fees = { package = "srml-fees", path = "../fees" } parity-codec-derive = { version = "3.1" } [features] @@ -26,7 +25,7 @@ default = ["std"] std = [ "rstd/std", "srml-support/std", - "serde/std", + "serde", "parity-codec/std", "primitives/std", "runtime_io/std", diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index c6817c25544f1a3b9323d07872831c7293227dbe..48908a01b316f4b89fa0d61fd5a47e366bfe3bf9 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,13 +18,14 @@ #![cfg_attr(not(feature = "std"), no_std)] - use rstd::prelude::*; use rstd::marker::PhantomData; use rstd::result; -use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalise, - OnInitialise, Hash, As, Digest}; -use srml_support::{Dispatchable, traits::ChargeBytesFee}; +use primitives::traits::{ + self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, + OnInitialize, Hash, As, Digest, NumberFor, Block as BlockT, OffchainWorker +}; +use srml_support::{Dispatchable, traits::MakePayment}; use parity_codec::{Codec, Encode}; use system::extrinsics_root; use primitives::{ApplyOutcome, ApplyError}; @@ -47,20 +48,45 @@ mod internal { } } -pub struct Executive< - System, - Block, - Context, - Payment, - AllModules, ->(PhantomData<(System, Block, Context, Payment, AllModules)>); +/// Something that can be used to execute a block. +pub trait ExecuteBlock { + /// Actually execute all transitioning for `block`. + fn execute_block(block: Block); + /// Execute all extrinsics like when executing a `block`, but with dropping intial and final checks. + fn execute_extrinsics_without_checks(block_number: NumberFor, extrinsics: Vec); +} + +pub struct Executive( + PhantomData<(System, Block, Context, Payment, AllModules)> +); impl< + System: system::Trait, + Block: traits::Block, Context: Default, + Payment: MakePayment, + AllModules: OnInitialize + OnFinalize + OffchainWorker, +> ExecuteBlock for Executive where + Block::Extrinsic: Checkable + Codec, + >::Checked: Applyable, + <>::Checked as Applyable>::Call: Dispatchable, + <<>::Checked as Applyable>::Call as Dispatchable>::Origin: From> +{ + fn execute_block(block: Block) { + Executive::::execute_block(block); + } + + fn execute_extrinsics_without_checks(block_number: NumberFor, extrinsics: Vec) { + Executive::::execute_extrinsics_without_checks(block_number, extrinsics); + } +} + +impl< System: system::Trait, Block: traits::Block, - Payment: ChargeBytesFee, - AllModules: OnInitialise + OnFinalise, + Context: Default, + Payment: MakePayment, + AllModules: OnInitialize + OnFinalize + OffchainWorker, > Executive where Block::Extrinsic: Checkable + Codec, >::Checked: Applyable, @@ -68,9 +94,13 @@ impl< <<>::Checked as Applyable>::Call as Dispatchable>::Origin: From> { /// Start the execution of a particular block. - pub fn initialise_block(header: &System::Header) { - >::initialise(header.number(), header.parent_hash(), header.extrinsics_root()); - >::on_initialise(*header.number()); + pub fn initialize_block(header: &System::Header) { + Self::initialize_block_impl(header.number(), header.parent_hash(), header.extrinsics_root()); + } + + fn initialize_block_impl(block_number: &System::BlockNumber, parent_hash: &System::Hash, extrinsics_root: &System::Hash) { + >::initialize(block_number, parent_hash, extrinsics_root); + >::on_initialize(*block_number); } fn initial_checks(block: &Block) { @@ -91,32 +121,49 @@ impl< /// Actually execute all transitioning for `block`. pub fn execute_block(block: Block) { - Self::initialise_block(block.header()); + Self::initialize_block(block.header()); // any initial checks Self::initial_checks(&block); - // execute transactions + // execute extrinsics let (header, extrinsics) = block.deconstruct(); - extrinsics.into_iter().for_each(Self::apply_extrinsic_no_note); - - // post-transactional book-keeping. - >::note_finished_extrinsics(); - >::on_finalise(*header.number()); + Self::execute_extrinsics_with_book_keeping(extrinsics, *header.number()); // any final checks Self::final_checks(&header); } - /// Finalise the block - it is up the caller to ensure that all header fields are valid + /// Execute all extrinsics like when executing a `block`, but with dropping intial and final checks. + pub fn execute_extrinsics_without_checks(block_number: NumberFor, extrinsics: Vec) { + // Make the api happy, but maybe we should not set them at all. + let parent_hash = ::Hashing::hash(b"parent_hash"); + let extrinsics_root = ::Hashing::hash(b"extrinsics_root"); + + Self::initialize_block_impl(&block_number, &parent_hash, &extrinsics_root); + + // execute extrinsics + Self::execute_extrinsics_with_book_keeping(extrinsics, block_number); + } + + /// Execute given extrinsics and take care of post-extrinsics book-keeping + fn execute_extrinsics_with_book_keeping(extrinsics: Vec, block_number: NumberFor) { + extrinsics.into_iter().for_each(Self::apply_extrinsic_no_note); + + // post-extrinsics book-keeping. + >::note_finished_extrinsics(); + >::on_finalize(block_number); + } + + /// Finalize the block - it is up the caller to ensure that all header fields are valid /// except state-root. - pub fn finalise_block() -> System::Header { + pub fn finalize_block() -> System::Header { >::note_finished_extrinsics(); - >::on_finalise(>::block_number()); + >::on_finalize(>::block_number()); // setup extrinsics >::derive_extrinsics(); - >::finalise() + >::finalize() } /// Apply extrinsic outside of the block execution function. @@ -167,7 +214,7 @@ impl< ) } // pay any fees. - Payment::charge_base_bytes_fee(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?; + Payment::make_payment(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?; // AUDIT: Under no circumstances may this function panic from here onwards. @@ -194,7 +241,7 @@ impl< fn final_checks(header: &System::Header) { // remove temporaries. - let new_header = >::finalise(); + let new_header = >::finalize(); // check digest. assert_eq!( @@ -239,7 +286,7 @@ impl< if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { // pay any fees. - if Payment::charge_base_bytes_fee(sender, encoded_len).is_err() { + if Payment::make_payment(sender, encoded_len).is_err() { return TransactionValidity::Invalid(ApplyError::CantPay as i8) } @@ -272,6 +319,11 @@ impl< }) } } + + /// Start an offchain worker and generate extrinsics. + pub fn offchain_worker(n: System::BlockNumber) { + >::generate_extrinsics(n) + } } #[cfg(test)] @@ -285,7 +337,6 @@ mod tests { use primitives::testing::{Digest, DigestItem, Header, Block}; use srml_support::{traits::Currency, impl_outer_origin, impl_outer_event}; use system; - use fees; use hex_literal::{hex, hex_impl}; impl_outer_origin! { @@ -295,7 +346,7 @@ mod tests { impl_outer_event!{ pub enum MetaEvent for Runtime { - balances, fees, + balances, } } @@ -319,35 +370,31 @@ mod tests { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); - type EnsureAccountLiquid = (); - type Event = MetaEvent; - } - impl fees::Trait for Runtime { type Event = MetaEvent; - type TransferAsset = balances::Module; + type TransactionPayment = (); + type DustRemoval = (); + type TransferPayment = (); } type TestXt = primitives::testing::TestXt>; - type Executive = super::Executive, system::ChainContext, fees::Module, ()>; + type Executive = super::Executive, system::ChainContext, balances::Module, ()>; #[test] fn balance_transfer_dispatch_works() { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(balances::GenesisConfig:: { + transaction_base_fee: 10, + transaction_byte_fee: 0, balances: vec![(1, 111)], existential_deposit: 0, transfer_fee: 0, creation_fee: 0, vesting: vec![], }.build_storage().unwrap().0); - t.extend(fees::GenesisConfig:: { - transaction_base_fee: 10, - transaction_byte_fee: 0, - }.build_storage().unwrap().0); let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(2, 69)); let mut t = runtime_io::TestExternalities::::new(t); with_externalities(&mut t, || { - Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), + Executive::initialize_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); Executive::apply_extrinsic(xt).unwrap(); assert_eq!(>::total_balance(&1), 32); @@ -368,7 +415,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("6651861f40a8f42c033b3e937cb3513e6dbaf4be6bafb1561a19f884be3f58dd").into(), + state_root: hex!("49cd58a254ccf6abc4a023d9a22dcfc421e385527a250faec69f8ad0d8ed3e48").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Digest { logs: vec![], }, }, @@ -402,7 +449,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("6651861f40a8f42c033b3e937cb3513e6dbaf4be6bafb1561a19f884be3f58dd").into(), + state_root: hex!("49cd58a254ccf6abc4a023d9a22dcfc421e385527a250faec69f8ad0d8ed3e48").into(), extrinsics_root: [0u8; 32].into(), digest: Digest { logs: vec![], }, }, @@ -416,7 +463,7 @@ mod tests { let mut t = new_test_ext(); let xt = primitives::testing::TestXt(Some(1), 42, Call::transfer(33, 69)); with_externalities(&mut t, || { - Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); + Executive::initialize_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); assert!(Executive::apply_extrinsic(xt).is_err()); assert_eq!(>::extrinsic_index(), Some(0)); }); @@ -431,7 +478,7 @@ mod tests { let encoded = xt2.encode(); let len = if should_fail { (internal::MAX_TRANSACTIONS_SIZE - 1) as usize } else { encoded.len() }; with_externalities(&mut t, || { - Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); + Executive::initialize_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); assert_eq!(>::all_extrinsics_len(), 0); Executive::apply_extrinsic(xt).unwrap(); diff --git a/srml/fees/Cargo.toml b/srml/fees/Cargo.toml deleted file mode 100644 index 7f49956167dd5a790088dfe68228952cff489cd4..0000000000000000000000000000000000000000 --- a/srml/fees/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "srml-fees" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false } -parity-codec-derive = { version = "3.1", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } -srml-support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[features] -default = ["std"] -std = [ - "serde/std", - "parity-codec/std", - "parity-codec-derive/std", - "primitives/std", - "rstd/std", - "runtime_io/std", - "runtime_primitives/std", - "srml-support/std", - "system/std", -] diff --git a/srml/fees/src/lib.rs b/srml/fees/src/lib.rs deleted file mode 100644 index 09e32db9b0d4b4c10a0de68792af265e17dce731..0000000000000000000000000000000000000000 --- a/srml/fees/src/lib.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Handles all transaction fee related operations - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -use srml_support::{ - dispatch::Result, StorageMap, decl_event, decl_storage, decl_module, - traits::{ArithmeticType, ChargeBytesFee, ChargeFee, TransferAsset, WithdrawReason} -}; -use runtime_primitives::traits::{ - As, CheckedAdd, CheckedSub, CheckedMul, Zero -}; -use system; - -mod mock; -mod tests; - -type AssetOf = <::TransferAsset as ArithmeticType>::Type; - -pub trait Trait: system::Trait { - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// A function does the asset transfer between accounts - type TransferAsset: ArithmeticType + TransferAsset>; -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - fn on_finalise() { - let extrinsic_count = >::extrinsic_count(); - (0..extrinsic_count).for_each(|index| { - // Deposit `Charged` event if some amount of fee charged. - let fee = >::take(index); - if !fee.is_zero() { - Self::deposit_event(RawEvent::Charged(index, fee)); - } - }); - } - } -} - -decl_event!( - pub enum Event where Amount = AssetOf { - /// Fee charged (extrinsic_index, fee_amount) - Charged(u32, Amount), - } -); - -decl_storage! { - trait Store for Module as Fees { - /// The fee to be paid for making a transaction; the base. - pub TransactionBaseFee get(transaction_base_fee) config(): AssetOf; - /// The fee to be paid for making a transaction; the per-byte portion. - pub TransactionByteFee get(transaction_byte_fee) config(): AssetOf; - - /// The `extrinsic_index => accumulated_fees` map, containing records to - /// track the overall charged fees for each transaction. - /// - /// All records should be removed at finalise stage. - CurrentTransactionFee get(current_transaction_fee): map u32 => AssetOf; - } -} - -impl ChargeBytesFee for Module { - fn charge_base_bytes_fee(transactor: &T::AccountId, encoded_len: usize) -> Result { - let bytes_fee = Self::transaction_byte_fee().checked_mul( - & as As>::sa(encoded_len as u64) - ).ok_or_else(|| "bytes fee overflow")?; - let overall = Self::transaction_base_fee().checked_add(&bytes_fee).ok_or_else(|| "bytes fee overflow")?; - Self::charge_fee(transactor, overall) - } -} - -impl ChargeFee for Module { - type Amount = AssetOf; - - fn charge_fee(transactor: &T::AccountId, amount: AssetOf) -> Result { - let extrinsic_index = >::extrinsic_index().ok_or_else(|| "no extrinsic index found")?; - let current_fee = Self::current_transaction_fee(extrinsic_index); - let new_fee = current_fee.checked_add(&amount).ok_or_else(|| "fee got overflow after charge")?; - - T::TransferAsset::withdraw(transactor, amount, WithdrawReason::TransactionPayment)?; - - >::insert(extrinsic_index, new_fee); - Ok(()) - } - - fn refund_fee(transactor: &T::AccountId, amount: AssetOf) -> Result { - let extrinsic_index = >::extrinsic_index().ok_or_else(|| "no extrinsic index found")?; - let current_fee = Self::current_transaction_fee(extrinsic_index); - let new_fee = current_fee.checked_sub(&amount).ok_or_else(|| "fee got underflow after refund")?; - - T::TransferAsset::deposit(transactor, amount)?; - - >::insert(extrinsic_index, new_fee); - Ok(()) - } -} diff --git a/srml/fees/src/mock.rs b/srml/fees/src/mock.rs deleted file mode 100644 index 7f6c715f4b8bbeceec7e3656b5ea400c84bf8834..0000000000000000000000000000000000000000 --- a/srml/fees/src/mock.rs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -#![cfg(test)] - -use runtime_primitives::BuildStorage; -use runtime_primitives::{ - traits::{IdentityLookup, BlakeTwo256}, - testing::{Digest, DigestItem, Header}, -}; -use primitives::{H256, Blake2Hasher}; -use runtime_io; -use srml_support::{ - impl_outer_origin, impl_outer_event, - traits::{ArithmeticType, TransferAsset, WithdrawReason} -}; -use crate::{GenesisConfig, Module, Trait, system}; - -impl_outer_origin!{ - pub enum Origin for Test {} -} - -mod fees { - pub use crate::Event; -} - -impl_outer_event!{ - pub enum TestEvent for Test { - fees, - } -} - -pub struct TransferAssetMock; - -impl TransferAsset for TransferAssetMock { - type Amount = u64; - - fn transfer(_: &AccountId, _: &AccountId, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } - fn withdraw(_: &AccountId, _: Self::Amount, _: WithdrawReason) -> Result<(), &'static str> { Ok(()) } - fn deposit(_: &AccountId, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } -} - -impl ArithmeticType for TransferAssetMock { - type Type = u64; -} - -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Test; -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type Digest = Digest; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = TestEvent; - type Log = DigestItem; -} -impl Trait for Test { - type Event = TestEvent; - type TransferAsset = TransferAssetMock; -} - -pub type System = system::Module; -pub type Fees = Module; - -pub struct ExtBuilder { - transaction_base_fee: u64, - transaction_byte_fee: u64, -} -impl Default for ExtBuilder { - fn default() -> Self { - Self { - transaction_base_fee: 0, - transaction_byte_fee: 0, - } - } -} -impl ExtBuilder { - pub fn transaction_base_fee(mut self, transaction_base_fee: u64) -> Self { - self.transaction_base_fee = transaction_base_fee; - self - } - pub fn transaction_byte_fee(mut self, transaction_byte_fee: u64) -> Self { - self.transaction_byte_fee = transaction_byte_fee; - self - } - pub fn build(self) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; - t.extend(GenesisConfig:: { - transaction_base_fee: self.transaction_base_fee, - transaction_byte_fee: self.transaction_byte_fee, - }.build_storage().unwrap().0); - t.into() - } -} diff --git a/srml/fees/src/tests.rs b/srml/fees/src/tests.rs deleted file mode 100644 index a1c96570629e85d2b5c8df5a8bed4fc314792803..0000000000000000000000000000000000000000 --- a/srml/fees/src/tests.rs +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the module. - -#![cfg(test)] - -use super::*; -use runtime_io::with_externalities; -use runtime_primitives::traits::{OnFinalise}; -use system::{EventRecord, Phase}; - -use mock::{Fees, System, ExtBuilder}; -use srml_support::{assert_ok, assert_err}; - -#[test] -fn charge_base_bytes_fee_should_work() { - with_externalities( - &mut ExtBuilder::default() - .transaction_base_fee(3) - .transaction_byte_fee(5) - .build(), - || { - System::set_extrinsic_index(0); - assert_ok!(Fees::charge_base_bytes_fee(&0, 7)); - assert_eq!(Fees::current_transaction_fee(0), 3 + 5 * 7); - - System::set_extrinsic_index(1); - assert_ok!(Fees::charge_base_bytes_fee(&0, 11)); - assert_eq!(Fees::current_transaction_fee(1), 3 + 5 * 11); - - System::set_extrinsic_index(3); - assert_ok!(Fees::charge_base_bytes_fee(&0, 13)); - assert_eq!(Fees::current_transaction_fee(3), 3 + 5 * 13); - } - ); -} - -#[test] -fn charge_base_bytes_fee_should_not_work_if_bytes_fee_overflow() { - // bytes fee overflows. - with_externalities( - &mut ExtBuilder::default() - .transaction_base_fee(0) - .transaction_byte_fee(u64::max_value()) - .build(), - || { - System::set_extrinsic_index(0); - assert_err!( - Fees::charge_base_bytes_fee(&0, 2), - "bytes fee overflow" - ); - } - ); -} - -#[test] -fn charge_base_bytes_fee_should_not_work_if_overall_fee_overflow() { - // bytes fee doesn't overflow, but overall fee (bytes_fee + base_fee) does - with_externalities( - &mut ExtBuilder::default() - .transaction_base_fee(u64::max_value()) - .transaction_byte_fee(1) - .build(), - || { - System::set_extrinsic_index(0); - assert_err!( - Fees::charge_base_bytes_fee(&0, 1), - "bytes fee overflow" - ); - } - ); -} - -#[test] -fn charge_fee_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_extrinsic_index(0); - assert_ok!(Fees::charge_fee(&0, 2)); - assert_ok!(Fees::charge_fee(&0, 3)); - assert_eq!(Fees::current_transaction_fee(0), 2 + 3); - - System::set_extrinsic_index(2); - assert_ok!(Fees::charge_fee(&0, 5)); - assert_ok!(Fees::charge_fee(&0, 7)); - assert_eq!(Fees::current_transaction_fee(2), 5 + 7); - }); -} - -#[test] -fn charge_fee_when_overflow_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_extrinsic_index(0); - assert_ok!(Fees::charge_fee(&0, u64::max_value())); - assert_err!(Fees::charge_fee(&0, 1), "fee got overflow after charge"); - }); -} - -#[test] -fn refund_fee_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_extrinsic_index(0); - assert_ok!(Fees::charge_fee(&0, 5)); - assert_ok!(Fees::refund_fee(&0, 3)); - assert_eq!(Fees::current_transaction_fee(0), 5 - 3); - }); -} - -#[test] -fn refund_fee_when_underflow_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_extrinsic_index(0); - assert_err!(Fees::refund_fee(&0, 1), "fee got underflow after refund"); - }); -} - -#[test] -fn on_finalise_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - // charge fees in extrinsic index 3 - System::set_extrinsic_index(3); - assert_ok!(Fees::charge_fee(&0, 1)); - System::note_applied_extrinsic(&Ok(()), 1); - // charge fees in extrinsic index 5 - System::set_extrinsic_index(5); - assert_ok!(Fees::charge_fee(&0, 1)); - System::note_applied_extrinsic(&Ok(()), 1); - System::note_finished_extrinsics(); - - // `current_transaction_fee`, `extrinsic_count` should be as expected. - assert_eq!(Fees::current_transaction_fee(3), 1); - assert_eq!(Fees::current_transaction_fee(5), 1); - assert_eq!(System::extrinsic_count(), 5 + 1); - - >::on_finalise(1); - - // When finalised, `CurrentTransactionFee` records should be cleared. - assert_eq!(Fees::current_transaction_fee(3), 0); - assert_eq!(Fees::current_transaction_fee(5), 0); - - // When finalised, if any fee charged in a extrinsic, a `Charged` event should be deposited - // for it. - let fee_charged_events: Vec> = System::events() - .into_iter() - .filter(|e| match e.event { - mock::TestEvent::fees(RawEvent::Charged(_, _)) => return true, - _ => return false, - }) - .collect(); - assert_eq!(fee_charged_events, vec![ - EventRecord { - phase: Phase::Finalization, - event: RawEvent::Charged(3, 1).into(), - }, - EventRecord { - phase: Phase::Finalization, - event: RawEvent::Charged(5, 1).into(), - }, - ]); - }); -} diff --git a/srml/finality-tracker/Cargo.toml b/srml/finality-tracker/Cargo.toml index 246d48d01c732e7fbf4360df72703df1dee325e2..22691e1aa7b14f5538f749edb6261c6fd3d13bc7 100644 --- a/srml/finality-tracker/Cargo.toml +++ b/srml/finality-tracker/Cargo.toml @@ -8,14 +8,12 @@ edition = "2018" hex-literal = "0.1.0" serde = { version = "1.0", default-features = false } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "3.0", default-features = false } -parity-codec-derive = { version = "3.0", default-features = false } -substrate-inherents = { path = "../../core/inherents", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +parity-codec = { version = "3.2", default-features = false } +inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } srml-system = { path = "../system", default-features = false } -srml-session = { path = "../session", default-features = false } [dev-dependencies] substrate-primitives = { path = "../../core/primitives", default-features = false } @@ -29,10 +27,9 @@ std = [ "serde/std", "serde_derive", "parity-codec/std", - "sr-std/std", + "rstd/std", "srml-support/std", - "sr-primitives/std", + "primitives/std", "srml-system/std", - "srml-session/std", - "substrate-inherents/std", + "inherents/std", ] diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs index 43e95912cfb2940e235fba2ee66f9bad1cf0f158..34be4ea66a590f216ee350550fc43ae8670a3038 100644 --- a/srml/finality-tracker/src/lib.rs +++ b/srml/finality-tracker/src/lib.rs @@ -21,13 +21,13 @@ #[macro_use] extern crate srml_support; -use substrate_inherents::{ +use inherents::{ RuntimeString, InherentIdentifier, ProvideInherent, InherentData, MakeFatalError, }; use srml_support::StorageValue; -use sr_primitives::traits::{As, One, Zero}; -use sr_std::{prelude::*, result, cmp, vec}; +use primitives::traits::{As, One, Zero}; +use rstd::{prelude::*, result, cmp, vec}; use parity_codec::Decode; use srml_system::{ensure_inherent, Trait as SystemTrait}; @@ -68,7 +68,7 @@ impl InherentDataProvider { } #[cfg(feature = "std")] -impl substrate_inherents::ProvideInherentData for InherentDataProvider +impl inherents::ProvideInherentData for InherentDataProvider where F: Fn() -> Result { fn inherent_identifier(&self) -> &'static InherentIdentifier { @@ -126,7 +126,7 @@ decl_module! { ::Update::put(hint); } - fn on_finalise() { + fn on_finalize() { Self::update_hint(::Update::take()) } } @@ -261,9 +261,9 @@ mod tests { use sr_io::{with_externalities, TestExternalities}; use substrate_primitives::H256; - use sr_primitives::BuildStorage; - use sr_primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalise, Header as HeaderT}; - use sr_primitives::testing::{Digest, DigestItem, Header}; + use primitives::BuildStorage; + use primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}; + use primitives::testing::{Digest, DigestItem, Header}; use srml_support::impl_outer_origin; use srml_system as system; use lazy_static::lazy_static; @@ -344,9 +344,9 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { let mut parent_hash = System::parent_hash(); for i in 2..106 { - System::initialise(&i, &parent_hash, &Default::default()); - FinalityTracker::on_finalise(i); - let hdr = System::finalise(); + System::initialize(&i, &parent_hash, &Default::default()); + FinalityTracker::on_finalize(i); + let hdr = System::finalize(); parent_hash = hdr.hash(); } @@ -369,13 +369,13 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { let mut parent_hash = System::parent_hash(); for i in 2..106 { - System::initialise(&i, &parent_hash, &Default::default()); + System::initialize(&i, &parent_hash, &Default::default()); assert_ok!(FinalityTracker::dispatch( Call::final_hint(i-1), Origin::INHERENT, )); - FinalityTracker::on_finalise(i); - let hdr = System::finalise(); + FinalityTracker::on_finalize(i); + let hdr = System::finalize(); parent_hash = hdr.hash(); } diff --git a/srml/grandpa/Cargo.toml b/srml/grandpa/Cargo.toml index e7a1b701052d333c48813d4b1cdf2343dbc170b1..b7cc5dc231f3d7f3075db9710644574d73b7b43c 100644 --- a/srml/grandpa/Cargo.toml +++ b/srml/grandpa/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] #hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../../core/primitives", default-features = false } substrate-finality-grandpa-primitives = { path = "../../core/finality-grandpa/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } @@ -16,6 +16,7 @@ primitives = { package = "sr-primitives", path = "../../core/sr-primitives", def srml-support = { path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } session = { package = "srml-session", path = "../session", default-features = false } +consensus = { package = "srml-consensus", path = "../consensus", default-features = false } finality-tracker = { package = "srml-finality-tracker", path = "../finality-tracker", default-features = false } [dev-dependencies] @@ -24,7 +25,7 @@ runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] std = [ - "serde/std", + "serde", "serde_derive", "parity-codec/std", "substrate-primitives/std", @@ -33,6 +34,7 @@ std = [ "srml-support/std", "primitives/std", "system/std", + "consensus/std", "session/std", "finality-tracker/std", ] diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs index f06c84e23507e942bad6a02d59f75ffb8a453796..e9b00662d6e52fed452344acbb44a1c21d3b2f6b 100644 --- a/srml/grandpa/src/lib.rs +++ b/srml/grandpa/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -40,10 +40,11 @@ use srml_support::{Parameter, decl_event, decl_storage, decl_module}; use srml_support::dispatch::Result; use srml_support::storage::StorageValue; use srml_support::storage::unhashed::StorageVec; -use primitives::traits::{CurrentHeight, Convert}; -use substrate_primitives::Ed25519AuthorityId; +use primitives::traits::CurrentHeight; +use substrate_primitives::ed25519; use system::ensure_signed; use primitives::traits::MaybeSerializeDebug; +use ed25519::Public as AuthorityId; mod mock; mod tests; @@ -72,7 +73,7 @@ pub trait GrandpaChangeSignal { #[cfg_attr(feature = "std", derive(Serialize, Debug))] #[derive(Encode, Decode, PartialEq, Eq, Clone)] pub enum RawLog { - /// Authorities set change has been signalled. Contains the new set of authorities + /// Authorities set change has been signaled. Contains the new set of authorities /// and the delay in blocks _to finalize_ before applying. AuthoritiesChangeSignal(N, Vec<(SessionKey, u64)>), /// A forced authorities set change. Contains in this order: the median last @@ -100,7 +101,7 @@ impl RawLog { } impl GrandpaChangeSignal for RawLog - where N: Clone, SessionKey: Clone + Into, + where N: Clone, SessionKey: Clone + Into, { fn as_signal(&self) -> Option> { RawLog::as_signal(self).map(|(delay, next_authorities)| ScheduledChange { @@ -175,7 +176,6 @@ impl Decode for StoredPendingChange where ::SessionKey { /// New authority set has been applied. @@ -185,7 +185,7 @@ decl_event!( decl_storage! { trait Store for Module as GrandpaFinality { - // Pending change: (signalled at, scheduled change). + // Pending change: (signaled at, scheduled change). PendingChange get(pending_change): Option>; // next block number where we can force a change. NextForced get(next_forced): Option; @@ -215,13 +215,13 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { fn deposit_event() = default; - /// Report some misbehaviour. + /// Report some misbehavior. fn report_misbehavior(origin, _report: Vec) { ensure_signed(origin)?; // FIXME: https://github.com/paritytech/substrate/issues/1112 } - fn on_finalise(block_number: T::BlockNumber) { + fn on_finalize(block_number: T::BlockNumber) { if let Some(pending_change) = >::get() { if block_number == pending_change.scheduled_at { if let Some(median) = pending_change.forced { @@ -268,7 +268,7 @@ impl Module { /// indicates the median last finalized block number and it should be used /// as the canon block when starting the new grandpa voter. /// - /// No change should be signalled while any change is pending. Returns + /// No change should be signaled while any change is pending. Returns /// an error if a change is already pending. pub fn schedule_change( next_authorities: Vec<(T::SessionKey, u64)>, @@ -309,7 +309,7 @@ impl Module { } } -impl Module where Ed25519AuthorityId: core::convert::From<::SessionKey> { +impl Module where AuthorityId: core::convert::From<::SessionKey> { /// See if the digest contains any standard scheduled change. pub fn scrape_digest_change(log: &Log) -> Option> @@ -340,19 +340,14 @@ impl Default for SyncedAuthorities { } impl session::OnSessionChange for SyncedAuthorities where - T: Trait, - T: session::Trait, - ::ConvertAccountIdToSessionKey: Convert< - ::AccountId, - ::SessionKey, - >, + T: Trait + consensus::Trait::SessionKey>, + ::Log: From::SessionKey>> { fn on_session_change(_: X, _: bool) { use primitives::traits::Zero; - let next_authorities = >::validators() + let next_authorities = >::authorities() .into_iter() - .map(T::ConvertAccountIdToSessionKey::convert) .map(|key| (key, 1)) // evenly-weighted. .collect::::SessionKey, u64)>>(); @@ -365,22 +360,17 @@ impl session::OnSessionChange for SyncedAuthorities where } impl finality_tracker::OnFinalizationStalled for SyncedAuthorities where - T: Trait, - T: session::Trait, + T: Trait + consensus::Trait::SessionKey>, + ::Log: From::SessionKey>>, T: finality_tracker::Trait, - ::ConvertAccountIdToSessionKey: Convert< - ::AccountId, - ::SessionKey, - >, { fn on_stalled(further_wait: T::BlockNumber) { // when we record old authority sets, we can use `finality_tracker::median` // to figure out _who_ failed. until then, we can't meaningfully guard // against `next == last` the way that normal session changes do. - let next_authorities = >::validators() + let next_authorities = >::authorities() .into_iter() - .map(T::ConvertAccountIdToSessionKey::convert) .map(|key| (key, 1)) // evenly-weighted. .collect::::SessionKey, u64)>>(); diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs index ca5744b19b9e31321c21710f766a0481a5f02495..4405604ab19c07a9e074439ebc778ae3b10ac20c 100644 --- a/srml/grandpa/src/mock.rs +++ b/srml/grandpa/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -52,7 +52,7 @@ impl system::Trait for Test { type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = TestEvent; type Log = DigestItem; diff --git a/srml/grandpa/src/tests.rs b/srml/grandpa/src/tests.rs index f7e08a20b3b6f597fafb97a21aceb16f9404493e..3050b6a572e0d2d8269cf0a6ba8beb5862248da8 100644 --- a/srml/grandpa/src/tests.rs +++ b/srml/grandpa/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ #![cfg(test)] -use primitives::{testing, traits::OnFinalise}; +use primitives::{testing, traits::OnFinalize}; use primitives::traits::Header; use runtime_io::with_externalities; use crate::mock::{Grandpa, System, new_test_ext}; @@ -30,13 +30,13 @@ use super::*; #[test] fn authorities_change_logged() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { - System::initialise(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default()); Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 0, None).unwrap(); System::note_finished_extrinsics(); - Grandpa::on_finalise(1); + Grandpa::on_finalize(1); - let header = System::finalise(); + let header = System::finalize(); assert_eq!(header.digest, testing::Digest { logs: vec![ RawLog::AuthoritiesChangeSignal(0, vec![(4, 1), (5, 1), (6, 1)]).into(), @@ -55,10 +55,10 @@ fn authorities_change_logged() { #[test] fn authorities_change_logged_after_delay() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { - System::initialise(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default()); Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap(); - Grandpa::on_finalise(1); - let header = System::finalise(); + Grandpa::on_finalize(1); + let header = System::finalize(); assert_eq!(header.digest, testing::Digest { logs: vec![ RawLog::AuthoritiesChangeSignal(1, vec![(4, 1), (5, 1), (6, 1)]).into(), @@ -68,11 +68,11 @@ fn authorities_change_logged_after_delay() { // no change at this height. assert_eq!(System::events(), vec![]); - System::initialise(&2, &header.hash(), &Default::default()); + System::initialize(&2, &header.hash(), &Default::default()); System::note_finished_extrinsics(); - Grandpa::on_finalise(2); + Grandpa::on_finalize(2); - let _header = System::finalise(); + let _header = System::finalize(); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Finalization, @@ -85,27 +85,27 @@ fn authorities_change_logged_after_delay() { #[test] fn cannot_schedule_change_when_one_pending() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { - System::initialise(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default()); Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap(); assert!(Grandpa::pending_change().is_some()); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); - Grandpa::on_finalise(1); - let header = System::finalise(); + Grandpa::on_finalize(1); + let header = System::finalize(); - System::initialise(&2, &header.hash(), &Default::default()); + System::initialize(&2, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().is_some()); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); - Grandpa::on_finalise(2); - let header = System::finalise(); + Grandpa::on_finalize(2); + let header = System::finalize(); - System::initialise(&3, &header.hash(), &Default::default()); + System::initialize(&3, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().is_none()); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok()); - Grandpa::on_finalise(3); - let _header = System::finalise(); + Grandpa::on_finalize(3); + let _header = System::finalize(); }); } @@ -128,7 +128,7 @@ fn new_decodes_from_old() { #[test] fn dispatch_forced_change() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { - System::initialise(&1, &Default::default(), &Default::default()); + System::initialize(&1, &Default::default(), &Default::default()); Grandpa::schedule_change( vec![(4, 1), (5, 1), (6, 1)], 5, @@ -138,60 +138,61 @@ fn dispatch_forced_change() { assert!(Grandpa::pending_change().is_some()); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, Some(0)).is_err()); - Grandpa::on_finalise(1); - let mut header = System::finalise(); + Grandpa::on_finalize(1); + let mut header = System::finalize(); for i in 2..7 { - System::initialise(&i, &header.hash(), &Default::default()); + System::initialize(&i, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().unwrap().forced.is_some()); assert_eq!(Grandpa::next_forced(), Some(11)); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, Some(0)).is_err()); - Grandpa::on_finalise(i); - header = System::finalise(); + Grandpa::on_finalize(i); + header = System::finalize(); } // change has been applied at the end of block 6. // add a normal change. { - System::initialise(&7, &header.hash(), &Default::default()); + System::initialize(&7, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().is_none()); assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok()); - Grandpa::on_finalise(7); - header = System::finalise(); + Grandpa::on_finalize(7); + header = System::finalize(); } // run the normal change. { - System::initialise(&8, &header.hash(), &Default::default()); + System::initialize(&8, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().is_some()); assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]); assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); - Grandpa::on_finalise(8); - header = System::finalise(); + Grandpa::on_finalize(8); + header = System::finalize(); } // normal change applied. but we can't apply a new forced change for some // time. for i in 9..11 { - System::initialise(&i, &header.hash(), &Default::default()); + System::initialize(&i, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().is_none()); assert_eq!(Grandpa::grandpa_authorities(), vec![(5, 1)]); assert_eq!(Grandpa::next_forced(), Some(11)); assert!(Grandpa::schedule_change(vec![(5, 1), (6, 1)], 5, Some(0)).is_err()); - Grandpa::on_finalise(i); - header = System::finalise(); + Grandpa::on_finalize(i); + header = System::finalize(); } { - System::initialise(&11, &header.hash(), &Default::default()); + System::initialize(&11, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().is_none()); assert!(Grandpa::schedule_change(vec![(5, 1), (6, 1), (7, 1)], 5, Some(0)).is_ok()); assert_eq!(Grandpa::next_forced(), Some(21)); - Grandpa::on_finalise(11); - header = System::finalise(); + Grandpa::on_finalize(11); + header = System::finalize(); } + let _ = header; }); } diff --git a/srml/indices/Cargo.toml b/srml/indices/Cargo.toml index 7182514b07d5bab7a822bf6fbb6f49d9d6cfd36d..2331f325d1dd1aaf8fd42559bf143fc65bde7129 100644 --- a/srml/indices/Cargo.toml +++ b/srml/indices/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "3.1", default-features = false } +parity-codec = { version = "3.2", default-features = false } parity-codec-derive = { version = "3.1", default-features = false } substrate-keyring = { path = "../../core/keyring", optional = true } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } @@ -24,7 +24,7 @@ ref_thread_local = "0.0" [features] default = ["std"] std = [ - "serde/std", + "serde", "safe-mix/std", "substrate-keyring", "parity-codec/std", diff --git a/srml/indices/src/address.rs b/srml/indices/src/address.rs index 5e313883e0b5b081347ecd1d0240123e9f447597..c7709e3bec3a5722b0662d141a65c9b494474d6c 100644 --- a/srml/indices/src/address.rs +++ b/srml/indices/src/address.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -54,7 +54,7 @@ impl From for Address(a: T, b: T) -> Option { - if a < b { Some(a) } else { None } + if a < b { Some(b) } else { None } } impl Decode for Address where @@ -108,3 +108,31 @@ impl Default for Address where Address::Id(Default::default()) } } + +#[cfg(test)] +mod tests { + use crate::{Encode, Decode}; + + type Address = super::Address<[u8; 8], u32>; + fn index(i: u32) -> Address { super::Address::Index(i) } + fn id(i: [u8; 8]) -> Address { super::Address::Id(i) } + + fn compare(a: Option
, d: &[u8]) { + if let Some(ref a) = a { + assert_eq!(d, &a.encode()[..]); + } + assert_eq!(Address::decode(&mut &d[..]), a); + } + + #[test] + fn it_should_work() { + compare(Some(index(2)), &[2][..]); + compare(None, &[240][..]); + compare(None, &[252, 239, 0][..]); + compare(Some(index(240)), &[252, 240, 0][..]); + compare(Some(index(304)), &[252, 48, 1][..]); + compare(None, &[253, 255, 255, 0, 0][..]); + compare(Some(index(0x10000)), &[253, 0, 0, 1, 0][..]); + compare(Some(id([42, 69, 42, 69, 42, 69, 42, 69])), &[255, 42, 69, 42, 69, 42, 69, 42, 69][..]); + } +} diff --git a/srml/indices/src/lib.rs b/srml/indices/src/lib.rs index c63f819d35d3f56cab6d9fc3ebf5a383223a26d5..76261796c8b78b6131fb1fb00794b897b473b8c9 100644 --- a/srml/indices/src/lib.rs +++ b/srml/indices/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -198,4 +198,7 @@ impl StaticLookup for Module { fn lookup(a: Self::Source) -> result::Result { Self::lookup_address(a).ok_or("invalid account index") } + fn unlookup(a: Self::Target) -> Self::Source { + address::Address::Id(a) + } } diff --git a/srml/indices/src/mock.rs b/srml/indices/src/mock.rs index 0123bc7fc834017ef134cd15bd68101db62190af..80d3fa2c4fc9d3a4d15e33f607a6d44a03d26ac1 100644 --- a/srml/indices/src/mock.rs +++ b/srml/indices/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/indices/src/tests.rs b/srml/indices/src/tests.rs index 965f155f2926676b90286ab716c58c41956bccff..7b60e305278c58be97d156b0bbffc892afe7b750 100644 --- a/srml/indices/src/tests.rs +++ b/srml/indices/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/metadata/Cargo.toml b/srml/metadata/Cargo.toml index 1bbb8a77df76ece4bf56c62cf201ca6ecd7f081d..eed5e6b4e3379fad722aecc007b46e92ab5d2de3 100644 --- a/srml/metadata/Cargo.toml +++ b/srml/metadata/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } diff --git a/srml/metadata/src/lib.rs b/srml/metadata/src/lib.rs index f47843c871a66d2176726cb019ac1087954d88c8..9b03daafa65d3e81152e0f44e991b0c924e7b85c 100644 --- a/srml/metadata/src/lib.rs +++ b/srml/metadata/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -213,7 +213,7 @@ pub trait DefaultByte { fn default_byte(&self) -> Vec; } -/// Wrapper over dyn pointer for accessing a cached once byet value. +/// Wrapper over dyn pointer for accessing a cached once byte value. #[derive(Clone)] pub struct DefaultByteGetter(pub &'static dyn DefaultByte); @@ -261,7 +261,14 @@ pub enum StorageFunctionType { Map { key: DecodeDifferentStr, value: DecodeDifferentStr, - } + is_linked: bool, + }, + DoubleMap { + key1: DecodeDifferentStr, + key2: DecodeDifferentStr, + value: DecodeDifferentStr, + key2_hasher: DecodeDifferentStr, + }, } /// A storage function modifier. @@ -301,8 +308,12 @@ pub struct RuntimeMetadataPrefixed(pub u32, pub RuntimeMetadata); pub enum RuntimeMetadata { /// Unused; enum filler. V0(RuntimeMetadataDeprecated), - /// Version 1 for runtime metadata. - V1(RuntimeMetadataV1), + /// Version 1 for runtime metadata. No longer used. + V1(RuntimeMetadataDeprecated), + /// Version 2 for runtime metadata. No longer used. + V2(RuntimeMetadataDeprecated), + /// Version 3 for runtime metadata. + V3(RuntimeMetadataV3), } /// Enum that should fail. @@ -322,10 +333,10 @@ impl Decode for RuntimeMetadataDeprecated { } } -/// The metadata of a runtime version 1. +/// The metadata of a runtime. #[derive(Eq, Encode, PartialEq)] #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] -pub struct RuntimeMetadataV1 { +pub struct RuntimeMetadataV3 { pub modules: DecodeDifferentArray, } diff --git a/srml/session/Cargo.toml b/srml/session/Cargo.toml index 8fdd08f1ae652c25c210a2c54d6b2a620d734770..4f1fe086cffdab125a8e59210c14d6858915c28c 100644 --- a/srml/session/Cargo.toml +++ b/srml/session/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "3.1", default-features = false } +parity-codec = { version = "3.2", default-features = false } parity-codec-derive = { version = "3.1", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } @@ -20,11 +20,12 @@ timestamp = { package = "srml-timestamp", path = "../timestamp", default-feature [dev-dependencies] substrate-primitives = { path = "../../core/primitives" } runtime_io = { package = "sr-io", path = "../../core/sr-io" } +lazy_static = "1.0" [features] default = ["std"] std = [ - "serde/std", + "serde", "safe-mix/std", "parity-codec/std", "parity-codec-derive/std", diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs index 13f2a4cd0ae00cac41452a51ad9c9a912b054197..204eaccc1f94befa5ba604c2531c0a62d7e1c9f9 100644 --- a/srml/session/src/lib.rs +++ b/srml/session/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -50,8 +50,8 @@ macro_rules! impl_session_change { for_each_tuple!(impl_session_change); -pub trait Trait: timestamp::Trait { - type ConvertAccountIdToSessionKey: Convert; +pub trait Trait: timestamp::Trait + consensus::Trait { + type ConvertAccountIdToSessionKey: Convert>; type OnSessionChange: OnSessionChange; type Event: From> + Into<::Event>; } @@ -78,13 +78,12 @@ decl_module! { Self::apply_force_new_session(apply_rewards) } - fn on_finalise(n: T::BlockNumber) { + fn on_finalize(n: T::BlockNumber) { Self::check_rotate_session(n); } } } -/// An event in this module. decl_event!( pub enum Event where ::BlockNumber { /// New session has happened. Note that the argument is the session index, not the block @@ -104,7 +103,7 @@ decl_storage! { /// Timestamp when current session started. pub CurrentStart get(current_start) build(|_| T::Moment::zero()): T::Moment; - /// New session is being forced is this entry exists; in which case, the boolean value is whether + /// New session is being forced if this entry exists; in which case, the boolean value is whether /// the new session should be considered a normal rotation (rewardable) or exceptional (slashable). pub ForcingNewSession get(forcing_new_session): Option; /// Block at which the session length last changed. @@ -122,12 +121,12 @@ decl_storage! { } impl Module { - /// The number of validators currently. + /// The current number of validators. pub fn validator_count() -> u32 { >::get().len() as u32 } - /// The last length change, if there was one, zero if not. + /// 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) } @@ -141,7 +140,7 @@ impl Module { /// Set the current set of validators. /// - /// Called by `staking::new_era()` only. `rotate_session` must be called after this in order to + /// Called by `staking::new_era` only. `rotate_session` must 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()); @@ -149,9 +148,9 @@ impl Module { /// Hook to be called after transaction processing. pub fn check_rotate_session(block_number: T::BlockNumber) { - // do this last, after the staking system has had chance to switch out the authorities for the + // Do this last, after the staking system has had the chance to switch out the authorities for the // new set. - // check block number and call next_session if necessary. + // Check block number and call `rotate_session` if necessary. let is_final_block = ((block_number - Self::last_length_change()) % Self::length()).is_zero(); let (should_end_session, apply_rewards) = >::take() .map_or((is_final_block, is_final_block), |apply_rewards| (true, apply_rewards)); @@ -160,7 +159,7 @@ impl Module { } } - /// Move onto next session: register the new authority set. + /// Move on to next session: register the new authority set. pub fn rotate_session(is_final_block: bool, apply_rewards: bool) { let now = >::get(); let time_elapsed = now.clone() - Self::current_start(); @@ -187,24 +186,27 @@ impl Module { T::OnSessionChange::on_session_change(time_elapsed, apply_rewards); // Update any changes in session keys. - for (i, v) in Self::validators().into_iter().enumerate() { + let v = Self::validators(); + >::set_authority_count(v.len() as u32); + for (i, v) in v.into_iter().enumerate() { >::set_authority( i as u32, &>::get(&v) - .unwrap_or_else(|| T::ConvertAccountIdToSessionKey::convert(v)) + .or_else(|| T::ConvertAccountIdToSessionKey::convert(v)) + .unwrap_or_default() ); }; } /// Get the time that should have elapsed over a session if everything was working perfectly. pub fn ideal_session_duration() -> T::Moment { - let block_period: T::Moment = >::block_period(); + let block_period: T::Moment = >::minimum_period(); let session_length: T::BlockNumber = Self::length(); Mul::::mul(block_period, session_length) } /// Number of blocks remaining in this session, not counting this one. If the session is - /// due to rotate at the end of this block, then it will return 0. If the just began, then + /// due to rotate at the end of this block, then it will return 0. If the session just began, then /// it will return `Self::length() - 1`. pub fn blocks_remaining() -> T::BlockNumber { let length = Self::length(); @@ -223,6 +225,7 @@ impl OnFreeBalanceZero for Module { #[cfg(test)] mod tests { use super::*; + use std::cell::RefCell; use srml_support::{impl_outer_origin, assert_ok}; use runtime_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; @@ -234,6 +237,17 @@ mod tests { pub enum Origin for Test {} } + thread_local!{ + static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); + } + + pub struct TestOnSessionChange; + impl OnSessionChange for TestOnSessionChange { + fn on_session_change(_elapsed: u64, _should_reward: bool) { + NEXT_VALIDATORS.with(|v| Session::set_validators(&*v.borrow())); + } + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl consensus::Trait for Test { @@ -249,7 +263,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; @@ -260,7 +274,7 @@ mod tests { } impl Trait for Test { type ConvertAccountIdToSessionKey = ConvertUintAuthorityId; - type OnSessionChange = (); + type OnSessionChange = TestOnSessionChange; type Event = (); } @@ -272,14 +286,14 @@ mod tests { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(consensus::GenesisConfig::{ code: vec![], - authorities: vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)], + authorities: NEXT_VALIDATORS.with(|l| l.borrow().iter().cloned().map(UintAuthorityId).collect()), }.build_storage().unwrap().0); t.extend(timestamp::GenesisConfig::{ - period: 5, + minimum_period: 5, }.build_storage().unwrap().0); t.extend(GenesisConfig::{ session_length: 2, - validators: vec![1, 2, 3], + validators: NEXT_VALIDATORS.with(|l| l.borrow().clone()), keys: vec![], }.build_storage().unwrap().0); runtime_io::TestExternalities::new(t) @@ -288,12 +302,35 @@ mod tests { #[test] fn simple_setup_should_work() { with_externalities(&mut new_test_ext(), || { - assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1).into(), UintAuthorityId(2).into(), UintAuthorityId(3).into()]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); assert_eq!(Session::length(), 2); assert_eq!(Session::validators(), vec![1, 2, 3]); }); } + #[test] + fn authorities_should_track_validators() { + with_externalities(&mut new_test_ext(), || { + NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2]); + assert_ok!(Session::force_new_session(false)); + Session::check_rotate_session(1); + assert_eq!(Session::validators(), vec![1, 2]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); + + NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2, 4]); + assert_ok!(Session::force_new_session(false)); + Session::check_rotate_session(2); + assert_eq!(Session::validators(), vec![1, 2, 4]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(4)]); + + NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2, 3]); + assert_ok!(Session::force_new_session(false)); + Session::check_rotate_session(3); + assert_eq!(Session::validators(), vec![1, 2, 3]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + }); + } + #[test] fn should_work_with_early_exit() { with_externalities(&mut new_test_ext(), || { diff --git a/srml/staking/Cargo.toml b/srml/staking/Cargo.toml index 5fc70e27ea688fc1ac0e68dd24f56b67b19d1664..967cee3391f08fe8b323fb1d65ef917e5bb75495 100644 --- a/srml/staking/Cargo.toml +++ b/srml/staking/Cargo.toml @@ -6,11 +6,12 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-keyring = { path = "../../core/keyring", optional = true } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } consensus = { package = "srml-consensus", path = "../consensus", default-features = false } @@ -19,18 +20,18 @@ session = { package = "srml-session", path = "../session", default-features = fa [dev-dependencies] substrate-primitives = { path = "../../core/primitives" } -runtime_io = { package = "sr-io", path = "../../core/sr-io" } timestamp = { package = "srml-timestamp", path = "../timestamp" } balances = { package = "srml-balances", path = "../balances" } [features] default = ["std"] std = [ - "serde/std", + "serde", "safe-mix/std", "substrate-keyring", "parity-codec/std", "rstd/std", + "runtime_io/std", "srml-support/std", "primitives/std", "session/std", diff --git a/srml/staking/Staking.md b/srml/staking/Staking.md deleted file mode 100644 index 160349656bd9e565dbbdd71231f1303c7621dff2..0000000000000000000000000000000000000000 --- a/srml/staking/Staking.md +++ /dev/null @@ -1,62 +0,0 @@ -# Module Summary, Description and Specification - -## Staking - -The staking module is the means by which a set of network maintainers (known as "authorities" in some contexts and "validators" in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under normal operation but are held at pain of "slash" (expropriation) should they be found not to bee discharhing their duties properly. - -### Vocabulary - -- Staking: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a rewarded maintainer of the network. -- Validating: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. -- Nominating: The process of placing staked funds behind one or more validators in order to share in any reward, and punishment, they take. -- Stash account: The account holding an owner's funds used for staking. -- Controller account: The account which controls am owner's funds for staking. -- Era: A (whole) number of sessions which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. -- Slash: The punishment of a staker by reducing their funds. - -### Goals - -The staking system in Substrate NPoS is designed to achieve three goals: -- It should be possible to stake funds that are controlled by a cold wallet. -- It should be possible to withdraw some, or deposit more, funds without interrupting the role of t. -- It should be possible to switch between roles (nominator, validator, idle) with minimal overhead. - -### Stash account - -To achieve these goals, Substrate NPoS distinguishes the act of staking from the act of declaring the role (nominating or validating) desired. An owner of funds wanting to validate or nominate must first deposit some or all of an account's balance to be managed by the staking system. When they do this, we call it *staking* and we say the funds are *under management* and *bonded*. A transaction-dispatchable call `bond` is provided for this. Once an account has funds bonded, those funds may no longer be transfered out or deducted in any way, including for transaction fees payment. If all funds of the account are thus used, then the account is effectively locked since it is unable to pay for any transactions. - -Since the funds under management may be entirely frozen, and quite possibly controlled only by an offline cold wallet device, another account is used to control the staking activity of these funds. At the point of staking an account, this account is declared. Whereas the account holding the funds under management is known as the *stash*, the second account that controls the staking activity is called the *controller* account. Once staked, the stash account has no further transactional interaction with the staking module; all transactions regarding the staking activity of the stash are signed with the controller account. If there are unmanaged funds, then non-staking transactions may still be issued from the stash account, such as transfering funds out with the balances module. - -### Controller account - -Once the stash account's funds are committed under management of the staking system, then the controller account takes over. Three operations allow the owner to control their role in the staking system, switching between idle (no role at all) with the `chill` call; switching to a validator role with the `validate` call; and finally switching to the nominator role with `nominate`. In the case of the latter, the set of validators they are happy to entrust their stake to is also provided. The effect of these operations is felt at the next point that the nominator/validator set is recalculated, which will usually be at the end of the current era. - -Three further operations are provided for the fund management: two for withdrawing funds that are under management of the staking system `unbond` and `withdraw_unbonded`, and another for introducing additional funds under management, `bond_extra`. Regarding the withdrawal of funds, the funds become inactive in the staking system from the era following the `unbond` call, however they may not be transfered out of the account (by a normal transfer operation using the stash key) until the bonding period has ended. At that point, the `withdraw_unbonded` must be called before the funds are free to bee used. - -Funds deposited into the stash account will not automatically be introduced under management of the staking system: They may be retransfered out of the stash account normally until they enter under management. If there is a desire to bring such funds not yet under managment into the staking system, a separate transaction calling `bond_extra` must be issued to do this. - -### Validating - -A `validate` transaction takes a parameter of type `ValidatorPrefs`; this encodes a set of options available to validators. There are two options here: the `unstake_threshold` and `validator_payment`. The former allows a validator to control how long they acrue punishment for being offline before they are finally removed from the validator list and have the slash deducted. There is a tradeoff between being removed from the validator set early and thus missing out on an era's rewards and risking a much more substantial punishment as the slash amount increases exponentially with each offline infraction. - -The latter option, `validator_payment`, allows a validator to reserve some amount of funds for themselves before the rest is shared out, *pro rata* amongst itself and the nominators. By "default", this is zero which means the validator and nominators partake in the rewards equally. However, by raising this, the validator may reserve some of the funds for themselves, making them a less attractive financial proposal compared to other less "greedy" validators. This allows over-subscribed validators to monetise their reputation and provides a macroeconomic mechanism of redistributing nominations between different validators. - -### Nonminating - -A `nominate` transaction take a single parameter which is the set of validator identities the nominator approves of their stake backing. Nomination does not allow control of *how much* of the stake backs any individual validator. If a staker wishes to have such fine-grained control, they could split their funds between several accounts and stake each individually to effect such a arrangement. - -At the beginning of each era, each staker's funds is automatically allocated between some or all of each of their nominated validators, possibly with some (or, in extremis all) left unallocated. Only the portion of their stake that is allocated generates rewards and is at risk of slashing. - -When an era begins, a basic usage of the Phragmén method gives an initial allocation. Over some initial period (perhaps one session) in the era, third-parties may submit their own solutions (typically determined by running Phragmén more extensively) in order to further optimise the allocation between nominators and validators. At the end of the initial period, the allocation is fixed for the rest of the era. During the initial period, any slashing uses the initial, suboptimal allocations. - -### Rewards & Payouts - -At the end of each successful session, a reward is accrued according to the overall timeliness of blocks. If the session's aveerage block period was optimal, then the maximum reward is accrued; the fewer blocks producted, the lower the reward. At the end of each era, each validator is paid this overall reward into an account of their choosing. Nominator portions are distributed *pro rata* for the amount of stake backing that validator and according to the validator's preferences. - -There are three possible payment destinations or `Payee`s and this is set during the call to `bond` and may be updated by dispatching a `set_payee` transaction. The `Controller` payee places rewards into the controller account. The `Stash` and `Staked` targets both place rewards into the stash account, but the latter also places the rewards immediately under management. - -### Slashing - -Slashing happens when a validator has misbehaved in some way. Funds may be slashed up until the point they are withdrawn from management (using the `withdraw_unbonded` call). Digests of validator and nominator arrangements are recorded in order to ensure that historical misbehaviour can be properly attributed to stakes and punished. - -For a slash on some validator balance and associated nominator balances, the validator balance is reduced at preference. If the slash amount is greater than that which the validator has at stake, then the nominators balances are reduced pro rata for the remainder. \ No newline at end of file diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 71a7f27ce16120e36c56a8624d220e385aa4ee4a..32b44f0264bd818b73907288570dd64f39db59d6 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -6,8 +6,6 @@ // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. - - // Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -16,31 +14,283 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Staking manager: Periodically determines the best set of validators. +//! # Staking Module +//! +//! +//! The staking module is the means by which a set of network maintainers (known as _authorities_ in some contexts and _validators_ in others) +//! are chosen based upon those who voluntarily place funds under deposit. Under deposit, those funds are rewarded under +//! normal operation but are held at pain of _slash_ (expropriation) should the staked maintainer be found not to be +//! discharging their duties properly. +//! +//! You can start using the Staking module by implementing the staking [`Trait`]. +//! +//! ## Overview +//! +//! ### Terminology +//! +//! +//! - Staking: The process of locking up funds for some time, placing them at risk of slashing (loss) in order to become a rewarded maintainer of the network. +//! - Validating: The process of running a node to actively maintain the network, either by producing blocks or guaranteeing finality of the chain. +//! - Nominating: The process of placing staked funds behind one or more validators in order to share in any reward, and punishment, they take. +//! - Stash account: The account holding an owner's funds used for staking. +//! - Controller account: The account which controls an owner's funds for staking. +//! - Era: A (whole) number of sessions, which is the period that the validator set (and each validator's active nominator set) is recalculated and where rewards are paid out. +//! - Slash: The punishment of a staker by reducing their funds. +//! +//! ### Goals +//! +//! +//! The staking system in Substrate NPoS is designed to achieve three goals: +//! +//! - It should be possible to stake funds that are controlled by a cold wallet. +//! - It should be possible to withdraw some, or deposit more, funds without interrupting the role of an entity. +//! - It should be possible to switch between roles (nominator, validator, idle) with minimal overhead. +//! +//! ### Scenarios +//! +//! #### Staking +//! +//! Almost any interaction with the staking module requires a process of _**bonding**_ (also known as +//! being a _staker_). To become *bonded* a fund-holding account known as the _stash account_, which holds some of all of the +//! funds that become frozen in place as part of the staking process, is paired with an active **controller** account which issues +//! instructions on how they shall be used. +//! +//! An account pair can become bonded using the [`bond`](./enum.Call.html#variant.bond) call. +//! +//! Stash accounts can change their associated controller using the [`set_controller`](./enum.Call.html#variant.set_controller) call. +//! +//! There are three possible roles that any staked account pair can be in: `Validator`, `Nominator` and `Idle` (defined in [`StakerStatus`]). There are +//! three corresponding instructions to change between roles, namely: +//! [`validate`](./enum.Call.html#variant.validate), [`nominate`](./enum.Call.html#variant.nominate) and [`chill`](./enum.Call.html#variant.chill). +//! +//! #### Validating +//! +//! A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of +//! the network. A validator should avoid both any sort of malicious misbehavior and going offline. +//! Bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they +//! are declared as a _candidate_ and they _might_ get elected at the _next era_ as a validator. The result of the +//! election is determined by nominators and their votes. +//! +//! An account can become a validator candidate via the [`validate`](./enum.Call.html#variant.validate) call. +//! +//! #### Nomination +//! +//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators +//! to be elected. Once interest in nomination is stated by an account, it takes effect at the next election round. The +//! funds in the nominator's stash account indicate the _weight_ of its vote. +//! Both the rewards and any punishment that a validator earns are shared between the validator and its nominators. +//! This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply +//! because the nominators will also lose funds if they vote poorly. +//! +//! An account can become a nominator via the [`nominate`](enum.Call.html#variant.nominate) call. +//! +//! #### Rewards and Slash +//! +//! The **reward and slashing** procedure is the core of the staking module, attempting to _embrace valid behavior_ +//! while _punishing any misbehavior or lack of availability_. +//! +//! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is determined, a value is +//! deducted from the balance of the validator and all the nominators who voted for this validator (values are deducted from the _stash_ account of the slashed entity). +//! +//! Similar to slashing, rewards are also shared among a validator and its associated nominators. +//! Yet, the reward funds are not always transferred to the stash account and can be configured. See [Reward Calculation](#reward-calculation) +//! for more details. +//! +//! #### Chilling +//! +//! Finally, any of the roles above can choose to step back temporarily and just chill for a while. This means that if +//! they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer +//! be a candidate for the next election. +//! +//! An account can step back via the [`chill`](enum.Call.html#variant.chill) call. +//! +//! ## Interface +//! +//! ### Dispatchable +//! +//! The Dispatchable functions of the staking module enable the steps needed for entities to accept and change their +//! role, alongside some helper functions to get/set the metadata of the module. +//! +//! Please refer to the [`Call`] enum and its associated variants for a detailed list of dispatchable functions. +//! +//! ### Public +//! The staking module contains many public storage items and (im)mutable functions. Please refer to the [struct list](#structs) +//! below and the [`Module`] struct definition for more details. +//! +//! ## Usage +//! +//! +//! ### Snippet: Bonding and Accepting Roles +//! +//! An arbitrary account pair, given that the associated stash has the required funds, can become stakers via the following call: +//! +//! ```rust,ignore +//! // bond account 3 as stash +//! // account 4 as controller +//! // with stash value 1500 units +//! // while the rewards get transferred to the controller account. +//! Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller); +//! ``` +//! +//! To state desire to become a validator: +//! +//! ```rust,ignore +//! // controller account 4 states desire for validation with the given preferences. +//! Staking::validate(Origin::signed(4), ValidatorPrefs::default()); +//! ``` +//! +//! Similarly, to state desire in nominating: +//! +//! ```rust,ignore +//! // controller account 4 nominates for account 10 and 20. +//! Staking::nominate(Origin::signed(4), vec![20, 10]); +//! ``` +//! +//! Finally, account 4 can withdraw from any of the above roles via +//! +//! ```rust,ignore +//! Staking::chill(Origin::signed(4)); +//! ``` +//! +//! You can find the equivalent of the above calls in your [Substrate UI](https://substrate-ui.parity.io). +//! ### Snippet: Reporting Misbehavior +//! +//! ``` +//! use srml_support::{decl_module, dispatch::Result}; +//! use system::ensure_signed; +//! use srml_staking::{self as staking}; +//! +//! pub trait Trait: staking::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! /// Report whoever calls this function as offline once. +//! pub fn report_sender(origin) -> Result { +//! let reported = ensure_signed(origin)?; +//! >::on_offline_validator(reported, 1); +//! Ok(()) +//! } +//! } +//! } +//! # fn main() { } +//! ``` +//! +//! ## Implementation Details +//! +//! ### Slot Stake +//! +//! The term [`SlotStake`] will be used throughout this section. It refers to a value calculated at the end of each era, +//! containing the _minimum value at stake among all validators._ Note that a validator's value at stake might be a combination of +//! The validator's own stake and the votes it received. See [`Exposure`] for more details. +//! +//! ### Reward Calculation +//! +//! Rewards are recorded **per-session** and paid **per-era**. The value of the reward for each session is calculated at +//! the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of +//! the new _per-session-reward_ is calculated at the end of each era by multiplying [`SlotStake`] and [`SessionReward`] +//! (`SessionReward` is the multiplication factor, represented by a number between 0 and 1). +//! Once a new era is triggered, rewards are paid to the validators and the associated nominators. +//! +//! The validator can declare an amount, named [`validator_payment`](./struct.ValidatorPrefs.html#structfield.validator_payment), that does not get shared with the nominators at +//! each reward payout through their [`ValidatorPrefs`]. This value gets deducted from the total reward that can be paid. +//! The remaining portion is split among the validator and all of the nominators that nominated the validator, +//! proportional to the value staked behind this validator +//! (_i.e._ dividing the [`own`](./struct.Exposure.html#structfield.own) or [`others`](./struct.Exposure.html#structfield.others) by [`total`](./struct.Exposure.html#structfield.total) in [`Exposure`]). +//! +//! All entities who receive a reward have the option to choose their reward destination, +//! through the [`Payee`] storage item (see [`set_payee`](enum.Call.html#variant.set_payee)), to be one of the following: +//! +//! - Controller account, (obviously) not increasing the staked value. +//! - Stash account, not increasing the staked value. +//! - Stash account, also increasing the staked value. +//! +//! ### Slashing details +//! +//! A validator can be _reported_ to be offline at any point via [`on_offline_validator`](enum.Call.html#variant.on_offline_validator) public function. +//! Each validator declares how many times it can be _reported_ before it actually gets slashed via their +//! `unstake_threshold` in [`ValidatorPrefs`]. +//! +//! On top of this, staking module also introduces an [`OfflineSlashGrace`], which applies to all validators and prevents +//! them from getting immediately slashed. +//! +//! Essentially, a validator gets slashed once they have been reported more than [`OfflineSlashGrace`] + [`unstake_threshold`](./struct.ValidatorPrefs.html#structfield.unstake_threshold) times. +//! Getting slashed due to offline report always leads to being _unstaked_ (_i.e._ removed as a validator candidate) as the consequence. +//! +//! The base slash value is computed _per slash-event_ by multiplying [`OfflineSlash`] and the `total` [`Exposure`]. This value +//! is then multiplied by `2.pow(unstake_threshold)` to obtain the final slash value. +//! All individual accounts' punishments are capped at their total stake (NOTE: This cap should never come into force in a correctly implemented, non-corrupted, well-configured system). +//! +//! ### Additional Fund Management Operations +//! +//! Any funds already placed into stash can be the target of the following operations: +//! +//! The controller account can free a portion (or all) of the funds using the [`unbond`](enum.Call.html#variant.unbond) call. +//! Note that the funds are not immediately accessible. Instead, a duration denoted by [`BondingDuration`] (in number of eras) +//! must pass until the funds can actually be removed. Once the [`BondingDuration`] is over the [`withdraw_unbonded`]((enum.Call.html#variant.withdraw_unbonded)) call can be used +//! to actually withdraw the funds. +//! +//!### Election Algorithm +//! +//! The current election algorithm is implemented based on Phragmén. +//! The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS). +//! +//! The election algorithm, aside from electing the validators with the most stake value and votes, tries to divide the nominator votes +//! among candidates in an equal manner. To further assure this, an optional post-processing can be applied that iteratively normalizes the nominator staked values +//! until the total difference among votes of a particular nominator are less than a threshold. +//! +//! +//! ## GenesisConfig +//! +//! See the [`GenesisConfig`] for a list of attributes that can be provided. +//! +//! ## Related Modules +//! +//! - [**Balances**](https://crates.parity.io/srml_balances/index.html): Used to manage values at stake. +//! - [**Sessions**](https://crates.parity.io/srml_session/index.html): Used to manage sessions. Also, a list of new validators is also stored in the sessions module's `Validators` at the end of each era. +//! - [**System**](https://crates.parity.io/srml_system/index.html): Used to obtain block number and time, among other details. +//! #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "std")] +use runtime_io::with_storage; use rstd::{prelude::*, result}; use parity_codec::{HasCompact, Encode, Decode}; use srml_support::{StorageValue, StorageMap, EnumerableStorageMap, dispatch::Result}; use srml_support::{decl_module, decl_event, decl_storage, ensure}; use srml_support::traits::{ - Currency, OnDilution, EnsureAccountLiquid, OnFreeBalanceZero, WithdrawReason, ArithmeticType + Currency, OnFreeBalanceZero, OnDilution, LockIdentifier, LockableCurrency, WithdrawReasons, + OnUnbalanced, Imbalance, }; use session::OnSessionChange; use primitives::Perbill; -use primitives::traits::{Zero, One, As, StaticLookup, Saturating}; +use primitives::traits::{Convert, Zero, One, As, StaticLookup, CheckedSub, Saturating, Bounded}; +#[cfg(feature = "std")] +use primitives::{Serialize, Deserialize}; use system::ensure_signed; mod mock; - mod tests; +mod phragmen; + +use phragmen::{elect, ElectionConfig}; const RECENT_OFFLINE_COUNT: usize = 32; const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4; const MAX_NOMINATIONS: usize = 16; const MAX_UNSTAKE_THRESHOLD: u32 = 10; +/// Indicates the initial status of the staker. +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub enum StakerStatus { + /// Chilling. + Idle, + /// Declared desire in validating or already participating in it. + Validator, + /// Nominating for a group of other stakers. + Nominator(Vec), +} + /// A destination account for payment. #[derive(PartialEq, Eq, Copy, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] @@ -111,7 +361,11 @@ pub struct StakingLedger>, } -impl StakingLedger { +impl< + AccountId, + Balance: HasCompact + Copy + Saturating, + BlockNumber: HasCompact + PartialOrd +> StakingLedger { /// Remove entries from `unlocking` that are sufficiently old and reduce the /// total by the sum of their balances. fn consolidate_unlocked(self, current_era: BlockNumber) -> Self { @@ -132,7 +386,7 @@ impl { - /// Which nominator. + /// The stash account of the nominator in question. who: AccountId, /// Amount of funds exposed. #[codec(compact)] @@ -153,19 +407,35 @@ pub struct Exposure { pub others: Vec>, } -type BalanceOf = <::Currency as ArithmeticType>::Type; +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type PositiveImbalanceOf = <::Currency as Currency<::AccountId>>::PositiveImbalance; +type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; pub trait Trait: system::Trait + session::Trait { /// The staking balance. - type Currency: ArithmeticType + Currency>; + type Currency: + Currency + + LockableCurrency; + + /// Convert a balance into a number used for election calculation. + /// This must fit into a `u64` but is allowed to be sensibly lossy. + type CurrencyToVote: Convert, u64> + Convert>; /// Some tokens minted. type OnRewardMinted: OnDilution>; /// The overarching event type. type Event: From> + Into<::Event>; + + /// Handler for the unbalanced reduction when slashing a staker. + type Slash: OnUnbalanced>; + + /// Handler for the unbalanced increment when rewarding a staker. + type Reward: OnUnbalanced>; } +const STAKING_ID: LockIdentifier = *b"staking "; + decl_storage! { trait Store for Module as Staking { @@ -184,76 +454,46 @@ decl_storage! { /// The length of the bonding duration in blocks. pub BondingDuration get(bonding_duration) config(): T::BlockNumber = T::BlockNumber::sa(1000); - // TODO: remove once Alex/CC updated #1785 - pub Invulerables get(invulerables): Vec; - - /// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're easy to initialise + /// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're easy to initialize /// and the performance hit is minimal (we expect no more than four invulnerables) and restricted to testnets. pub Invulnerables get(invulnerables) config(): Vec; /// Map from all locked "stash" accounts to the controller account. - pub Bonded get(bonded) build(|config: &GenesisConfig| { - config.stakers.iter().map(|(stash, controller, _)| (stash.clone(), controller.clone())).collect::>() - }): map T::AccountId => Option; + pub Bonded get(bonded): map T::AccountId => Option; /// Map from all (unlocked) "controller" accounts to the info regarding the staking. - pub Ledger get(ledger) build(|config: &GenesisConfig| { - config.stakers.iter().map(|(stash, controller, value)| ( - controller.clone(), - StakingLedger { - stash: stash.clone(), - total: *value, - active: *value, - unlocking: Vec::, T::BlockNumber>>::new(), - }, - )).collect::>() - }): map T::AccountId => Option, T::BlockNumber>>; - - /// Where the reward payment should be made. + pub Ledger get(ledger): map T::AccountId => Option, T::BlockNumber>>; + + /// Where the reward payment should be made. Keyed by stash. pub Payee get(payee): map T::AccountId => RewardDestination; - /// The set of keys are all controllers that want to validate. - /// - /// The values are the preferences that a validator has. - pub Validators get(validators) build(|config: &GenesisConfig| { - config.stakers.iter().map(|(_stash, controller, _value)| ( - controller.clone(), - ValidatorPrefs::>::default(), - )).collect::>() - }): linked_map T::AccountId => ValidatorPrefs>; - - /// The set of keys are all controllers that want to nominate. - /// - /// The value are the nominations. + /// The map from (wannabe) validator stash key to the preferences of that validator. + pub Validators get(validators): linked_map T::AccountId => ValidatorPrefs>; + + /// The map from nominator stash key to the set of stash keys of all validators to nominate. pub Nominators get(nominators): linked_map T::AccountId => Vec; /// Nominators for a particular account that is in action right now. You can't iterate through validators here, /// but you can find them in the `sessions` module. - pub Stakers get(stakers) build(|config: &GenesisConfig| { - config.stakers.iter().map(|(_stash, controller, value)| ( - controller.clone(), - Exposure { - total: *value, - own: *value, - others: Vec::>::new(), - }, - )).collect::>() - }): map T::AccountId => Exposure>; + /// + /// This is keyed by the stash account. + pub Stakers get(stakers): map T::AccountId => Exposure>; // The historical validators and their nominations for a given era. Stored as a trie root of the mapping // `T::AccountId` => `Exposure>`, which is just the contents of `Stakers`, // under a key that is the `era`. - // + // // Every era change, this will be appended with the trie root of the contents of `Stakers`, and the oldest // entry removed down to a specific number of entries (probably around 90 for a 3 month history). -// pub HistoricalStakers get(historical_stakers): map T::BlockNumber => Option; + // pub HistoricalStakers get(historical_stakers): map T::BlockNumber => Option; + + /// The currently elected validator set keyed by stash account ID. + pub CurrentElected get(current_elected): Vec; /// The current era index. pub CurrentEra get(current_era) config(): T::BlockNumber; /// Maximum reward, per validator, that is provided per acceptable session. pub CurrentSessionReward get(current_session_reward) config(): BalanceOf; - /// Slash, per validator that is taken for the first time they are found to be offline. - pub CurrentOfflineSlash get(current_offline_slash) config(): BalanceOf; /// The accumulated reward for the current era. Reset to zero at the beginning of the era and /// increased for every successfully finished session. @@ -268,7 +508,7 @@ decl_storage! { /// /// This is used to derive rewards and punishments. pub SlotStake get(slot_stake) build(|config: &GenesisConfig| { - config.stakers.iter().map(|&(_, _, value)| value).min().unwrap_or_default() + config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() }): BalanceOf; /// The number of times a given validator has been reported offline. This gets decremented by one each era that passes. @@ -281,7 +521,35 @@ decl_storage! { pub RecentlyOffline get(recently_offline): Vec<(T::AccountId, T::BlockNumber, u32)>; } add_extra_genesis { - config(stakers): Vec<(T::AccountId, T::AccountId, BalanceOf)>; + config(stakers): Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; + build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| { + with_storage(storage, || { + for &(ref stash, ref controller, balance, ref status) in &config.stakers { + assert!(T::Currency::free_balance(&stash) >= balance); + let _ = >::bond( + T::Origin::from(Some(stash.clone()).into()), + T::Lookup::unlookup(controller.clone()), + balance, + RewardDestination::Staked + ); + let _ = match status { + StakerStatus::Validator => { + >::validate( + T::Origin::from(Some(controller.clone()).into()), + Default::default() + ) + }, StakerStatus::Nominator(votes) => { + >::nominate( + T::Origin::from(Some(controller.clone()).into()), + votes.iter().map(|l| {T::Lookup::unlookup(l.clone())}).collect() + ) + }, _ => Ok(()) + }; + } + + >::select_validators(); + }); + }); } } @@ -291,6 +559,8 @@ decl_module! { /// Take the origin account as a stash and lock up `value` of its balance. `controller` will be the /// account that controls it. + /// + /// The dispatch origin for this call must be _Signed_ by the stash account. fn bond(origin, controller: ::Source, #[compact] value: BalanceOf, payee: RewardDestination) { let stash = ensure_signed(origin)?; @@ -300,46 +570,52 @@ decl_module! { let controller = T::Lookup::lookup(controller)?; + if >::exists(&controller) { + return Err("controller already paired") + } + // You're auto-bonded forever, here. We might improve this by only bonding when // you actually validate/nominate. >::insert(&stash, controller.clone()); + >::insert(&stash, payee); let stash_balance = T::Currency::free_balance(&stash); let value = value.min(stash_balance); - - >::insert(&controller, StakingLedger { stash, total: value, active: value, unlocking: vec![] }); - >::insert(&controller, payee); + Self::update_ledger(&controller, &StakingLedger { stash, total: value, active: value, unlocking: vec![] }); } /// Add some extra amount that have appeared in the stash `free_balance` into the balance up for /// staking. - /// + /// /// Use this if there are additional funds in your stash account that you wish to bond. - /// - /// NOTE: This call must be made by the controller, not the stash. - fn bond_extra(origin, max_additional: BalanceOf) { - let controller = ensure_signed(origin)?; + /// + /// The dispatch origin for this call must be _Signed_ by the stash, not the controller. + fn bond_extra(origin, #[compact] max_additional: BalanceOf) { + let stash = ensure_signed(origin)?; + + let controller = Self::bonded(&stash).ok_or("not a stash")?; let mut ledger = Self::ledger(&controller).ok_or("not a controller")?; - let stash_balance = T::Currency::free_balance(&ledger.stash); - if stash_balance > ledger.total { - let extra = (stash_balance - ledger.total).min(max_additional); + let stash_balance = T::Currency::free_balance(&stash); + + if let Some(extra) = stash_balance.checked_sub(&ledger.total) { + let extra = extra.min(max_additional); ledger.total += extra; ledger.active += extra; - >::insert(&controller, ledger); + Self::update_ledger(&controller, &ledger); } } /// Schedule a portion of the stash to be unlocked ready for transfer out after the bond - /// period ends. If this leaves an amount actively bonded less than + /// period ends. If this leaves an amount actively bonded less than /// T::Currency::existential_deposit(), then it is increased to the full amount. - /// + /// /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move - /// the funds out of management ready for transfer. - /// - /// NOTE: This call must be made by the controller, not the stash. - /// - /// See also `withdraw_unbonded`. + /// the funds out of management ready for transfer. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// + /// See also [`Call::withdraw_unbonded`]. fn unbond(origin, #[compact] value: BalanceOf) { let controller = ensure_signed(origin)?; let mut ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -350,84 +626,106 @@ decl_module! { ledger.active -= value; // Avoid there being a dust balance left in the staking system. - let ed = T::Currency::minimum_balance(); - if ledger.active < ed { + if ledger.active < T::Currency::minimum_balance() { value += ledger.active; ledger.active = Zero::zero(); } let era = Self::current_era() + Self::bonding_duration(); ledger.unlocking.push(UnlockChunk { value, era }); - >::insert(&controller, ledger); + Self::update_ledger(&controller, &ledger); } } /// Remove any unlocked chunks from the `unlocking` queue from our management. - /// + /// /// This essentially frees up that balance to be used by the stash account to do /// whatever it wants. - /// - /// NOTE: This call must be made by the controller, not the stash. - /// - /// See also `unbond`. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// + /// See also [`Call::unbond`]. fn withdraw_unbonded(origin) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or("not a controller")?; - >::insert(&controller, ledger.consolidate_unlocked(Self::current_era())); + let ledger = ledger.consolidate_unlocked(Self::current_era()); + Self::update_ledger(&controller, &ledger); } /// Declare the desire to validate for the origin controller. /// /// Effects will be felt at the beginning of the next era. - /// - /// NOTE: This call must be made by the controller, not the stash. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn validate(origin, prefs: ValidatorPrefs>) { let controller = ensure_signed(origin)?; - let _ledger = Self::ledger(&controller).ok_or("not a controller")?; + let ledger = Self::ledger(&controller).ok_or("not a controller")?; + let stash = &ledger.stash; ensure!(prefs.unstake_threshold <= MAX_UNSTAKE_THRESHOLD, "unstake threshold too large"); - >::remove(&controller); - >::insert(controller, prefs); + >::remove(stash); + >::insert(stash, prefs); } /// Declare the desire to nominate `targets` for the origin controller. /// /// Effects will be felt at the beginning of the next era. - /// - /// NOTE: This call must be made by the controller, not the stash. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn nominate(origin, targets: Vec<::Source>) { let controller = ensure_signed(origin)?; - let _ledger = Self::ledger(&controller).ok_or("not a controller")?; + let ledger = Self::ledger(&controller).ok_or("not a controller")?; + let stash = &ledger.stash; ensure!(!targets.is_empty(), "targets cannot be empty"); let targets = targets.into_iter() .take(MAX_NOMINATIONS) .map(T::Lookup::lookup) .collect::, &'static str>>()?; - >::remove(&controller); - >::insert(controller, targets); + >::remove(stash); + >::insert(stash, targets); } /// Declare no desire to either validate or nominate. /// /// Effects will be felt at the beginning of the next era. - /// - /// NOTE: This call must be made by the controller, not the stash. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn chill(origin) { let controller = ensure_signed(origin)?; - let _ledger = Self::ledger(&controller).ok_or("not a controller")?; - >::remove(&controller); - >::remove(&controller); + let ledger = Self::ledger(&controller).ok_or("not a controller")?; + let stash = &ledger.stash; + >::remove(stash); + >::remove(stash); } /// (Re-)set the payment target for a controller. /// /// Effects will be felt at the beginning of the next era. - /// - /// NOTE: This call must be made by the controller, not the stash. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. fn set_payee(origin, payee: RewardDestination) { let controller = ensure_signed(origin)?; - let _ledger = Self::ledger(&controller).ok_or("not a controller")?; - >::insert(&controller, payee); + let ledger = Self::ledger(&controller).ok_or("not a controller")?; + let stash = &ledger.stash; + >::insert(stash, payee); + } + + /// (Re-)set the payment target for a controller. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// The dispatch origin for this call must be _Signed_ by the stash, not the controller. + fn set_controller(origin, controller: ::Source) { + let stash = ensure_signed(origin)?; + let old_controller = Self::bonded(&stash).ok_or("not a stash")?; + let controller = T::Lookup::lookup(controller)?; + if >::exists(&controller) { + return Err("controller already paired") + } + if controller != old_controller { + >::insert(&stash, &controller); + if let Some(l) = >::take(&old_controller) { >::insert(&controller, l) }; + } } /// Set the number of sessions in an era. @@ -463,7 +761,6 @@ decl_module! { } } -/// An event in this module. decl_event!( pub enum Event where Balance = BalanceOf, ::AccountId { /// All validators have been rewarded by the given balance. @@ -490,83 +787,90 @@ impl Module { Self::sessions_per_era() * >::length() } - /// The stashed funds whose staking activities are controlled by `controller` and - /// which are actively in stake right now. - pub fn stash_balance(controller: &T::AccountId) -> BalanceOf { - Self::ledger(controller) - .map_or_else(Zero::zero, |l| l.active) - } - /// The total balance that can be slashed from a validator controller account as of /// right now. pub fn slashable_balance(who: &T::AccountId) -> BalanceOf { Self::stakers(who).total } - // PUBLIC MUTABLES (DANGEROUS) - + // MUTABLES (DANGEROUS) + + /// Update the ledger for a controller. This will also update the stash lock. + fn update_ledger(controller: &T::AccountId, ledger: &StakingLedger, T::BlockNumber>) { + T::Currency::set_lock(STAKING_ID, &ledger.stash, ledger.total, T::BlockNumber::max_value(), WithdrawReasons::all()); + >::insert(controller, ledger); + } + /// Slash a given validator by a specific amount. Removes the slash from their balance by preference, /// and reduces the nominators' balance if needed. - fn slash_validator(v: &T::AccountId, slash: BalanceOf) { + fn slash_validator(stash: &T::AccountId, slash: BalanceOf) { // The exposure (backing stake) information of the validator to be slashed. - let exposure = Self::stakers(v); - // The amount we are actually going to slash (can't be bigger than thair total exposure) + let exposure = Self::stakers(stash); + // The amount we are actually going to slash (can't be bigger than their total exposure) let slash = slash.min(exposure.total); // The amount we'll slash from the validator's stash directly. let own_slash = exposure.own.min(slash); - let own_slash = own_slash - T::Currency::slash(v, own_slash).unwrap_or_default(); + let (mut imbalance, missing) = T::Currency::slash(stash, own_slash); + let own_slash = own_slash - missing; // The amount remaining that we can't slash from the validator, that must be taken from the nominators. let rest_slash = slash - own_slash; - if !rest_slash.is_zero() { // The total to be slashed from the nominators. let total = exposure.total - exposure.own; if !total.is_zero() { let safe_mul_rational = |b| b * rest_slash / total;// FIXME #1572 avoid overflow for i in exposure.others.iter() { - let _ = T::Currency::slash(&i.who, safe_mul_rational(i.value)); // best effort - not much that can be done on fail. + // best effort - not much that can be done on fail. + imbalance.subsume(T::Currency::slash(&i.who, safe_mul_rational(i.value)).0) } } } + T::Slash::on_unbalanced(imbalance); } /// Actually make a payment to a staker. This uses the currency's reward function /// to pay the right payee for the given staker account. - fn make_payout(who: &T::AccountId, amount: BalanceOf) { - match Self::payee(who) { - RewardDestination::Controller => { - let _ = T::Currency::reward(&who, amount); - } - RewardDestination::Stash => { - let _ = Self::ledger(who).map(|l| T::Currency::reward(&l.stash, amount)); - } - RewardDestination::Staked => >::mutate(who, |ml| { - if let Some(l) = ml.as_mut() { + fn make_payout(stash: &T::AccountId, amount: BalanceOf) -> Option> { + let dest = Self::payee(stash); + match dest { + RewardDestination::Controller => Self::bonded(stash) + .and_then(|controller| + T::Currency::deposit_into_existing(&controller, amount).ok() + ), + RewardDestination::Stash => + T::Currency::deposit_into_existing(stash, amount).ok(), + RewardDestination::Staked => Self::bonded(stash) + .and_then(|c| Self::ledger(&c).map(|l| (c, l))) + .and_then(|(controller, mut l)| { l.active += amount; l.total += amount; - let _ = T::Currency::reward(&l.stash, amount); - } - }), - } + let r = T::Currency::deposit_into_existing(stash, amount).ok(); + Self::update_ledger(&controller, &l); + r + }), + } } /// Reward a given validator by a specific amount. Add the reward to their, and their nominators' /// balance, pro-rata based on their exposure, after having removed the validator's pre-payout cut. - fn reward_validator(who: &T::AccountId, reward: BalanceOf) { - let off_the_table = reward.min(Self::validators(who).validator_payment); + fn reward_validator(stash: &T::AccountId, reward: BalanceOf) { + let off_the_table = reward.min(Self::validators(stash).validator_payment); let reward = reward - off_the_table; + let mut imbalance = >::zero(); let validator_cut = if reward.is_zero() { Zero::zero() } else { - let exposure = Self::stakers(who); + let exposure = Self::stakers(stash); let total = exposure.total.max(One::one()); let safe_mul_rational = |b| b * reward / total;// FIXME #1572: avoid overflow for i in &exposure.others { - Self::make_payout(&i.who, safe_mul_rational(i.value)); + let nom_payout = safe_mul_rational(i.value); + imbalance.maybe_subsume(Self::make_payout(&i.who, nom_payout)); } safe_mul_rational(exposure.own) }; - Self::make_payout(who, validator_cut + off_the_table); + imbalance.maybe_subsume(Self::make_payout(stash, validator_cut + off_the_table)); + T::Reward::on_unbalanced(imbalance); } /// Get the reward for the session, assuming it ends with this block. @@ -604,7 +908,7 @@ impl Module { // Payout let reward = >::take(); if !reward.is_zero() { - let validators = >::validators(); + let validators = Self::current_elected(); for v in validators.iter() { Self::reward_validator(v, reward); } @@ -626,140 +930,133 @@ impl Module { } // Reassign all Stakers. + let slot_stake = Self::select_validators(); - // Map of (would-be) validator account to amount of stake backing it. - - // First, we pull all validators, together with their stash balance into a Vec (cpu=O(V), mem=O(V)) - let mut candidates = >::enumerate() - .map(|(who, _)| { - let stash_balance = Self::stash_balance(&who); - (who, Exposure { total: stash_balance, own: stash_balance, others: vec![] }) - }) - .collect::>)>>(); - // Second, we sort by accountid (cpu=O(V.log(V))) - candidates.sort_unstable_by_key(|i| i.0.clone()); - // Third, iterate through nominators and add their balance to the first validator in their approval - // list. cpu=O(N.log(V)) - for (who, nominees) in >::enumerate() { - // For this trivial nominator mapping, we just assume that nominators always - // have themselves assigned to the first validator in their list. - if nominees.is_empty() { - // Not possible, but we protect against it anyway. - continue; - } - if let Ok(index) = candidates.binary_search_by(|i| i.0.cmp(&nominees[0])) { - let stash_balance = Self::stash_balance(&who); - candidates[index].1.total += stash_balance; - candidates[index].1.others.push(IndividualExposure { who, value: stash_balance }); + // Update the balances for rewarding according to the stakes. + >::put(Self::session_reward() * slot_stake); + } + + fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { + Self::bonded(stash).and_then(Self::ledger).map(|l| l.total).unwrap_or_default() + } + + /// Select a new validator set from the assembled stakers and their role preferences. + /// + /// Returns the new SlotStake value. + fn select_validators() -> BalanceOf { + let rounds = || >::get() as usize; + let validators = || >::enumerate(); + let nominators = || >::enumerate(); + let min_validator_count = Self::minimum_validator_count() as usize; + let maybe_elected_candidates = elect::( + rounds, + validators, + nominators, + Self::slashable_balance_of, + min_validator_count, + ElectionConfig::> { + equalize: false, + tolerance: >::sa(10 as u64), + iterations: 10, } - } + ); - // Get the new staker set by sorting by total backing stake and truncating. - // cpu=O(V.log(s)) average, O(V.s) worst. - let count = Self::validator_count() as usize; - let candidates = if candidates.len() <= count { - candidates - } else { - candidates.into_iter().fold(vec![], |mut winners: Vec<(T::AccountId, Exposure>)>, entry| { - if let Err(insert_point) = winners.binary_search_by_key(&entry.1.total, |i| i.1.total) { - if winners.len() < count { - winners.insert(insert_point, entry) - } else { - if insert_point > 0 { - // Big enough to be considered: insert at beginning and swap up to relevant point. - winners[0] = entry; - for i in 0..(insert_point - 1) { - winners.swap(i, i + 1) - } - } - } + if let Some(elected_candidates) = maybe_elected_candidates { + // Clear Stakers and reduce their slash_count. + for v in Self::current_elected().iter() { + >::remove(v); + let slash_count = >::take(v); + if slash_count > 1 { + >::insert(v, slash_count - 1); } - winners - }) - }; + } - // Clear Stakers and reduce their slash_count. - for v in >::validators().iter() { - >::remove(v); - let slash_count = >::take(v); - if slash_count > 1 { - >::insert(v, slash_count - 1); + // Populate Stakers and figure out the minimum stake behind a slot. + let mut slot_stake = elected_candidates[0].exposure.total; + for c in &elected_candidates { + if c.exposure.total < slot_stake { + slot_stake = c.exposure.total; + } + >::insert(c.who.clone(), c.exposure.clone()); } - } + >::put(&slot_stake); - // Figure out the minimum stake behind a slot. - let slot_stake = candidates.last().map(|i| i.1.total).unwrap_or_default(); - >::put(&slot_stake); + // Set the new validator set. + let elected_stashes = elected_candidates.into_iter().map(|i| i.who).collect::>(); + >::put(&elected_stashes); + >::set_validators( + &elected_stashes.into_iter().map(|s| Self::bonded(s).unwrap_or_default()).collect::>() + ); - // Populate Stakers. - for (who, exposure) in &candidates { - >::insert(who, exposure); + slot_stake + } else { + // There were not enough candidates for even our minimal level of functionality. + // This is bad. + // We should probably disable all functionality except for block production + // and let the chain keep producing blocks until we can decide on a sufficiently + // substantial set. + Self::slot_stake() } - // Set the new validator set. - >::set_validators( - &candidates.into_iter().map(|i| i.0).collect::>() - ); - - // Update the balances for slashing/rewarding according to the stakes. - >::put(Self::offline_slash() * slot_stake); - >::put(Self::session_reward() * slot_stake); } /// Call when a validator is determined to be offline. `count` is the - /// number of offences the validator has committed. - pub fn on_offline_validator(v: T::AccountId, count: usize) { + /// number of offenses the validator has committed. + /// + /// NOTE: This is called with the controller (not the stash) account id. + pub fn on_offline_validator(controller: T::AccountId, count: usize) { use primitives::traits::CheckedShl; - // Early exit if validator is invulnerable. - if Self::invulnerables().contains(&v) { - return - } - // TODO: remove once Alex/CC updated #1785 - if Self::invulerables().contains(&v) { - return - } + if let Some(l) = Self::ledger(&controller) { + let stash = l.stash; - let slash_count = Self::slash_count(&v); - let new_slash_count = slash_count + count as u32; - >::insert(&v, new_slash_count); - let grace = Self::offline_slash_grace(); - - if RECENT_OFFLINE_COUNT > 0 { - let item = (v.clone(), >::block_number(), count as u32); - >::mutate(|v| if v.len() >= RECENT_OFFLINE_COUNT { - let index = v.iter() - .enumerate() - .min_by_key(|(_, (_, block, _))| block) - .expect("v is non-empty; qed") - .0; - v[index] = item; - } else { - v.push(item); - }); - } + // Early exit if validator is invulnerable. + if Self::invulnerables().contains(&stash) { + return + } - let prefs = Self::validators(&v); - let unstake_threshold = prefs.unstake_threshold.min(MAX_UNSTAKE_THRESHOLD); - let max_slashes = grace + unstake_threshold; - - let event = if new_slash_count > max_slashes { - let slot_stake = Self::slot_stake(); - // They're bailing. - let slash = Self::current_offline_slash() - // Multiply current_offline_slash by 2^(unstake_threshold with upper bound) - .checked_shl(unstake_threshold) - .map(|x| x.min(slot_stake)) - .unwrap_or(slot_stake); - let _ = Self::slash_validator(&v, slash); - >::remove(&v); - let _ = Self::apply_force_new_era(false); - - RawEvent::OfflineSlash(v.clone(), slash) - } else { - RawEvent::OfflineWarning(v.clone(), slash_count) - }; + let slash_count = Self::slash_count(&stash); + let new_slash_count = slash_count + count as u32; + >::insert(&stash, new_slash_count); + let grace = Self::offline_slash_grace(); + + if RECENT_OFFLINE_COUNT > 0 { + let item = (stash.clone(), >::block_number(), count as u32); + >::mutate(|v| if v.len() >= RECENT_OFFLINE_COUNT { + let index = v.iter() + .enumerate() + .min_by_key(|(_, (_, block, _))| block) + .expect("v is non-empty; qed") + .0; + v[index] = item; + } else { + v.push(item); + }); + } - Self::deposit_event(event); + let prefs = Self::validators(&stash); + let unstake_threshold = prefs.unstake_threshold.min(MAX_UNSTAKE_THRESHOLD); + let max_slashes = grace + unstake_threshold; + + let event = if new_slash_count > max_slashes { + let slash_exposure = Self::stakers(&stash).total; + let offline_slash_base = Self::offline_slash() * slash_exposure; + // They're bailing. + let slash = offline_slash_base + // Multiply slash_mantissa by 2^(unstake_threshold with upper bound) + .checked_shl(unstake_threshold) + .map(|x| x.min(slash_exposure)) + .unwrap_or(slash_exposure); + let _ = Self::slash_validator(&stash, slash); + >::remove(&stash); + let _ = Self::apply_force_new_era(false); + + RawEvent::OfflineSlash(stash.clone(), slash) + } else { + RawEvent::OfflineWarning(stash.clone(), slash_count) + }; + + Self::deposit_event(event); + } } } @@ -769,38 +1066,15 @@ impl OnSessionChange for Module { } } -impl EnsureAccountLiquid> for Module { - fn ensure_account_liquid(who: &T::AccountId) -> Result { - if >::exists(who) { - Err("stash accounts are not liquid") - } else { - Ok(()) - } - } - fn ensure_account_can_withdraw( - who: &T::AccountId, - amount: BalanceOf, - _reason: WithdrawReason, - ) -> Result { - if let Some(controller) = Self::bonded(who) { - let ledger = Self::ledger(&controller).ok_or("stash without controller")?; - let free_balance = T::Currency::free_balance(&who); - ensure!(free_balance.saturating_sub(ledger.total) > amount, - "stash with too much under management"); - } - Ok(()) - } -} - impl OnFreeBalanceZero for Module { - fn on_free_balance_zero(who: &T::AccountId) { - if let Some(controller) = >::take(who) { + fn on_free_balance_zero(stash: &T::AccountId) { + if let Some(controller) = >::take(stash) { >::remove(&controller); - >::remove(&controller); - >::remove(&controller); - >::remove(&controller); - >::remove(&controller); } + >::remove(stash); + >::remove(stash); + >::remove(stash); + >::remove(stash); } } diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index 244c3c18c22ceb8f537a78c7aa7d85fbef5c78e3..17723cb362604522862169f39113862ceeb72402 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,12 +18,26 @@ #![cfg(test)] -use primitives::{traits::IdentityLookup, BuildStorage, Perbill}; +use primitives::{traits::{IdentityLookup, Convert}, BuildStorage, Perbill}; use primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, ConvertUintAuthorityId}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; use srml_support::impl_outer_origin; -use crate::{GenesisConfig, Module, Trait}; +use crate::{GenesisConfig, Module, Trait, StakerStatus}; + +/// The AccountId alias in this test module. +pub type AccountIdType = u64; + +/// Simple structure that exposes how u64 currency can be represented as... u64. +pub struct CurrencyToVoteHandler; +impl Convert for CurrencyToVoteHandler { + fn convert(x: u64) -> u64 { x } +} +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { + x as u64 + } +} impl_outer_origin!{ pub enum Origin for Test {} @@ -44,8 +58,8 @@ impl system::Trait for Test { type Hash = H256; type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; - type AccountId = u64; - type Lookup = IdentityLookup; + type AccountId = AccountIdType; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; @@ -54,8 +68,10 @@ impl balances::Trait for Test { type Balance = u64; type OnFreeBalanceZero = Staking; type OnNewAccount = (); - type EnsureAccountLiquid = Staking; type Event = (); + type TransactionPayment = (); + type TransferPayment = (); + type DustRemoval = (); } impl session::Trait for Test { type ConvertAccountIdToSessionKey = ConvertUintAuthorityId; @@ -68,8 +84,11 @@ impl timestamp::Trait for Test { } impl Trait for Test { type Currency = balances::Module; + type CurrencyToVote = CurrencyToVoteHandler; type OnRewardMinted = (); type Event = (); + type Slash = (); + type Reward = (); } pub struct ExtBuilder { @@ -77,19 +96,27 @@ pub struct ExtBuilder { session_length: u64, sessions_per_era: u64, current_era: u64, - monied: bool, reward: u64, + validator_pool: bool, + nominate: bool, + validator_count: u32, + minimum_validator_count: u32, + fare: bool, } impl Default for ExtBuilder { fn default() -> Self { Self { existential_deposit: 0, - session_length: 3, - sessions_per_era: 3, + session_length: 1, + sessions_per_era: 1, current_era: 0, - monied: true, reward: 10, + validator_pool: false, + nominate: true, + validator_count: 2, + minimum_validator_count: 0, + fare: true } } } @@ -111,62 +138,99 @@ impl ExtBuilder { self.current_era = current_era; self } - pub fn _monied(mut self, monied: bool) -> Self { - self.monied = monied; + pub fn validator_pool(mut self, validator_pool: bool) -> Self { + self.validator_pool = validator_pool; self } - pub fn reward(mut self, reward: u64) -> Self { - self.reward = reward; + pub fn nominate(mut self, nominate: bool) -> Self { + self.nominate = nominate; + self + } + pub fn validator_count(mut self, count: u32) -> Self { + self.validator_count = count; + self + } + pub fn minimum_validator_count(mut self, count: u32) -> Self { + self.minimum_validator_count = count; + self + } + pub fn fare(mut self, is_fare: bool) -> Self { + self.fare = is_fare; self } pub fn build(self) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; + let (mut t, mut c) = system::GenesisConfig::::default().build_storage().unwrap(); let balance_factor = if self.existential_deposit > 0 { 256 } else { 1 }; - t.extend(consensus::GenesisConfig::{ + let _ = consensus::GenesisConfig::{ code: vec![], authorities: vec![], - }.build_storage().unwrap().0); - t.extend(session::GenesisConfig::{ + }.assimilate_storage(&mut t, &mut c); + let _ = session::GenesisConfig::{ session_length: self.session_length, - validators: vec![10, 20], + // NOTE: if config.nominate == false then 100 is also selected in the initial round. + validators: if self.validator_pool { vec![10, 20, 30, 40] } else { vec![10, 20] }, keys: vec![], - }.build_storage().unwrap().0); - t.extend(balances::GenesisConfig::{ - balances: if self.monied { - if self.reward > 0 { - vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 300 * balance_factor), (4, 400 * balance_factor), (10, balance_factor), (11, balance_factor * 1000), (20, balance_factor), (21, balance_factor * 2000)] - } else { - vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 300 * balance_factor), (4, 400 * balance_factor)] - } - } else { - vec![(10, balance_factor), (11, balance_factor * 1000), (20, balance_factor), (21, balance_factor * 2000)] - }, + }.assimilate_storage(&mut t, &mut c); + let _ = balances::GenesisConfig::{ + balances: vec![ + (1, 10 * balance_factor), + (2, 20 * balance_factor), + (3, 300 * balance_factor), + (4, 400 * balance_factor), + (10, balance_factor), + (11, balance_factor * 1000), + (20, balance_factor), + (21, balance_factor * 2000), + (30, balance_factor), + (31, balance_factor * 2000), + (40, balance_factor), + (41, balance_factor * 2000), + (100, 2000 * balance_factor), + (101, 2000 * balance_factor), + ], + transaction_base_fee: 0, + transaction_byte_fee: 0, existential_deposit: self.existential_deposit, transfer_fee: 0, creation_fee: 0, vesting: vec![], - }.build_storage().unwrap().0); - t.extend(GenesisConfig::{ + }.assimilate_storage(&mut t, &mut c); + let _ = GenesisConfig::{ sessions_per_era: self.sessions_per_era, current_era: self.current_era, - stakers: vec![(11, 10, balance_factor * 1000), (21, 20, balance_factor * 2000)], - validator_count: 2, - minimum_validator_count: 0, + stakers: if self.validator_pool { + vec![ + (11, 10, balance_factor * 1000, StakerStatus::::Validator), + (21, 20, balance_factor * if self.fare { 1000 } else { 2000 }, StakerStatus::::Validator), + (31, 30, balance_factor * 1000, if self.validator_pool { StakerStatus::::Validator } else { StakerStatus::::Idle }), + (41, 40, balance_factor * 1000, if self.validator_pool { StakerStatus::::Validator } else { StakerStatus::::Idle }), + // nominator + (101, 100, balance_factor * 500, if self.nominate { StakerStatus::::Nominator(vec![11, 21]) } else { StakerStatus::::Nominator(vec![]) }) + ] + } else { + vec![ + (11, 10, balance_factor * 1000, StakerStatus::::Validator), + (21, 20, balance_factor * if self.fare { 1000 } else { 2000 }, StakerStatus::::Validator), + // nominator + (101, 100, balance_factor * 500, if self.nominate { StakerStatus::::Nominator(vec![11, 21]) } else { StakerStatus::::Nominator(vec![]) }) + ] + }, + validator_count: self.validator_count, + minimum_validator_count: self.minimum_validator_count, bonding_duration: self.sessions_per_era * self.session_length * 3, session_reward: Perbill::from_millionths((1000000 * self.reward / balance_factor) as u32), - offline_slash: if self.monied { Perbill::from_percent(40) } else { Perbill::zero() }, + offline_slash: Perbill::from_percent(5), current_session_reward: self.reward, - current_offline_slash: 20, offline_slash_grace: 0, invulnerables: vec![], - }.build_storage().unwrap().0); - t.extend(timestamp::GenesisConfig::{ - period: 5, - }.build_storage().unwrap().0); + }.assimilate_storage(&mut t, &mut c); + let _ = timestamp::GenesisConfig::{ + minimum_period: 5, + }.assimilate_storage(&mut t, &mut c); t.into() } } diff --git a/srml/staking/src/phragmen.rs b/srml/staking/src/phragmen.rs new file mode 100644 index 0000000000000000000000000000000000000000..bb939baa7998a11e531f5373e5ed2944774ce728 --- /dev/null +++ b/srml/staking/src/phragmen.rs @@ -0,0 +1,377 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Rust implementation of the Phragmén election algorithm. + +use rstd::prelude::*; +use primitives::PerU128; +use primitives::traits::{Zero, Saturating, Convert}; +use parity_codec::{HasCompact, Encode, Decode}; +use crate::{Exposure, BalanceOf, Trait, ValidatorPrefs, IndividualExposure}; + +type Fraction = PerU128; +type ExtendedBalance = u128; + +/// Configure the behavior of the Phragmen election. +/// Might be deprecated. +pub struct ElectionConfig { + /// Perform equalize?. + pub equalize: bool, + /// Number of equalize iterations. + pub iterations: usize, + /// Tolerance of max change per equalize iteration. + pub tolerance: Balance, +} + +/// Wrapper around validation candidates some metadata. +#[derive(Clone, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Candidate { + /// The validator's account + pub who: AccountId, + /// Exposure struct, holding info about the value that the validator has in stake. + pub exposure: Exposure, + /// Intermediary value used to sort candidates. + pub score: Fraction, + /// Accumulator of the stake of this candidate based on received votes. + approval_stake: ExtendedBalance, + /// Flag for being elected. + elected: bool, + /// This is most often equal to `Exposure.total` but not always. Needed for [`equalize`] + backing_stake: ExtendedBalance +} + +/// Wrapper around the nomination info of a single nominator for a group of validators. +#[derive(Clone, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Nominator { + /// The nominator's account. + who: AccountId, + /// List of validators proposed by this nominator. + edges: Vec>, + /// the stake amount proposed by the nominator as a part of the vote. + budget: ExtendedBalance, + /// Incremented each time a nominee that this nominator voted for has been elected. + load: Fraction, +} + +/// Wrapper around a nominator vote and the load of that vote. +#[derive(Clone, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Edge { + /// Account being voted for + who: AccountId, + /// Load of this vote. + load: Fraction, + /// Final backing stake of this vote. + backing_stake: ExtendedBalance, + /// Index of the candidate stored in the 'candidates' vector + candidate_index: usize, + /// Index of the candidate stored in the 'elected_candidates' vector. Used only with equalize. + elected_idx: usize, + /// Indicates if this edge is a vote for an elected candidate. Used only with equalize. + elected: bool, +} + +/// Perform election based on Phragmén algorithm. +/// +/// Reference implementation: https://github.com/w3f/consensus +/// +/// Returns an Option of elected candidates, if election is performed. +/// Returns None if not enough candidates exist. +pub fn elect( + get_rounds: FR, + get_validators: FV, + get_nominators: FN, + stash_of: FS, + minimum_validator_count: usize, + config: ElectionConfig>, +) -> Option>>> where + FR: Fn() -> usize, + FV: Fn() -> Box>) + >>, + FN: Fn() -> Box) + >>, + for <'r> FS: Fn(&'r T::AccountId) -> BalanceOf, +{ + let expand = |b: BalanceOf| , u64>>::convert(b) as ExtendedBalance; + let shrink = |b: ExtendedBalance| >>::convert(b); + let rounds = get_rounds(); + let mut elected_candidates; + + // 1- Pre-process candidates and place them in a container + let mut candidates = get_validators().map(|(who, _)| { + let stash_balance = stash_of(&who); + Candidate { + who, + exposure: Exposure { total: stash_balance, own: stash_balance, others: vec![] }, + ..Default::default() + } + }).collect::>>>(); + + // 1.1- Add phantom votes. + let mut nominators: Vec> = Vec::with_capacity(candidates.len()); + candidates.iter_mut().enumerate().for_each(|(idx, c)| { + c.approval_stake += expand(c.exposure.total); + nominators.push(Nominator { + who: c.who.clone(), + edges: vec![ Edge { who: c.who.clone(), candidate_index: idx, ..Default::default() }], + budget: expand(c.exposure.total), + load: Fraction::zero(), + }) + }); + + // 2- Collect the nominators with the associated votes. + // Also collect approval stake along the way. + nominators.extend(get_nominators().map(|(who, nominees)| { + let nominator_stake = stash_of(&who); + let mut edges: Vec> = Vec::with_capacity(nominees.len()); + for n in &nominees { + if let Some(idx) = candidates.iter_mut().position(|i| i.who == *n) { + candidates[idx].approval_stake = candidates[idx].approval_stake + .saturating_add(expand(nominator_stake)); + edges.push(Edge { who: n.clone(), candidate_index: idx, ..Default::default() }); + } + } + + Nominator { + who, + edges: edges, + budget: expand(nominator_stake), + load: Fraction::zero(), + } + })); + + + // 3- optimization: + // Candidates who have 0 stake => have no votes or all null-votes. Kick them out not. + let mut candidates = candidates.into_iter().filter(|c| c.approval_stake > 0) + .collect::>>>(); + + // 4- If we have more candidates then needed, run Phragmén. + if candidates.len() >= rounds { + elected_candidates = Vec::with_capacity(rounds); + // Main election loop + for _round in 0..rounds { + // Loop 1: initialize score + for c in &mut candidates { + if !c.elected { + c.score = Fraction::from_xth(c.approval_stake); + } + } + // Loop 2: increment score. + for n in &nominators { + for e in &n.edges { + let c = &mut candidates[e.candidate_index]; + if !c.elected { + let temp = n.budget.saturating_mul(*n.load) / c.approval_stake; + c.score = Fraction::from_max_value((*c.score).saturating_add(temp)); + } + } + } + + // Find the best + let winner = candidates + .iter_mut() + .filter(|c| !c.elected) + .min_by_key(|c| *c.score) + .expect("candidates length is checked to be >0; qed"); + + // loop 3: update nominator and edge load + winner.elected = true; + for n in &mut nominators { + for e in &mut n.edges { + if e.who == winner.who { + e.load = Fraction::from_max_value(*winner.score - *n.load); + n.load = winner.score; + } + } + } + + elected_candidates.push(winner.clone()); + } // end of all rounds + + // 4.1- Update backing stake of candidates and nominators + for n in &mut nominators { + for e in &mut n.edges { + // if the target of this vote is among the winners, otherwise let go. + if let Some(c) = elected_candidates.iter_mut().find(|c| c.who == e.who) { + e.elected = true; + // NOTE: for now, always divide last to avoid collapse to zero. + e.backing_stake = n.budget.saturating_mul(*e.load) / *n.load; + c.backing_stake = c.backing_stake.saturating_add(e.backing_stake); + if c.who != n.who { + // Only update the exposure if this vote is from some other account. + c.exposure.total = c.exposure.total.saturating_add(shrink(e.backing_stake)); + c.exposure.others.push( + IndividualExposure { who: n.who.clone(), value: shrink(e.backing_stake) } + ); + } + } + } + } + + // Optionally perform equalize post-processing. + if config.equalize { + let tolerance = config.tolerance; + let equalize_iterations = config.iterations; + + // Fix indexes + nominators.iter_mut().for_each(|n| { + n.edges.iter_mut().for_each(|e| { + if let Some(idx) = elected_candidates.iter().position(|c| c.who == e.who) { + e.elected_idx = idx; + } + }); + }); + + for _i in 0..equalize_iterations { + let mut max_diff = >::zero(); + nominators.iter_mut().for_each(|mut n| { + let diff = equalize::(&mut n, &mut elected_candidates, tolerance); + if diff > max_diff { + max_diff = diff; + } + }); + if max_diff < tolerance { + break; + } + } + } + } else { + if candidates.len() > minimum_validator_count { + // if we don't have enough candidates, just choose all that have some vote. + elected_candidates = candidates; + for n in &mut nominators { + let nominator = n.who.clone(); + for e in &mut n.edges { + if let Some(c) = elected_candidates.iter_mut().find(|c| c.who == e.who && c.who != nominator) { + c.exposure.total = c.exposure.total.saturating_add(shrink(n.budget)); + c.exposure.others.push( + IndividualExposure { who: n.who.clone(), value: shrink(n.budget) } + ); + } + } + } + } else { + // if we have less than minimum, use the previous validator set. + return None + } + } + Some(elected_candidates) +} + +/// Performs equalize post-processing to the output of the election algorithm +/// This function mutates the input parameters, most noticeably it updates the exposure of +/// the elected candidates. +/// The return value is to tolerance at which the function has stopped. +pub fn equalize( + nominator: &mut Nominator, + elected_candidates: &mut Vec>>, + _tolerance: BalanceOf +) -> BalanceOf { + let expand = |b: BalanceOf| , u64>>::convert(b) as ExtendedBalance; + let shrink = |b: ExtendedBalance| >>::convert(b); + let tolerance = expand(_tolerance); + + let mut elected_edges = nominator.edges + .iter_mut() + .filter(|e| e.elected) + .collect::>>(); + + if elected_edges.len() == 0 { + return >::zero(); + } + + let stake_used = elected_edges + .iter() + .fold(0, |s, e| s.saturating_add(e.backing_stake)); + let backed_stakes = elected_edges + .iter() + .map(|e| elected_candidates[e.elected_idx].backing_stake) + .collect::>(); + let backing_backed_stake = elected_edges + .iter() + .filter(|e| e.backing_stake > 0) + .map(|e| elected_candidates[e.elected_idx].backing_stake) + .collect::>(); + + let mut difference; + if backing_backed_stake.len() > 0 { + let max_stake = *backing_backed_stake + .iter() + .max() + .expect("vector with positive length will have a max; qed"); + let min_stake = *backed_stakes + .iter() + .min() + .expect("vector with positive length will have a min; qed"); + difference = max_stake.saturating_sub(min_stake); + difference = difference.saturating_add(nominator.budget.saturating_sub(stake_used)); + if difference < tolerance { + return shrink(difference); + } + } else { + difference = nominator.budget; + } + + // Undo updates to exposure + elected_edges.iter_mut().for_each(|e| { + // NOTE: no assertions in the runtime, but this should nonetheless be indicative. + //assert_eq!(elected_candidates[e.elected_idx].who, e.who); + elected_candidates[e.elected_idx].backing_stake -= e.backing_stake; + elected_candidates[e.elected_idx].exposure.total -= shrink(e.backing_stake); + e.backing_stake = 0; + }); + + elected_edges.sort_unstable_by_key(|e| elected_candidates[e.elected_idx].backing_stake); + + let mut cumulative_stake: ExtendedBalance = 0; + let mut last_index = elected_edges.len() - 1; + let budget = nominator.budget; + elected_edges.iter_mut().enumerate().for_each(|(idx, e)| { + let stake = elected_candidates[e.elected_idx].backing_stake; + + let stake_mul = stake.saturating_mul(idx as ExtendedBalance); + let stake_sub = stake_mul.saturating_sub(cumulative_stake); + if stake_sub > budget { + last_index = idx.checked_sub(1).unwrap_or(0); + return + } + cumulative_stake = cumulative_stake.saturating_add(stake); + }); + + let last_stake = elected_candidates[elected_edges[last_index].elected_idx].backing_stake; + let split_ways = last_index + 1; + let excess = nominator.budget + .saturating_add(cumulative_stake) + .saturating_sub(last_stake.saturating_mul(split_ways as ExtendedBalance)); + let nominator_address = nominator.who.clone(); + elected_edges.iter_mut().take(split_ways).for_each(|e| { + let c = &mut elected_candidates[e.elected_idx]; + e.backing_stake = (excess / split_ways as ExtendedBalance) + .saturating_add(last_stake) + .saturating_sub(c.backing_stake); + c.exposure.total = c.exposure.total.saturating_add(shrink(e.backing_stake)); + c.backing_stake = c.backing_stake.saturating_add(e.backing_stake); + if let Some(i_expo) = c.exposure.others.iter_mut().find(|i| i.who == nominator_address) { + i_expo.value = shrink(e.backing_stake); + } + }); + shrink(difference) +} diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index 5ca7a46801e9a65024c0a5ca124cdb704f5d5e85..2d6ce5aa7ae1cb74b21aa6add818b1312d5b5f77 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,16 +20,17 @@ use super::*; use runtime_io::with_externalities; -use srml_support::{assert_ok, assert_noop, EnumerableStorageMap}; +use phragmen; +use primitives::PerU128; +use srml_support::{assert_ok, assert_noop, assert_eq_uvec, EnumerableStorageMap}; use mock::{Balances, Session, Staking, System, Timestamp, Test, ExtBuilder, Origin}; -use srml_support::traits::Currency; +use srml_support::traits::{Currency, ReservableCurrency}; #[test] fn basic_setup_works() { // Verifies initial conditions of mock - // TODO: Verify this check is comprehensive - // - Session Per Era, Session Reward - with_externalities(&mut ExtBuilder::default().build(), + with_externalities(&mut ExtBuilder::default() + .build(), || { assert_eq!(Staking::bonded(&11), Some(10)); // Account 11 is stashed and locked, and account 10 is the controller assert_eq!(Staking::bonded(&21), Some(20)); // Account 21 is stashed and locked, and account 20 is the controller @@ -38,23 +39,44 @@ fn basic_setup_works() { // Account 10 controls the stash from account 11, which is 100 * balance_factor units assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); // Account 20 controls the stash from account 21, which is 200 * balance_factor units - assert_eq!(Staking::ledger(&20), Some(StakingLedger { stash: 21, total: 2000, active: 2000, unlocking: vec![] })); + assert_eq!(Staking::ledger(&20), Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![] })); // Account 1 does not control any stash assert_eq!(Staking::ledger(&1), None); // ValidatorPrefs are default, thus unstake_threshold is 3, other values are default for their type assert_eq!(>::enumerate().collect::>(), vec![ - (20, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }), - (10, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }) + (21, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }), + (11, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }) ]); - // Account 10 is exposed by 100 * balance_factor from their own stash in account 11 - assert_eq!(Staking::stakers(10), Exposure { total: 1000, own: 1000, others: vec![] }); - assert_eq!(Staking::stakers(20), Exposure { total: 2000, own: 2000, others: vec![] }); + // Account 100 is the default nominator + assert_eq!(Staking::ledger(100), Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![] })); + assert_eq!(Staking::nominators(101), vec![11, 21]); + + // Account 10 is exposed by 1000 * balance_factor from their own stash in account 11 + the default nominator vote + assert_eq!(Staking::stakers(11), Exposure { total: 1124, own: 1000, others: vec![ IndividualExposure { who: 101, value: 124 }] }); + // Account 20 is exposed by 1000 * balance_factor from their own stash in account 21 + the default nominator vote + assert_eq!(Staking::stakers(21), Exposure { total: 1375, own: 1000, others: vec![ IndividualExposure { who: 101, value: 375 }] }); + + // The number of validators required. + assert_eq!(Staking::validator_count(), 2); + + // Initial Era and session + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + + // initial rewards + assert_eq!(Staking::current_session_reward(), 10); + + // initial slot_stake + assert_eq!(Staking::slot_stake(), 1124); // Naive + + // initial slash_count of validators + assert_eq!(Staking::slash_count(&11), 0); + assert_eq!(Staking::slash_count(&21), 0); }); } - #[test] fn no_offline_should_work() { // Test the staking module works when no validators are offline @@ -79,28 +101,29 @@ fn invulnerability_should_work() { // Test that users can be invulnerable from slashing and being kicked with_externalities(&mut ExtBuilder::default().build(), || { - // Make account 10 invulnerable - assert_ok!(Staking::set_invulnerables(vec![10])); - // Give account 10 some funds - Balances::set_free_balance(&10, 70); - // There is no slash grade period + // Make account 11 invulnerable + assert_ok!(Staking::set_invulnerables(vec![11])); + // Give account 11 some funds + let _ = Balances::make_free_balance_be(&11, 70); + // There is no slash grace -- slash immediately. assert_eq!(Staking::offline_slash_grace(), 0); - // Account 10 has not been slashed - assert_eq!(Staking::slash_count(&10), 0); - // Account 10 has the 70 funds we gave it above - assert_eq!(Balances::free_balance(&10), 70); - // Account 10 should be a validator - assert!(>::exists(&10)); - - // Set account 10 as an offline validator with a large number of reports + // Account 11 has not been slashed + assert_eq!(Staking::slash_count(&11), 0); + // Account 11 has the 70 funds we gave it above + assert_eq!(Balances::free_balance(&11), 70); + // Account 11 should be a validator + assert!(>::exists(&11)); + + // Set account 11 as an offline validator with a large number of reports // Should exit early if invulnerable Staking::on_offline_validator(10, 100); - // Show that account 10 has not been touched - assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Balances::free_balance(&10), 70); - assert!(>::exists(&10)); + // Show that account 11 has not been touched + assert_eq!(Staking::slash_count(&11), 0); + assert_eq!(Balances::free_balance(&11), 70); + assert!(>::exists(&11)); // New era not being forced + // NOTE: new era is always forced once slashing happens -> new validators need to be chosen. assert!(Staking::forcing_new_era().is_none()); }); } @@ -110,27 +133,26 @@ fn offline_should_slash_and_kick() { // Test that an offline validator gets slashed and kicked with_externalities(&mut ExtBuilder::default().build(), || { // Give account 10 some balance - Balances::set_free_balance(&10, 1000); + let _ = Balances::make_free_balance_be(&11, 1000); // Confirm account 10 is a validator - assert!(>::exists(&10)); + assert!(>::exists(&11)); // Validators get slashed immediately assert_eq!(Staking::offline_slash_grace(), 0); // Unstake threshold is 3 - assert_eq!(Staking::validators(&10).unstake_threshold, 3); + assert_eq!(Staking::validators(&11).unstake_threshold, 3); // Account 10 has not been slashed before - assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::slash_count(&11), 0); // Account 10 has the funds we just gave it - assert_eq!(Balances::free_balance(&10), 1000); + assert_eq!(Balances::free_balance(&11), 1000); // Report account 10 as offline, one greater than unstake threshold Staking::on_offline_validator(10, 4); // Confirm user has been reported - assert_eq!(Staking::slash_count(&10), 4); - // Confirm `slot_stake` is greater than exponential punishment, else math below will be different - assert!(Staking::slot_stake() > 2_u64.pow(3) * 20); - // Confirm balance has been reduced by 2^unstake_threshold * current_offline_slash() - assert_eq!(Balances::free_balance(&10), 1000 - 2_u64.pow(3) * 20); + assert_eq!(Staking::slash_count(&11), 4); + // Confirm balance has been reduced by 2^unstake_threshold * offline_slash() * amount_at_stake. + let slash_base = Staking::offline_slash() * Staking::stakers(11).total; + assert_eq!(Balances::free_balance(&11), 1000 - 2_u64.pow(3) * slash_base); // Confirm account 10 has been removed as a validator - assert!(!>::exists(&10)); + assert!(!>::exists(&11)); // A new era is forced due to slashing assert!(Staking::forcing_new_era().is_some()); }); @@ -141,51 +163,126 @@ fn offline_grace_should_delay_slashing() { // Tests that with grace, slashing is delayed with_externalities(&mut ExtBuilder::default().build(), || { // Initialize account 10 with balance - Balances::set_free_balance(&10, 70); - // Verify account 10 has balance - assert_eq!(Balances::free_balance(&10), 70); + let _ = Balances::make_free_balance_be(&11, 70); + // Verify account 11 has balance + assert_eq!(Balances::free_balance(&11), 70); // Set offline slash grace let offline_slash_grace = 1; assert_ok!(Staking::set_offline_slash_grace(offline_slash_grace)); assert_eq!(Staking::offline_slash_grace(), 1); - // Check unstaked_threshold is 3 (default) + // Check unstake_threshold is 3 (default) let default_unstake_threshold = 3; - assert_eq!(Staking::validators(&10), ValidatorPrefs { unstake_threshold: default_unstake_threshold, validator_payment: 0 }); + assert_eq!(Staking::validators(&11), ValidatorPrefs { unstake_threshold: default_unstake_threshold, validator_payment: 0 }); // Check slash count is zero - assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::slash_count(&11), 0); // Report account 10 up to the threshold Staking::on_offline_validator(10, default_unstake_threshold as usize + offline_slash_grace as usize); // Confirm slash count - assert_eq!(Staking::slash_count(&10), 4); + assert_eq!(Staking::slash_count(&11), 4); // Nothing should happen - assert_eq!(Balances::free_balance(&10), 70); + assert_eq!(Balances::free_balance(&11), 70); // Report account 10 one more time Staking::on_offline_validator(10, 1); - assert_eq!(Staking::slash_count(&10), 5); + assert_eq!(Staking::slash_count(&11), 5); // User gets slashed - assert_eq!(Balances::free_balance(&10), 0); + assert!(Balances::free_balance(&11) < 70); // New era is forced assert!(Staking::forcing_new_era().is_some()); }); } +#[test] +fn max_unstake_threshold_works() { + // Tests that max_unstake_threshold gets used when prefs.unstake_threshold is large + with_externalities(&mut ExtBuilder::default().build(), || { + const MAX_UNSTAKE_THRESHOLD: u32 = 10; + // Two users with maximum possible balance + let _ = Balances::make_free_balance_be(&11, u64::max_value()); + let _ = Balances::make_free_balance_be(&21, u64::max_value()); + + // Give them full exposure as a staker + >::insert(&11, Exposure { total: 1000000, own: 1000000, others: vec![]}); + >::insert(&21, Exposure { total: 2000000, own: 2000000, others: vec![]}); + + // Check things are initialized correctly + assert_eq!(Balances::free_balance(&11), u64::max_value()); + assert_eq!(Balances::free_balance(&21), u64::max_value()); + assert_eq!(Staking::offline_slash_grace(), 0); + // Account 10 will have max unstake_threshold + assert_ok!(Staking::validate(Origin::signed(10), ValidatorPrefs { + unstake_threshold: MAX_UNSTAKE_THRESHOLD, + validator_payment: 0, + })); + // Account 20 could not set their unstake_threshold past 10 + assert_noop!(Staking::validate(Origin::signed(20), ValidatorPrefs { + unstake_threshold: MAX_UNSTAKE_THRESHOLD + 1, + validator_payment: 0}), + "unstake threshold too large" + ); + // Give Account 20 unstake_threshold 11 anyway, should still be limited to 10 + >::insert(21, ValidatorPrefs { + unstake_threshold: MAX_UNSTAKE_THRESHOLD + 1, + validator_payment: 0, + }); + + >::put(Perbill::from_fraction(0.0001)); + + // Report each user 1 more than the max_unstake_threshold + Staking::on_offline_validator(10, MAX_UNSTAKE_THRESHOLD as usize + 1); + Staking::on_offline_validator(20, MAX_UNSTAKE_THRESHOLD as usize + 1); + + // Show that each balance only gets reduced by 2^max_unstake_threshold times 10% + // of their total stake. + assert_eq!(Balances::free_balance(&11), u64::max_value() - 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 100); + assert_eq!(Balances::free_balance(&21), u64::max_value() - 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 200); + }); +} + +#[test] +fn slashing_does_not_cause_underflow() { + // Tests that slashing more than a user has does not underflow + with_externalities(&mut ExtBuilder::default().build(), || { + // Verify initial conditions + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Staking::offline_slash_grace(), 0); + + // Set validator preference so that 2^unstake_threshold would cause overflow (greater than 64) + >::insert(11, ValidatorPrefs { + unstake_threshold: 10, + validator_payment: 0, + }); + + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + // Should not panic + Staking::on_offline_validator(10, 100); + // Confirm that underflow has not occurred, and account balance is set to zero + assert_eq!(Balances::free_balance(&11), 0); + }); +} + + #[test] fn rewards_should_work() { - // should check that: - // 1) rewards get recorded per session - // 2) rewards get paid per Era - // 3) (bonus) Check that nominators are also rewarded - with_externalities(&mut ExtBuilder::default().build(), + // should check that: + // * rewards get recorded per session + // * rewards get paid per Era + // * Check that nominators are also rewarded + with_externalities(&mut ExtBuilder::default() + .session_length(3) + .sessions_per_era(3) + .build(), || { - let delay = 2; - // this test is only in the scope of one era. Since this variable changes + let delay = 0; + // this test is only in the scope of one era. Since this variable changes // at the last block/new era, we'll save it. let session_reward = 10; @@ -198,37 +295,39 @@ fn rewards_should_work() { assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 0); - assert_eq!(Staking::current_session_reward(), 10); // check the balance of a validator accounts. - assert_eq!(Balances::total_balance(&10), 1); + assert_eq!(Balances::total_balance(&11), 1000); // and the nominator (to-be) - assert_eq!(Balances::total_balance(&2), 20); + let _ = Balances::make_free_balance_be(&2, 500); + assert_eq!(Balances::total_balance(&2), 500); // add a dummy nominator. // NOTE: this nominator is being added 'manually'. a Further test (nomination_and_reward..) will add it via '.nominate()' - >::insert(&10, Exposure { + >::insert(&11, Exposure { own: 500, // equal division indicates that the reward will be equally divided among validator and nominator. total: 1000, - others: vec![IndividualExposure {who: 2, value: 500 }] - }); - >::insert(&2, RewardDestination::Controller); + others: vec![IndividualExposure {who: 2, value: 500 }] + }); + >::insert(&2, RewardDestination::Stash); + assert_eq!(Staking::payee(2), RewardDestination::Stash); + assert_eq!(Staking::payee(11), RewardDestination::Controller); let mut block = 3; // Block 3 => Session 1 => Era 0 System::set_block_number(block); Timestamp::set_timestamp(block*5); // on time. - Session::check_rotate_session(System::block_number()); // QUESTIONS: why this matters ? + Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); // session triggered: the reward value stashed should be 10 -- defined in ExtBuilder genesis. assert_eq!(Staking::current_session_reward(), session_reward); assert_eq!(Staking::current_era_reward(), session_reward); - - block = 6; // Block 6 => Session 2 => Era 0 + + block = 6; // Block 6 => Session 2 => Era 0 System::set_block_number(block); Timestamp::set_timestamp(block*5 + delay); // a little late. Session::check_rotate_session(System::block_number()); @@ -242,22 +341,26 @@ fn rewards_should_work() { block = 9; // Block 9 => Session 3 => Era 1 System::set_block_number(block); - Timestamp::set_timestamp(block*5); // back to being punktlisch. no delayss + Timestamp::set_timestamp(block*5); // back to being on time. no delays Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::current_index(), 3); assert_eq!(Balances::total_balance(&10), 1 + (3*session_reward - delay)/2); - assert_eq!(Balances::total_balance(&2), 20 + (3*session_reward - delay)/2); + assert_eq!(Balances::total_balance(&2), 500 + (3*session_reward - delay)/2); }); } #[test] fn multi_era_reward_should_work() { // should check that: - // The value of current_session_reward is set at the end of each era, based on - // slot_stake and session_reward. Check and verify this. - with_externalities(&mut ExtBuilder::default().build(), + // The value of current_session_reward is set at the end of each era, based on + // slot_stake and session_reward. Check and verify this. + with_externalities(&mut ExtBuilder::default() + .session_length(3) + .sessions_per_era(3) + .nominate(false) + .build(), || { let delay = 0; let session_reward = 10; @@ -275,15 +378,15 @@ fn multi_era_reward_should_work() { // Block 3 => Session 1 => Era 0 System::set_block_number(block); Timestamp::set_timestamp(block*5); // on time. - Session::check_rotate_session(System::block_number()); // QUESTIONS: why this matters ? + Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); // session triggered: the reward value stashed should be 10 -- defined in ExtBuilder genesis. assert_eq!(Staking::current_session_reward(), session_reward); assert_eq!(Staking::current_era_reward(), session_reward); - - block = 6; // Block 6 => Session 2 => Era 0 + + block = 6; // Block 6 => Session 2 => Era 0 System::set_block_number(block); Timestamp::set_timestamp(block*5 + delay); // a little late. Session::check_rotate_session(System::block_number()); @@ -303,7 +406,7 @@ fn multi_era_reward_should_work() { // 1 + sum of of the session rewards accumulated let recorded_balance = 1 + 3*session_reward - delay; assert_eq!(Balances::total_balance(&10), recorded_balance); - + // the reward for next era will be: session_reward * slot_stake let new_session_reward = Staking::session_reward() * Staking::slot_stake(); assert_eq!(Staking::current_session_reward(), new_session_reward); @@ -311,12 +414,13 @@ fn multi_era_reward_should_work() { // fast forward to next era: block=12;System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number()); block=15;System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number()); - + // intermediate test. assert_eq!(Staking::current_era_reward(), 2*new_session_reward); - + + // new era is triggered here. block=18;System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number()); - + // pay time assert_eq!(Balances::total_balance(&10), 3*new_session_reward + recorded_balance); }); @@ -324,162 +428,274 @@ fn multi_era_reward_should_work() { #[test] fn staking_should_work() { - // should test: + // should test: // * new validators can be added to the default set - // * new ones will be chosen per era (+ based on phragmen) - // * either one can unlock the stash and back-down from being a validator. - with_externalities(&mut ExtBuilder::default().session_length(1).build(), || { - assert_eq!(Staking::era_length(), 3); - assert_eq!(Staking::validator_count(), 2); + // * new ones will be chosen per era + // * either one can unlock the stash and back-down from being a validator via `chill`ing. + with_externalities(&mut ExtBuilder::default() + .sessions_per_era(3) + .nominate(false) + .fare(false) // to give 20 more staked value + .build(), + || { // remember + compare this along with the test. - assert_eq!(Session::validators(), vec![10, 20]); + assert_eq_uvec!(Session::validators(), vec![20, 10]); + assert_ok!(Staking::set_bonding_duration(2)); assert_eq!(Staking::bonding_duration(), 2); - // --- Block 1: + // put some money in account that we'll use. + for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); } + + // --- Block 1: System::set_block_number(1); - // give the man some coins - Balances::set_free_balance(&3, 3000); - // initial stakers: vec![(11, 10, balance_factor * 100), (21, 20, balance_factor * 200)], - // account 3 controlled by 4. - assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); // balance of 3 = 3000, stashed = 1500 - Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); - // No effects will be seen so far.s - assert_eq!(Session::validators(), vec![10, 20]); - - // --- Block 2: - System::set_block_number(2); - // Explicitly state the desire to validate for all of them. - // note that the controller account will state interest as representative of the stash-controller pair. - assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 })); + // add a new candidate for being a validator. account 3 controlled by 4. + assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); + // No effects will be seen so far. + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // --- Block 2: + System::set_block_number(2); Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); + // No effects will be seen so far. Era has not been yet triggered. - assert_eq!(Session::validators(), vec![10, 20]); + assert_eq_uvec!(Session::validators(), vec![20, 10]); - // --- Block 3: the validators will now change. + // --- Block 3: the validators will now change. System::set_block_number(3); Session::check_rotate_session(System::block_number()); - // TODO: the assertion in the section should be changed to something in sync with how phragmen works. - // for now just check that some arbitrary "two validators" have been chosen. + // 2 only voted for 4 and 20 assert_eq!(Session::validators().len(), 2); - assert_eq!(Session::validators(), vec![4, 20]); + assert_eq_uvec!(Session::validators(), vec![20, 4]); assert_eq!(Staking::current_era(), 1); // --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3 System::set_block_number(4); - - // unlock the entire stashed value. - Staking::unbond(Origin::signed(4), Staking::ledger(&4).unwrap().active).unwrap(); - Session::check_rotate_session(System::block_number()); + + // 4 will chill + Staking::chill(Origin::signed(4)).unwrap(); + // nothing should be changed so far. - assert_eq!(Session::validators(), vec![4, 20]); + assert_eq_uvec!(Session::validators(), vec![20, 4]); assert_eq!(Staking::current_era(), 1); - - - // --- Block 5: nothing. 4 is still there. + + + // --- Block 5: nothing. 4 is still there. System::set_block_number(5); Session::check_rotate_session(System::block_number()); - assert_eq!(Session::validators(), vec![4, 20]); + assert_eq_uvec!(Session::validators(), vec![20, 4]); assert_eq!(Staking::current_era(), 1); - // --- Block 6: 4 will be not be a validator as it has nothing in stash. + // --- Block 6: 4 will not be a validator. System::set_block_number(6); Session::check_rotate_session(System::block_number()); - assert_eq!(Session::validators().contains(&4), false); + assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::validators().contains(&4), false); + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // Note: the stashed value of 4 is still lock + assert_eq!(Staking::ledger(&4), Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![] })); + // e.g. it cannot spend more than 500 that it has free from the total 2000 + assert_noop!(Balances::reserve(&3, 501), "account liquidity restrictions prevent withdrawal"); + assert_ok!(Balances::reserve(&3, 409)); }); } +#[test] +fn less_than_needed_candidates_works() { + // Test the situation where the number of validators are less than `ValidatorCount` but more than + // The expected behavior is to choose all the candidates that have some vote. + with_externalities(&mut ExtBuilder::default() + .minimum_validator_count(1) + .validator_count(3) + .nominate(false) + .build(), + || { + assert_eq!(Staking::era_length(), 1); + assert_eq!(Staking::validator_count(), 3); + assert_eq!(Staking::minimum_validator_count(), 1); + + // initial validators + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // 10 and 20 are now valid candidates. + // trigger era + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 1); + + // both validators will be chosen again. NO election algorithm is even executed. + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // But the exposure is updated in a simple way. No external votes exists. This is purely self-vote. + assert_eq!(Staking::stakers(10).others.iter().map(|e| e.who).collect::>>(), vec![]); + assert_eq!(Staking::stakers(20).others.iter().map(|e| e.who).collect::>>(), vec![]); + }); +} #[test] -fn nominating_and_rewards_should_work() { - // TODO: This should be rewritten and tested with the Phragmen algorithm - // For now it tests a functionality which somehow overlaps with other tests: - // the fact that the nominator is rewarded properly. +fn no_candidate_emergency_condition() { + // Test the situation where the number of validators are less than `ValidatorCount` and less than + // The expected behavior is to choose all candidates from the previous era. with_externalities(&mut ExtBuilder::default() - .session_length(1).sessions_per_era(1).build(), + .minimum_validator_count(10) + .validator_count(15) + .validator_pool(true) + .nominate(false) + .build(), || { - let session_reward = 10; - let initial_balance = 1000; assert_eq!(Staking::era_length(), 1); - assert_eq!(Staking::validator_count(), 2); - assert_eq!(Staking::bonding_duration(), 3); - assert_eq!(Session::validators(), vec![10, 20]); + assert_eq!(Staking::validator_count(), 15); + + // initial validators + assert_eq_uvec!(Session::validators(), vec![10, 20, 30, 40]); + + // trigger era + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 1); + + // No one nominates => no one has a proper vote => no change + assert_eq_uvec!(Session::validators(), vec![10, 20, 30, 40]); + }); +} + +#[test] +fn nominating_and_rewards_should_work() { + // PHRAGMEN OUTPUT: running this test with the reference impl gives: + // + // Votes [('10', 1000, ['10']), ('20', 1000, ['20']), ('30', 1000, ['30']), ('40', 1000, ['40']), ('2', 1000, ['10', '20', '30']), ('4', 1000, ['10', '20', '40'])] + // Sequential Phragmén gives + // 10 is elected with stake 2200.0 and score 0.0003333333333333333 + // 20 is elected with stake 1800.0 and score 0.0005555555555555556 + + // 10 has load 0.0003333333333333333 and supported + // 10 with stake 1000.0 + // 20 has load 0.0005555555555555556 and supported + // 20 with stake 1000.0 + // 30 has load 0 and supported + // 30 with stake 0 + // 40 has load 0 and supported + // 40 with stake 0 + // 2 has load 0.0005555555555555556 and supported + // 10 with stake 600.0 20 with stake 400.0 30 with stake 0.0 + // 4 has load 0.0005555555555555556 and supported + // 10 with stake 600.0 20 with stake 400.0 40 with stake 0.0 + + // Sequential Phragmén with post processing gives + // 10 is elected with stake 2000.0 and score 0.0003333333333333333 + // 20 is elected with stake 2000.0 and score 0.0005555555555555556 + + // 10 has load 0.0003333333333333333 and supported + // 10 with stake 1000.0 + // 20 has load 0.0005555555555555556 and supported + // 20 with stake 1000.0 + // 30 has load 0 and supported + // 30 with stake 0 + // 40 has load 0 and supported + // 40 with stake 0 + // 2 has load 0.0005555555555555556 and supported + // 10 with stake 400.0 20 with stake 600.0 30 with stake 0 + // 4 has load 0.0005555555555555556 and supported + // 10 with stake 600.0 20 with stake 400.0 40 with stake 0.0 + + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .validator_pool(true) + .build(), + || { + // initial validators -- everyone is actually even. + assert_eq_uvec!(Session::validators(), vec![40, 30]); // Set payee to controller assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); assert_ok!(Staking::set_payee(Origin::signed(20), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(30), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(40), RewardDestination::Controller)); // default reward for the first session. + let session_reward = 10; assert_eq!(Staking::current_session_reward(), session_reward); // give the man some money - for i in 1..5 { Balances::set_free_balance(&i, initial_balance); } - Balances::set_free_balance(&10, initial_balance); - Balances::set_free_balance(&20, initial_balance); + let initial_balance = 1000; + for i in [1, 2, 3, 4, 5, 10, 11, 20, 21].iter() { + let _ = Balances::make_free_balance_be(i, initial_balance); + } + // bond two account pairs and state interest in nomination. + // 2 will nominate for 10, 20, 30 + assert_ok!(Staking::bond(Origin::signed(1), 2, 1000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21, 31])); + // 4 will nominate for 10, 20, 40 + assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41])); System::set_block_number(1); - // record their balances. - for i in 1..5 { assert_eq!(Balances::total_balance(&i), initial_balance); } + Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 1); + // 10 and 20 have more votes, they will be chosen by phragmen. + assert_eq_uvec!(Session::validators(), vec![20, 10]); - // bond two account pairs and state interest in nomination. - // NOTE: in the current naive version only the first vote matters and will be chosen anyhow. + // OLD validators must have already received some rewards. + assert_eq!(Balances::total_balance(&40), 1 + session_reward); + assert_eq!(Balances::total_balance(&30), 1 + session_reward); - // 2 will nominate for 10, 10 has 1000 in stash, 500 will be 1/3 of the total 1500 - assert_ok!(Staking::bond(Origin::signed(1), 2, 500, RewardDestination::Controller)); - assert_ok!(Staking::nominate(Origin::signed(2), vec![10, 20])); - // 4 will nominate for 20, 20 has 2000 in stash, 500 will be 1/5 of the total 2500 - assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Stash)); - assert_ok!(Staking::nominate(Origin::signed(4), vec![20, 10])); - + // ------ check the staked value of all parties. + + // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(11).own, 1000); + assert_eq!(Staking::stakers(11).total, 1000 + 798); + // 2 and 4 supported 10, each with stake 600, according to phragmen. + assert_eq!(Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), vec![399, 399]); + assert_eq!(Staking::stakers(11).others.iter().map(|e| e.who).collect::>>(), vec![3, 1]); + // total expo of 20, with 500 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(21).own, 1000); + assert_eq!(Staking::stakers(21).total, 1000 + 1200); + // 2 and 4 supported 20, each with stake 250, according to phragmen. + assert_eq!(Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), vec![600, 600]); + assert_eq!(Staking::stakers(21).others.iter().map(|e| e.who).collect::>>(), vec![3, 1]); + + // They are not chosen anymore + assert_eq!(Staking::stakers(31).total, 0); + assert_eq!(Staking::stakers(41).total, 0); - Session::check_rotate_session(System::block_number()); - assert_eq!(Staking::current_era(), 1); - // validators will not change, since selection currently is actually not dependent on nomination and votes, only stake. - assert_eq!(Session::validators(), vec![10, 20]); - // avalidators must have already received some rewards. - assert_eq!(Balances::total_balance(&10), initial_balance + session_reward); - assert_eq!(Balances::total_balance(&20), initial_balance + session_reward); - System::set_block_number(2); + Session::check_rotate_session(System::block_number()); // next session reward. let new_session_reward = Staking::session_reward() * Staking::slot_stake(); // nothing else will happen, era ends and rewards are paid again, - // it is expected that nominators will also be paid. - Session::check_rotate_session(System::block_number()); - + // it is expected that nominators will also be paid. See below - // Nominator 2: staked 1/3 of the total, gets 1/3 of the reward, chose controller as destination - assert_eq!(Balances::total_balance(&2), initial_balance + new_session_reward/3); - // The Associated validator will get the other 2/3 - assert_eq!(Balances::total_balance(&10), initial_balance + session_reward + 2*new_session_reward/3); + // Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 + assert_eq!(Balances::total_balance(&2), initial_balance + (2*new_session_reward/9 + 3*new_session_reward/11)); + // Nominator 4: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 + assert_eq!(Balances::total_balance(&4), initial_balance + (2*new_session_reward/9 + 3*new_session_reward/11)); - // Nominator 4: staked 1/5 of the total, gets 1/5 of the reward, chose stash as destination - // This means that the reward will go to 3, which is bonded as the stash of 4. - assert_eq!(Balances::total_balance(&3), initial_balance + new_session_reward/5); - // The Associated validator will get the other 4/5 - assert_eq!(Balances::total_balance(&20), initial_balance + session_reward + 4*new_session_reward/5); + // 10 got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9 + assert_eq!(Balances::total_balance(&10), initial_balance + 5*new_session_reward/9 + 2) ; + // 10 got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = 5/11 + assert_eq!(Balances::total_balance(&20), initial_balance + 5*new_session_reward/11); }); } #[test] fn nominators_also_get_slashed() { // A nominator should be slashed if the validator they nominated is slashed - with_externalities(&mut ExtBuilder::default() - .session_length(1).sessions_per_era(1).build(), - || { + with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { assert_eq!(Staking::era_length(), 1); assert_eq!(Staking::validator_count(), 2); // slash happens immediately. @@ -487,34 +703,42 @@ fn nominators_also_get_slashed() { // Account 10 has not been reported offline assert_eq!(Staking::slash_count(&10), 0); // initial validators - assert_eq!(Session::validators(), vec![10, 20]); + assert_eq_uvec!(Session::validators(), vec![20, 10]); + >::put(Perbill::from_percent(12)); // Set payee to controller assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); // give the man some money. let initial_balance = 1000; - for i in 1..3 { Balances::set_free_balance(&i, initial_balance); } - Balances::set_free_balance(&10, initial_balance); + for i in [1, 2, 3, 10].iter() { + let _ = Balances::make_free_balance_be(i, initial_balance); + } // 2 will nominate for 10 let nominator_stake = 500; assert_ok!(Staking::bond(Origin::signed(1), 2, nominator_stake, RewardDestination::default())); - assert_ok!(Staking::nominate(Origin::signed(2), vec![10, 20])); + assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 10])); // new era, pay rewards, - System::set_block_number(2); + System::set_block_number(1); Session::check_rotate_session(System::block_number()); + // Nominator stash didn't collect any. + assert_eq!(Balances::total_balance(&2), initial_balance); + // 10 goes offline Staking::on_offline_validator(10, 4); - let slash_value = Staking::current_offline_slash()*8; let expo = Staking::stakers(10); - let actual_slash = expo.own.min(slash_value); - let nominator_actual_slash = nominator_stake.min(expo.total - actual_slash); + let slash_value = Staking::offline_slash() * expo.total * 2_u64.pow(3); + let total_slash = expo.total.min(slash_value); + let validator_slash = expo.own.min(total_slash); + let nominator_slash = nominator_stake.min(total_slash - validator_slash); + // initial + first era reward + slash - assert_eq!(Balances::total_balance(&10), initial_balance + 10 - actual_slash); - assert_eq!(Balances::total_balance(&2), initial_balance - nominator_actual_slash); + assert_eq!(Balances::total_balance(&10), initial_balance + 10 - validator_slash); + assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); + // Because slashing happened. assert!(Staking::forcing_new_era().is_some()); }); } @@ -522,35 +746,46 @@ fn nominators_also_get_slashed() { #[test] fn double_staking_should_fail() { // should test (in the same order): - // * an account already bonded as controller CAN be reused as the controller of another account. - // * an account already bonded as stash cannot be the controller of another account. + // * an account already bonded as stash cannot be be stashed again. // * an account already bonded as stash cannot nominate. // * an account already bonded as controller can nominate. with_externalities(&mut ExtBuilder::default() - .session_length(1).sessions_per_era(2).build(), - || { - let arbitrary_value = 5; - System::set_block_number(1); - // 2 = controller, 1 stashed => ok - assert_ok!(Staking::bond(Origin::signed(1), 2, arbitrary_value, RewardDestination::default())); - // 2 = controller, 3 stashed (Note that 2 is reused.) => ok - assert_ok!(Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default())); - // 4 = not used so far, 1 stashed => not allowed. - assert_noop!(Staking::bond(Origin::signed(1), 4, arbitrary_value, RewardDestination::default()), "stash already bonded"); - // 1 = stashed => attempting to nominate should fail. - assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), "not a controller"); - // 2 = controller => nominating should work. - assert_ok!(Staking::nominate(Origin::signed(2), vec![1])); - }); + .sessions_per_era(2) + .build(), + || { + let arbitrary_value = 5; + // 2 = controller, 1 stashed => ok + assert_ok!(Staking::bond(Origin::signed(1), 2, arbitrary_value, RewardDestination::default())); + // 4 = not used so far, 1 stashed => not allowed. + assert_noop!(Staking::bond(Origin::signed(1), 4, arbitrary_value, RewardDestination::default()), "stash already bonded"); + // 1 = stashed => attempting to nominate should fail. + assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), "not a controller"); + // 2 = controller => nominating should work. + assert_ok!(Staking::nominate(Origin::signed(2), vec![1])); + }); +} + +#[test] +fn double_controlling_should_fail() { + // should test (in the same order): + // * an account already bonded as controller CANNOT be reused as the controller of another account. + with_externalities(&mut ExtBuilder::default() + .sessions_per_era(2) + .build(), + || { + let arbitrary_value = 5; + // 2 = controller, 1 stashed => ok + assert_ok!(Staking::bond(Origin::signed(1), 2, arbitrary_value, RewardDestination::default())); + // 2 = controller, 3 stashed (Note that 2 is reused.) => no-op + assert_noop!(Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default()), "controller already paired"); + }); } #[test] fn session_and_eras_work() { with_externalities(&mut ExtBuilder::default() - .session_length(1) .sessions_per_era(2) - .reward(10) - .build(), + .build(), || { assert_eq!(Staking::era_length(), 2); assert_eq!(Staking::sessions_per_era(), 2); @@ -620,24 +855,44 @@ fn session_and_eras_work() { #[test] fn cannot_transfer_staked_balance() { // Tests that a stash account cannot transfer funds - with_externalities(&mut ExtBuilder::default().build(), || { + with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { // Confirm account 11 is stashed assert_eq!(Staking::bonded(&11), Some(10)); // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(&11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::stakers(&10).total, 1000); + assert_eq!(Staking::stakers(&11).total, 1000); // Confirm account 11 cannot transfer as a result - assert_noop!(Balances::transfer(Origin::signed(11), 20, 1), "stash with too much under management"); + assert_noop!(Balances::transfer(Origin::signed(11), 20, 1), "account liquidity restrictions prevent withdrawal"); // Give account 11 extra free balance - Balances::set_free_balance(&11, 10000); + let _ = Balances::make_free_balance_be(&11, 10000); // Confirm that account 11 can now transfer some balance assert_ok!(Balances::transfer(Origin::signed(11), 20, 1)); }); } - +#[test] +fn cannot_transfer_staked_balance_2() { + // Tests that a stash account cannot transfer funds + // Same test as above but with 20, and more accurate. + // 21 has 2000 free balance but 1000 at stake + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .fare(true) + .build(), + || { + // Confirm account 21 is stashed + assert_eq!(Staking::bonded(&21), Some(20)); + // Confirm account 21 has some free balance + assert_eq!(Balances::free_balance(&21), 2000); + // Confirm account 21 (via controller 20) is totally staked + assert_eq!(Staking::stakers(&21).total, 1000); + // Confirm account 21 can transfer at most 1000 + assert_noop!(Balances::transfer(Origin::signed(21), 20, 1001), "account liquidity restrictions prevent withdrawal"); + assert_ok!(Balances::transfer(Origin::signed(21), 20, 1000)); + }); +} #[test] fn cannot_reserve_staked_balance() { @@ -648,113 +903,31 @@ fn cannot_reserve_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(&11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::stakers(&10).total, 1000); + assert_eq!(Staking::stakers(&11).own, 1000); // Confirm account 11 cannot transfer as a result - assert_noop!(Balances::reserve(&11, 1), "stash with too much under management"); + assert_noop!(Balances::reserve(&11, 1), "account liquidity restrictions prevent withdrawal"); // Give account 11 extra free balance - Balances::set_free_balance(&11, 10000); + let _ = Balances::make_free_balance_be(&11, 10000); // Confirm account 11 can now reserve balance assert_ok!(Balances::reserve(&11, 1)); }); } -#[test] -fn max_unstake_threshold_works() { - // Tests that max_unstake_threshold gets used when prefs.unstake_threshold is large - with_externalities(&mut ExtBuilder::default().build(), || { - const MAX_UNSTAKE_THRESHOLD: u32 = 10; - // Two users with maximum possible balance - Balances::set_free_balance(&10, u64::max_value()); - Balances::set_free_balance(&20, u64::max_value()); - - // Give them full exposer as a staker - >::insert(&10, Exposure { total: u64::max_value(), own: u64::max_value(), others: vec![]}); - >::insert(&20, Exposure { total: u64::max_value(), own: u64::max_value(), others: vec![]}); - - // Check things are initialized correctly - assert_eq!(Balances::free_balance(&10), u64::max_value()); - assert_eq!(Balances::free_balance(&20), u64::max_value()); - assert_eq!(Balances::free_balance(&10), Balances::free_balance(&20)); - assert_eq!(Staking::offline_slash_grace(), 0); - assert_eq!(Staking::current_offline_slash(), 20); - // Account 10 will have max unstake_threshold - assert_ok!(Staking::validate(Origin::signed(10), ValidatorPrefs { - unstake_threshold: MAX_UNSTAKE_THRESHOLD, - validator_payment: 0, - })); - // Account 20 could not set their unstake_threshold past 10 - assert_noop!(Staking::validate(Origin::signed(20), ValidatorPrefs { - unstake_threshold: 11, - validator_payment: 0}), - "unstake threshold too large" - ); - // Give Account 20 unstake_threshold 11 anyway, should still be limited to 10 - >::insert(20, ValidatorPrefs { - unstake_threshold: 11, - validator_payment: 0, - }); - - // Make slot_stake really large, as to not affect punishment curve - >::put(u64::max_value()); - // Confirm `slot_stake` is greater than exponential punishment, else math below will be different - assert!(Staking::slot_stake() > 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 20); - - // Report each user 1 more than the max_unstake_threshold - Staking::on_offline_validator(10, MAX_UNSTAKE_THRESHOLD as usize + 1); - Staking::on_offline_validator(20, MAX_UNSTAKE_THRESHOLD as usize + 1); - - // Show that each balance only gets reduced by 2^max_unstake_threshold - assert_eq!(Balances::free_balance(&10), u64::max_value() - 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 20); - assert_eq!(Balances::free_balance(&20), u64::max_value() - 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 20); - }); -} - -#[test] -fn slashing_does_not_cause_underflow() { - // Tests that slashing more than a user has does not underflow - with_externalities(&mut ExtBuilder::default().build(), || { - // One user with less than `max_value` will test underflow does not occur - Balances::set_free_balance(&10, 1); - - // Verify initial conditions - assert_eq!(Balances::free_balance(&10), 1); - assert_eq!(Staking::offline_slash_grace(), 0); - - // Set validator preference so that 2^unstake_threshold would cause overflow (greater than 64) - >::insert(10, ValidatorPrefs { - unstake_threshold: 10, - validator_payment: 0, - }); - - // Should not panic - Staking::on_offline_validator(10, 100); - // Confirm that underflow has not occurred, and account balance is set to zero - assert_eq!(Balances::free_balance(&10), 0); - }); -} - - #[test] fn reward_destination_works() { // Rewards go to the correct destination as determined in Payee - with_externalities(&mut ExtBuilder::default() - .sessions_per_era(1) - .session_length(1) - .build(), - || { - // Check that account 10 is a validator - assert!(>::exists(10)); + with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { + // Check that account 11 is a validator + assert!(Staking::current_elected().contains(&11)); // Check the balance of the validator account - assert_eq!(Balances::free_balance(&10), 1); + assert_eq!(Balances::free_balance(&10), 1); // Check the balance of the stash account - assert_eq!(Balances::free_balance(&11), 1000); - // Check these two accounts are bonded - assert_eq!(Staking::bonded(&11), Some(10)); + assert_eq!(Balances::free_balance(&11), 1000); // Check how much is at stake assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); - // Track current session reward - let mut current_session_reward = Staking::current_session_reward(); + // Check current session reward is 10 + let session_reward0 = Staking::current_session_reward(); // 10 // Move forward the system for payment System::set_block_number(1); @@ -762,18 +935,16 @@ fn reward_destination_works() { Session::check_rotate_session(System::block_number()); // Check that RewardDestination is Staked (default) - assert_eq!(Staking::payee(&10), RewardDestination::Staked); - // Check current session reward is 10 - assert_eq!(current_session_reward, 10); - // Check that reward went to the stash account - assert_eq!(Balances::free_balance(&11), 1000 + 10); + assert_eq!(Staking::payee(&11), RewardDestination::Staked); + // Check that reward went to the stash account of validator + assert_eq!(Balances::free_balance(&11), 1000 + session_reward0); // Check that amount at stake increased accordingly - assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 10, active: 1000 + 10, unlocking: vec![] })); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + session_reward0, active: 1000 + session_reward0, unlocking: vec![] })); // Update current session reward - current_session_reward = Staking::current_session_reward(); + let session_reward1 = Staking::current_session_reward(); // 1010 (1* slot_stake) //Change RewardDestination to Stash - >::insert(&10, RewardDestination::Stash); + >::insert(&11, RewardDestination::Stash); // Move forward the system for payment System::set_block_number(2); @@ -781,88 +952,86 @@ fn reward_destination_works() { Session::check_rotate_session(System::block_number()); // Check that RewardDestination is Stash - assert_eq!(Staking::payee(&10), RewardDestination::Stash); + assert_eq!(Staking::payee(&11), RewardDestination::Stash); // Check that reward went to the stash account - assert_eq!(Balances::free_balance(&11), 1010 + current_session_reward); - // Check that amount at stake is not increased - assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1010, active: 1010, unlocking: vec![] })); - // Update current session reward - current_session_reward = Staking::current_session_reward(); + assert_eq!(Balances::free_balance(&11), 1000 + session_reward0 + session_reward1); + // Record this value + let recorded_stash_balance = 1000 + session_reward0 + session_reward1; + // Check that amount at stake is NOT increased + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + session_reward0, active: 1000 + session_reward0, unlocking: vec![] })); + + // Change RewardDestination to Controller + >::insert(&11, RewardDestination::Controller); - //Change RewardDestination to Controller - >::insert(&10, RewardDestination::Controller); + // Check controller balance + assert_eq!(Balances::free_balance(&10), 1); // Move forward the system for payment System::set_block_number(3); Timestamp::set_timestamp(15); Session::check_rotate_session(System::block_number()); + let session_reward2 = Staking::current_session_reward(); // 1010 (1* slot_stake) // Check that RewardDestination is Controller - assert_eq!(Staking::payee(&10), RewardDestination::Controller); + assert_eq!(Staking::payee(&11), RewardDestination::Controller); // Check that reward went to the controller account - assert_eq!(Balances::free_balance(&10), 1 + current_session_reward); - // Check that amount at stake is not increased - assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1010, active: 1010, unlocking: vec![] })); - + assert_eq!(Balances::free_balance(&10), 1 + session_reward2); + // Check that amount at stake is NOT increased + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + session_reward0, active: 1000 + session_reward0, unlocking: vec![] })); + // Check that amount in staked account is NOT increased. + assert_eq!(Balances::free_balance(&11), recorded_stash_balance); }); - } #[test] fn validator_payment_prefs_work() { // Test that validator preferences are correctly honored - // Note: unstake threshold is being directly tested in slashing tests. + // Note: unstake threshold is being directly tested in slashing tests. // This test will focus on validator payment. - with_externalities(&mut ExtBuilder::default().build(), - || { + with_externalities(&mut ExtBuilder::default() + .session_length(3) + .sessions_per_era(3) + .build(), + || { + // Initial config let session_reward = 10; let validator_cut = 5; - let validator_initial_balance = Balances::total_balance(&11); - // Initial config should be correct - assert_eq!(Staking::era_length(), 9); - assert_eq!(Staking::sessions_per_era(), 3); - assert_eq!(Staking::last_era_length_change(), 0); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 0); - + let stash_initial_balance = Balances::total_balance(&11); assert_eq!(Staking::current_session_reward(), session_reward); // check the balance of a validator accounts. - assert_eq!(Balances::total_balance(&10), 1); + assert_eq!(Balances::total_balance(&10), 1); // check the balance of a validator's stash accounts. - assert_eq!(Balances::total_balance(&11), validator_initial_balance); + assert_eq!(Balances::total_balance(&11), stash_initial_balance); // and the nominator (to-be) - assert_eq!(Balances::total_balance(&2), 20); + let _ = Balances::make_free_balance_be(&2, 500); // add a dummy nominator. - // NOTE: this nominator is being added 'manually', use '.nominate()' to do it realistically. - >::insert(&10, Exposure { + >::insert(&11, Exposure { own: 500, // equal division indicates that the reward will be equally divided among validator and nominator. total: 1000, - others: vec![IndividualExposure {who: 2, value: 500 }] + others: vec![IndividualExposure {who: 2, value: 500 }] }); - >::insert(&2, RewardDestination::Controller); - >::insert(&10, ValidatorPrefs { - unstake_threshold: 3, - validator_payment: validator_cut + >::insert(&2, RewardDestination::Stash); + >::insert(&11, ValidatorPrefs { + unstake_threshold: 3, + validator_payment: validator_cut }); - // ------------ Fast forward - let mut block = 3; + // ------------ Fast forward // Block 3 => Session 1 => Era 0 + let mut block = 3; System::set_block_number(block); - Timestamp::set_timestamp(block*5); // on time. - Session::check_rotate_session(System::block_number()); + Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); // session triggered: the reward value stashed should be 10 -- defined in ExtBuilder genesis. assert_eq!(Staking::current_session_reward(), session_reward); assert_eq!(Staking::current_era_reward(), session_reward); - - block = 6; // Block 6 => Session 2 => Era 0 + + block = 6; // Block 6 => Session 2 => Era 0 System::set_block_number(block); - Timestamp::set_timestamp(block*5); // a little late. Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 2); @@ -872,7 +1041,6 @@ fn validator_payment_prefs_work() { block = 9; // Block 9 => Session 3 => Era 1 System::set_block_number(block); - Timestamp::set_timestamp(block*5); Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::current_index(), 3); @@ -880,137 +1048,184 @@ fn validator_payment_prefs_work() { // whats left to be shared is the sum of 3 rounds minus the validator's cut. let shared_cut = 3 * session_reward - validator_cut; // Validator's payee is Staked account, 11, reward will be paid here. - assert_eq!(Balances::total_balance(&11), validator_initial_balance + shared_cut/2 + validator_cut); + assert_eq!(Balances::total_balance(&11), stash_initial_balance + shared_cut/2 + validator_cut); // Controller account will not get any reward. assert_eq!(Balances::total_balance(&10), 1); // Rest of the reward will be shared and paid to the nominator in stake. - assert_eq!(Balances::total_balance(&2), 20 + shared_cut/2); + assert_eq!(Balances::total_balance(&2), 500 + shared_cut/2); }); -} -#[test] -fn staking_ledger_grows_and_shrinks() { - // TODO: Show that staking ledger grows with new events - // TODO: Show that staking ledger shrinks when user is removed -} - -#[test] -fn consolidate_unlocked_works() { - // TODO: Figure out what it does and then test it } #[test] fn bond_extra_works() { // Tests that extra `free_balance` in the stash can be added to stake + // NOTE: this tests only verifies `StakingLedger` for correct updates + // See `bond_extra_and_withdraw_unbonded_works` for more details and updates on `Exposure`. with_externalities(&mut ExtBuilder::default().build(), || { // Check that account 10 is a validator - assert!(>::exists(10)); + assert!(>::exists(11)); // Check that account 10 is bonded to account 11 assert_eq!(Staking::bonded(&11), Some(10)); // Check how much is at stake assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); // Give account 11 some large free balance greater than total - Balances::set_free_balance(&11, 1000000); - // Check the balance of the stash account - assert_eq!(Balances::free_balance(&11), 1000000); + let _ = Balances::make_free_balance_be(&11, 1000000); // Call the bond_extra function from controller, add only 100 - assert_ok!(Staking::bond_extra(Origin::signed(10), 100)); + assert_ok!(Staking::bond_extra(Origin::signed(11), 100)); // There should be 100 more `total` and `active` in the ledger assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] })); // Call the bond_extra function with a large number, should handle it - assert_ok!(Staking::bond_extra(Origin::signed(10), u64::max_value())); + assert_ok!(Staking::bond_extra(Origin::signed(11), u64::max_value())); // The full amount of the funds should now be in the total and active assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000000, active: 1000000, unlocking: vec![] })); - }); } #[test] -fn withdraw_unbonded_works() { - // TODO: Learn what it is and test it -} +fn bond_extra_and_withdraw_unbonded_works() { + // * Should test + // * Given an account being bonded [and chosen as a validator](not mandatory) + // * It can add extra funds to the bonded account. + // * it can unbond a portion of its funds from the stash account. + // * Once the unbonding period is done, it can actually take the funds out of the stash. + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .build(), + || { + // Set payee to controller. avoids confusion + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); -#[test] -fn reporting_misbehaviors_work() { - // TODO: Does this code exist? -} + // Set unbonding era (bonding_duration) to 2 + assert_ok!(Staking::set_bonding_duration(2)); -#[test] -fn correct_number_of_validators_are_chosen() { - // TODO: Check that number is at least minimum, and at most what is set - // TODO: Test emergency conditions? -} + // Give account 11 some large free balance greater than total + let _ = Balances::make_free_balance_be(&11, 1000000); + + // Initial config should be correct + assert_eq!(Staking::sessions_per_era(), 1); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + assert_eq!(Staking::current_session_reward(), 10); + + // check the balance of a validator accounts. + assert_eq!(Balances::total_balance(&10), 1); + + // confirm that 10 is a normal validator and gets paid at the end of the era. + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + // Initial state of 10 + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); + assert_eq!(Staking::stakers(&11), Exposure { total: 1000, own: 1000, others: vec![] }); + + // deposit the extra 100 units + Staking::bond_extra(Origin::signed(11), 100).unwrap(); + + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] })); + // Exposure is a snapshot! only updated after the next era update. + assert_ne!(Staking::stakers(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + + // trigger next era. + System::set_block_number(2);Timestamp::set_timestamp(10);Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::current_index(), 2); + + // ledger should be the same. + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] })); + // Exposure is now updated. + assert_eq!(Staking::stakers(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + + // Unbond almost all of the funds in stash. + Staking::unbond(Origin::signed(10), 1000).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] }) + ); + + // Attempting to free the balances now will fail. 2 eras need to pass. + Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] })); + + // trigger next era. + System::set_block_number(3); + Session::check_rotate_session(System::block_number()); + + assert_eq!(Staking::current_era(), 3); + assert_eq!(Session::current_index(), 3); + + // nothing yet + Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] })); + + // trigger next era. + System::set_block_number(4); + Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 4); + assert_eq!(Session::current_index(), 4); + Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + // Now the value is free and the staking ledger is updated. + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 100, active: 100, unlocking: vec![] })); + }) +} #[test] -fn slot_stake_is_least_staked_validator_and_limits_maximum_punishment() { - // TODO: Complete this test! +fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment() { // Test that slot_stake is determined by the least staked validator // Test that slot_stake is the maximum punishment that can happen to a validator - // Note that rewardDestination is the stash account by default - // Note that unlike reward slash will affect free_balance, not the stash account. with_externalities(&mut ExtBuilder::default() - .session_length(1) - .sessions_per_era(1) + .nominate(false) + .fare(false) .build(), || { // Confirm validator count is 2 assert_eq!(Staking::validator_count(), 2); // Confirm account 10 and 20 are validators - assert!(>::exists(&10) && >::exists(&20)); - // Confirm 10 has less stake than 20 - assert!(Staking::stakers(&10).total < Staking::stakers(&20).total); - assert_eq!(Staking::stakers(&10).total, 1000); - assert_eq!(Staking::stakers(&20).total, 2000); + assert!(>::exists(&11) && >::exists(&21)); - // Give the man some money. - Balances::set_free_balance(&10, 1000); - Balances::set_free_balance(&20, 1000); + assert_eq!(Staking::stakers(&11).total, 1000); + assert_eq!(Staking::stakers(&21).total, 2000); - // Confirm initial free balance. - assert_eq!(Balances::free_balance(&10), 1000); - assert_eq!(Balances::free_balance(&20), 1000); + // Give the man some money. + let _ = Balances::make_free_balance_be(&10, 1000); + let _ = Balances::make_free_balance_be(&20, 1000); // We confirm initialized slot_stake is this value - assert_eq!(Staking::slot_stake(), Staking::stakers(&10).total); - + assert_eq!(Staking::slot_stake(), Staking::stakers(&11).total); + // Now lets lower account 20 stake - >::insert(&20, Exposure { total: 69, own: 69, others: vec![] }); - assert_eq!(Staking::stakers(&20).total, 69); + >::insert(&21, Exposure { total: 69, own: 69, others: vec![] }); + assert_eq!(Staking::stakers(&21).total, 69); >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![] }); - // New era --> rewards are paid --> stakes are changed + // New era --> rewards are paid --> stakes are changed System::set_block_number(1); - Timestamp::set_timestamp(5); Session::check_rotate_session(System::block_number()); - assert_eq!(Staking::current_era(), 1); - // -- new balances + reward - assert_eq!(Staking::stakers(&10).total, 1000 + 10); - assert_eq!(Staking::stakers(&20).total, 69 + 10); - // -- Note that rewards are going drectly to stash, not as free balance. - assert_eq!(Balances::free_balance(&10), 1000); - assert_eq!(Balances::free_balance(&20), 1000); + // -- new balances + reward + assert_eq!(Staking::stakers(&11).total, 1000 + 10); + assert_eq!(Staking::stakers(&21).total, 69 + 10); // -- slot stake should also be updated. assert_eq!(Staking::slot_stake(), 79); - // // If 10 gets slashed now, despite having +1000 in stash, it will be slashed byt 79, which is the slot stake + // If 10 gets slashed now, it will be slashed by 5% of exposure.total * 2.pow(unstake_thresh) Staking::on_offline_validator(10, 4); - // // Confirm user has been reported - assert_eq!(Staking::slash_count(&10), 4); - // // check the balance of 10 (slash will be deducted from free balance.) - assert_eq!(Balances::free_balance(&10), 1000 - 79); - + // Confirm user has been reported + assert_eq!(Staking::slash_count(&11), 4); + // check the balance of 10 (slash will be deducted from free balance.) + assert_eq!(Balances::free_balance(&11), 1000 + 10 - 50 /*5% of 1000*/ * 8 /*2**3*/); }); } - #[test] fn on_free_balance_zero_stash_removes_validator() { // Tests that validator storage items are cleaned up when stash is empty @@ -1019,12 +1234,10 @@ fn on_free_balance_zero_stash_removes_validator() { .existential_deposit(10) .build(), || { - // Check that account 10 is a validator - assert!(>::exists(10)); // Check the balance of the validator account - assert_eq!(Balances::free_balance(&10), 256); + assert_eq!(Balances::free_balance(&10), 256); // Check the balance of the stash account - assert_eq!(Balances::free_balance(&11), 256000); + assert_eq!(Balances::free_balance(&11), 256000); // Check these two accounts are bonded assert_eq!(Staking::bonded(&11), Some(10)); @@ -1036,38 +1249,38 @@ fn on_free_balance_zero_stash_removes_validator() { // Check storage items that should be cleaned up assert!(>::exists(&10)); - assert!(>::exists(&10)); - assert!(>::exists(&10)); - assert!(>::exists(&10)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); // Reduce free_balance of controller to 0 - Balances::set_free_balance(&10, 0); - // Check total balance of account 10 - assert_eq!(Balances::total_balance(&10), 0); + Balances::slash(&10, u64::max_value()); // Check the balance of the stash account has not been touched - assert_eq!(Balances::free_balance(&11), 256000); + assert_eq!(Balances::free_balance(&11), 256000); // Check these two accounts are still bonded assert_eq!(Staking::bonded(&11), Some(10)); // Check storage items have not changed assert!(>::exists(&10)); - assert!(>::exists(&10)); - assert!(>::exists(&10)); - assert!(>::exists(&10)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); // Reduce free_balance of stash to 0 - Balances::set_free_balance(&11, 0); + Balances::slash(&11, u64::max_value()); // Check total balance of stash - assert_eq!(Balances::total_balance(&11), 0); + assert_eq!(Balances::total_balance(&11), 0); // Check storage items do not exist assert!(!>::exists(&10)); - assert!(!>::exists(&10)); - assert!(!>::exists(&10)); - assert!(!>::exists(&10)); - assert!(!>::exists(&10)); assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); }); } @@ -1082,49 +1295,679 @@ fn on_free_balance_zero_stash_removes_nominator() { // Make 10 a nominator assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); // Check that account 10 is a nominator - assert!(>::exists(10)); + assert!(>::exists(11)); // Check the balance of the nominator account - assert_eq!(Balances::free_balance(&10), 256); + assert_eq!(Balances::free_balance(&10), 256); // Check the balance of the stash account - assert_eq!(Balances::free_balance(&11), 256000); - // Check these two accounts are bonded - assert_eq!(Staking::bonded(&11), Some(10)); + assert_eq!(Balances::free_balance(&11), 256000); // Set payee information assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); - // Check storage items that should be cleaned up assert!(>::exists(&10)); - assert!(>::exists(&10)); - assert!(>::exists(&10)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); // Reduce free_balance of controller to 0 - Balances::set_free_balance(&10, 0); + Balances::slash(&10, u64::max_value()); // Check total balance of account 10 - assert_eq!(Balances::total_balance(&10), 0); + assert_eq!(Balances::total_balance(&10), 0); // Check the balance of the stash account has not been touched - assert_eq!(Balances::free_balance(&11), 256000); + assert_eq!(Balances::free_balance(&11), 256000); // Check these two accounts are still bonded assert_eq!(Staking::bonded(&11), Some(10)); // Check storage items have not changed assert!(>::exists(&10)); - assert!(>::exists(&10)); - assert!(>::exists(&10)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); // Reduce free_balance of stash to 0 - Balances::set_free_balance(&11, 0); + Balances::slash(&11, u64::max_value()); // Check total balance of stash - assert_eq!(Balances::total_balance(&11), 0); + assert_eq!(Balances::total_balance(&11), 0); // Check storage items do not exist assert!(!>::exists(&10)); - assert!(!>::exists(&10)); - assert!(!>::exists(&10)); - assert!(!>::exists(&10)); - assert!(!>::exists(&10)); assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + }); +} + +#[test] +fn phragmen_poc_works() { + // Tests the POC test of the phragmen, mentioned in the paper and reference implementation. + // Initial votes: + // Votes [ + // ('2', 500, ['10', '20', '30']), + // ('4', 500, ['10', '20', '40']), + // ('10', 1000, ['10']), + // ('20', 1000, ['20']), + // ('30', 1000, ['30']), + // ('40', 1000, ['40'])] + // + // Sequential Phragmén gives + // 10 is elected with stake 1666.6666666666665 and score 0.0005 + // 20 is elected with stake 1333.3333333333333 and score 0.00075 + + // 2 has load 0.00075 and supported + // 10 with stake 333.3333333333333 20 with stake 166.66666666666666 30 with stake 0.0 + // 4 has load 0.00075 and supported + // 10 with stake 333.3333333333333 20 with stake 166.66666666666666 40 with stake 0.0 + // 10 has load 0.0005 and supported + // 10 with stake 1000.0 + // 20 has load 0.00075 and supported + // 20 with stake 1000.0 + // 30 has load 0 and supported + // 30 with stake 0 + // 40 has load 0 and supported + // 40 with stake 0 + + // Sequential Phragmén with post processing gives + // 10 is elected with stake 1500.0 and score 0.0005 + // 20 is elected with stake 1500.0 and score 0.00075 + // + // 10 has load 0.0005 and supported + // 10 with stake 1000.0 + // 20 has load 0.00075 and supported + // 20 with stake 1000.0 + // 30 has load 0 and supported + // 30 with stake 0 + // 40 has load 0 and supported + // 40 with stake 0 + // 2 has load 0.00075 and supported + // 10 with stake 166.66666666666674 20 with stake 333.33333333333326 30 with stake 0 + // 4 has load 0.00075 and supported + // 10 with stake 333.3333333333333 20 with stake 166.66666666666666 40 with stake 0.0 + + + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .validator_pool(true) + .build(), + || { + // We don't really care about this. At this point everything is even. + assert_eq_uvec!(Session::validators(), vec![40, 30]); + + // Set payees to Controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(20), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(30), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(40), RewardDestination::Controller)); + + // no one is a nominator + assert_eq!(>::enumerate().count(), 0 as usize); + + // bond [2,1] / [4,3] a nominator + let _ = Balances::deposit_creating(&1, 1000); + let _ = Balances::deposit_creating(&3, 1000); + + assert_ok!(Staking::bond(Origin::signed(1), 2, 500, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21, 31])); + + assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41])); + + // New era => election algorithm will trigger + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // with stake 1666 and 1333 respectively + assert_eq!(Staking::stakers(11).own, 1000); + assert_eq!(Staking::stakers(11).total, 1000 + 332); + assert_eq!(Staking::stakers(21).own, 1000); + assert_eq!(Staking::stakers(21).total, 1000 + 666); + + // Nominator's stake distribution. + assert_eq!(Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), vec![166, 166]); + assert_eq!(Staking::stakers(11).others.iter().map(|e| e.value).sum::>(), 332); + assert_eq!(Staking::stakers(11).others.iter().map(|e| e.who).collect::>>(), vec![3, 1]); + + assert_eq!(Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), vec![333, 333]); + assert_eq!(Staking::stakers(21).others.iter().map(|e| e.value).sum::>(), 666); + assert_eq!(Staking::stakers(21).others.iter().map(|e| e.who).collect::>>(), vec![3, 1]); }); -} \ No newline at end of file +} + +#[test] +fn phragmen_election_works_with_post_processing() { + // tests the encapsulated phragmen::elect function. + // Votes [ + // ('10', 1000, ['10']), + // ('20', 1000, ['20']), + // ('30', 1000, ['30']), + // ('2', 50, ['10', '20']), + // ('4', 1000, ['10', '30']) + // ] + // Sequential Phragmén gives + // 10 is elected with stake 1705.7377049180327 and score 0.0004878048780487805 + // 30 is elected with stake 1344.2622950819673 and score 0.0007439024390243903 + + // 10 has load 0.0004878048780487805 and supported + // 10 with stake 1000.0 + // 20 has load 0 and supported + // 20 with stake 0 + // 30 has load 0.0007439024390243903 and supported + // 30 with stake 1000.0 + // 2 has load 0.0004878048780487805 and supported + // 10 with stake 50.0 20 with stake 0.0 + // 4 has load 0.0007439024390243903 and supported + // 10 with stake 655.7377049180328 30 with stake 344.26229508196724 + + // Sequential Phragmén with post processing gives + // 10 is elected with stake 1525.0 and score 0.0004878048780487805 + // 30 is elected with stake 1525.0 and score 0.0007439024390243903 + + // 10 has load 0.0004878048780487805 and supported + // 10 with stake 1000.0 + // 20 has load 0 and supported + // 20 with stake 0 + // 30 has load 0.0007439024390243903 and supported + // 30 with stake 1000.0 + // 2 has load 0.0004878048780487805 and supported + // 10 with stake 50.0 20 with stake 0.0 + // 4 has load 0.0007439024390243903 and supported + // 10 with stake 475.0 30 with stake 525.0 + with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { + // initial setup of 10 and 20, both validators + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // Bond [30, 31] as the third validator + assert_ok!(Staking::bond(Origin::signed(31), 30, 1000, RewardDestination::default())); + assert_ok!(Staking::validate(Origin::signed(30), ValidatorPrefs::default())); + + // bond [2,1](A), [4,3](B), as 2 nominators + for i in &[1, 3] { let _ = Balances::deposit_creating(i, 2000); } + + assert_ok!(Staking::bond(Origin::signed(1), 2, 50, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21])); + + assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 31])); + + let rounds = || 2 as usize; + let validators = || >::enumerate(); + let nominators = || >::enumerate(); + let min_validator_count = Staking::minimum_validator_count() as usize; + + let winners = phragmen::elect::( + rounds, + validators, + nominators, + Staking::slashable_balance_of, + min_validator_count, + ElectionConfig::> { + equalize: true, + tolerance: >::sa(10 as u64), + iterations: 10, + } + ); + + let winners = winners.unwrap(); + + // 10 and 30 must be the winners + assert_eq!(winners.iter().map(|w| w.who).collect::>>(), vec![11, 31]); + + let winner_10 = winners.iter().filter(|w| w.who == 11).nth(0).unwrap(); + let winner_30 = winners.iter().filter(|w| w.who == 31).nth(0).unwrap(); + + // Check exposures + assert_eq!(winner_10.exposure.total, 1000 + 525); + assert_eq!(winner_10.score, PerU128::from_max_value(165991398498018762665060784113057664)); + assert_eq!(winner_10.exposure.others[0].value, 475); + assert_eq!(winner_10.exposure.others[1].value, 50); + + assert_eq!(winner_30.exposure.total, 1000 + 525); + assert_eq!(winner_30.score, PerU128::from_max_value(253136882709478613064217695772412937)); + assert_eq!(winner_30.exposure.others[0].value, 525); + }) +} + +#[test] +fn switching_roles() { + // Test that it should be possible to switch between roles (nominator, validator, idle) with minimal overhead. + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .sessions_per_era(3) + .build(), + || { + // Reset reward destination + for i in &[10, 20] { assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); } + + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // put some money in account that we'll use. + for i in 1..7 { let _ = Balances::deposit_creating(&i, 5000); } + + // add 2 nominators + assert_ok!(Staking::bond(Origin::signed(1), 2, 2000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 5])); + + assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![21, 1])); + + // add a new validator candidate + assert_ok!(Staking::bond(Origin::signed(5), 6, 1000, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(6), ValidatorPrefs::default())); + + // new block + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + // no change + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // new block + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + // no change + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // new block --> ne era --> new validators + System::set_block_number(3); + Session::check_rotate_session(System::block_number()); + + // with current nominators 10 and 5 have the most stake + assert_eq_uvec!(Session::validators(), vec![6, 10]); + + // 2 decides to be a validator. Consequences: + assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + // new stakes: + // 10: 1000 self vote + // 20: 1000 self vote + 500 vote + // 6 : 1000 self vote + // 2 : 2000 self vote + 500 vote. + // Winners: 20 and 2 + + System::set_block_number(4); + Session::check_rotate_session(System::block_number()); + assert_eq_uvec!(Session::validators(), vec![6, 10]); + + System::set_block_number(5); + Session::check_rotate_session(System::block_number()); + assert_eq_uvec!(Session::validators(), vec![6, 10]); + + // ne era + System::set_block_number(6); + Session::check_rotate_session(System::block_number()); + assert_eq_uvec!(Session::validators(), vec![2, 20]); + }); +} + +#[test] +fn wrong_vote_is_null() { + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .validator_pool(true) + .build(), + || { + assert_eq_uvec!(Session::validators(), vec![40, 30]); + + // put some money in account that we'll use. + for i in 1..3 { let _ = Balances::deposit_creating(&i, 5000); } + + // add 1 nominators + assert_ok!(Staking::bond(Origin::signed(1), 2, 2000, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![ + 11, 21, // good votes + 1, 2, 15, 1000, 25 // crap votes. No effect. + ])); + + // new block + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + assert_eq_uvec!(Session::validators(), vec![20, 10]); + }); +} + +#[test] +fn bond_with_no_staked_value() { + // Behavior when someone bonds with no staked value. + // Particularly when she votes and the candidate is elected. + with_externalities(&mut ExtBuilder::default() + .validator_count(3) + .nominate(false) + .minimum_validator_count(1) + .build(), || { + // setup + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + let _ = Balances::deposit_creating(&3, 1000); + let initial_balance_2 = Balances::free_balance(&2); + let initial_balance_4 = Balances::free_balance(&4); + + // initial validators + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // Stingy validator. + assert_ok!(Staking::bond(Origin::signed(1), 2, 0, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + // Not elected even though we want 3. + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // min of 10 and 20. + assert_eq!(Staking::slot_stake(), 1000); + + // let's make the stingy one elected. + assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![1])); + + // no rewards paid to 2 and 4 yet + assert_eq!(Balances::free_balance(&2), initial_balance_2); + assert_eq!(Balances::free_balance(&4), initial_balance_4); + + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + // Stingy one is selected + assert_eq_uvec!(Session::validators(), vec![20, 10, 2]); + assert_eq!(Staking::stakers(1), Exposure { own: 0, total: 500, others: vec![IndividualExposure { who: 3, value: 500}]}); + // New slot stake. + assert_eq!(Staking::slot_stake(), 500); + + // no rewards paid to 2 and 4 yet + assert_eq!(Balances::free_balance(&2), initial_balance_2); + assert_eq!(Balances::free_balance(&4), initial_balance_4); + + System::set_block_number(3); + Session::check_rotate_session(System::block_number()); + + let reward = Staking::current_session_reward(); + // 2 will not get any reward + // 4 will get all the reward share + assert_eq!(Balances::free_balance(&2), initial_balance_2); + assert_eq!(Balances::free_balance(&4), initial_balance_4 + reward); + }); +} + +#[test] +fn bond_with_little_staked_value_bounded_by_slot_stake() { + // Behavior when someone bonds with little staked value. + // Particularly when she votes and the candidate is elected. + with_externalities(&mut ExtBuilder::default() + .validator_count(3) + .nominate(false) + .minimum_validator_count(1) + .build(), + || { + // setup + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + let initial_balance_2 = Balances::free_balance(&2); + let initial_balance_10 = Balances::free_balance(&10); + + // initial validators + assert_eq_uvec!(Session::validators(), vec![20, 10]); + + // Stingy validator. + assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + // 2 is elected. + // and fucks up the slot stake. + assert_eq_uvec!(Session::validators(), vec![20, 10, 2]); + assert_eq!(Staking::slot_stake(), 1); + + // Old ones are rewarded. + assert_eq!(Balances::free_balance(&10), initial_balance_10 + 10); + // no rewards paid to 2. This was initial election. + assert_eq!(Balances::free_balance(&2), initial_balance_2); + + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + assert_eq_uvec!(Session::validators(), vec![20, 10, 2]); + assert_eq!(Staking::slot_stake(), 1); + + let reward = Staking::current_session_reward(); + // 2 will not get the full reward, practically 1 + assert_eq!(Balances::free_balance(&2), initial_balance_2 + reward.max(1)); + // same for 10 + assert_eq!(Balances::free_balance(&10), initial_balance_10 + 10 + reward.max(1)); + }); +} + + +#[test] +#[ignore] // Enable this once post-processing is on. +fn phragmen_linear_worse_case_equalize() { + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .validator_pool(true) + .fare(true) + .build(), + || { + let bond_validator = |a, b| { + let _ = Balances::deposit_creating(&(a-1), b); + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(a), ValidatorPrefs::default())); + }; + let bond_nominator = |a, b, v| { + let _ = Balances::deposit_creating(&(a-1), b); + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(a), v)); + }; + + for i in &[10, 20, 30, 40] { assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); } + + bond_validator(50, 1000); + bond_validator(60, 1000); + bond_validator(70, 1000); + + bond_nominator(2, 2000, vec![11]); + bond_nominator(4, 1000, vec![11, 21]); + bond_nominator(6, 1000, vec![21, 31]); + bond_nominator(8, 1000, vec![31, 41]); + bond_nominator(110, 1000, vec![41, 51]); + bond_nominator(112, 1000, vec![51, 61]); + bond_nominator(114, 1000, vec![61, 71]); + + assert_eq_uvec!(Session::validators(), vec![40, 30]); + assert_ok!(Staking::set_validator_count(7)); + + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + assert_eq_uvec!(Session::validators(), vec![10, 60, 40, 20, 50, 30, 70]); + + // Sequential Phragmén with post processing gives + // 10 is elected with stake 3000.0 and score 0.00025 + // 30 is elected with stake 2008.8712884829595 and score 0.0003333333333333333 + // 50 is elected with stake 2000.0001049958742 and score 0.0003333333333333333 + // 60 is elected with stake 1991.128921508789 and score 0.0004444444444444444 + // 20 is elected with stake 2017.7421569824219 and score 0.0005277777777777777 + // 40 is elected with stake 2000.0001049958742 and score 0.0005555555555555556 + // 70 is elected with stake 1982.2574230340813 and score 0.0007222222222222222 + + assert_eq!(Staking::stakers(11).total, 3000); + assert_eq!(Staking::stakers(31).total, 2035); + assert_eq!(Staking::stakers(51).total, 2000); + assert_eq!(Staking::stakers(61).total, 1968); + assert_eq!(Staking::stakers(21).total, 2035); + assert_eq!(Staking::stakers(41).total, 2024); + assert_eq!(Staking::stakers(71).total, 1936); + }) +} + +#[test] +fn phragmen_chooses_correct_number_of_validators() { + with_externalities(&mut ExtBuilder::default() + .nominate(true) + .validator_pool(true) + .fare(true) + .validator_count(1) + .build(), + || { + assert_eq!(Staking::validator_count(), 1); + assert_eq!(Session::validators().len(), 1); + + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + assert_eq!(Session::validators().len(), 1); + }) +} + + +#[test] +fn phragmen_score_should_be_accurate_on_large_stakes() { + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .build() + , || { + let bond_validator = |a, b| { + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(a), ValidatorPrefs::default())); + }; + + for i in 1..=8 { + let _ = Balances::make_free_balance_be(&i, u64::max_value()); + } + + bond_validator(2, u64::max_value()); + bond_validator(4, u64::max_value()); + bond_validator(6, u64::max_value()-1); + bond_validator(8, u64::max_value()-2); + + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + assert_eq!(Session::validators(), vec![4, 2]); + }) +} + +#[test] +fn phragmen_should_not_overflow_validators() { + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .build() + , || { + let bond_validator = |a, b| { + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(a), ValidatorPrefs::default())); + }; + let bond_nominator = |a, b, v| { + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(a), v)); + }; + let check_exposure = |a| { + let expo = Staking::stakers(&a); + assert_eq!(expo.total, expo.own + expo.others.iter().map(|e| e.value).sum::()); + }; + + for i in 1..=8 { + let _ = Balances::make_free_balance_be(&i, u64::max_value()); + } + + let _ = Staking::chill(Origin::signed(10)); + let _ = Staking::chill(Origin::signed(20)); + + bond_validator(2, u64::max_value()); + bond_validator(4, u64::max_value()); + + bond_nominator(6, u64::max_value()/2, vec![1, 3]); + bond_nominator(8, u64::max_value()/2, vec![1, 3]); + + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + assert_eq_uvec!(Session::validators(), vec![4, 2]); + check_exposure(4); + check_exposure(2); + }) +} + +#[test] +fn phragmen_should_not_overflow_nominators() { + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .build() + , || { + let bond_validator = |a, b| { + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(a), ValidatorPrefs::default())); + }; + let bond_nominator = |a, b, v| { + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(a), v)); + }; + let check_exposure = |a| { + let expo = Staking::stakers(&a); + assert_eq!(expo.total, expo.own + expo.others.iter().map(|e| e.value).sum::()); + }; + + let _ = Staking::chill(Origin::signed(10)); + let _ = Staking::chill(Origin::signed(20)); + + for i in 1..=8 { + let _ = Balances::make_free_balance_be(&i, u64::max_value()); + } + + bond_validator(2, u64::max_value()/2); + bond_validator(4, u64::max_value()/2); + + bond_nominator(6, u64::max_value(), vec![1, 3]); + bond_nominator(8, u64::max_value(), vec![1, 3]); + + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + assert_eq_uvec!(Session::validators(), vec![4, 2]); + check_exposure(4); + check_exposure(2); + }) +} + +#[test] +fn phragmen_should_not_overflow_ultimate() { + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .build() + , || { + let bond_validator = |a, b| { + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(a), ValidatorPrefs::default())); + }; + let bond_nominator = |a, b, v| { + assert_ok!(Staking::bond(Origin::signed(a-1), a, b, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(a), v)); + }; + let check_exposure = |a| { + let expo = Staking::stakers(&a); + assert_eq!(expo.total, expo.own + expo.others.iter().map(|e| e.value).sum::()); + }; + + for i in 1..=8 { + let _ = Balances::make_free_balance_be(&i, u64::max_value()); + } + + bond_validator(2, u64::max_value()); + bond_validator(4, u64::max_value()); + + bond_nominator(6, u64::max_value(), vec![1, 3]); + bond_nominator(8, u64::max_value(), vec![1, 3]); + + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + assert_eq_uvec!(Session::validators(), vec![4, 2]); + check_exposure(4); + check_exposure(2); + }) +} diff --git a/srml/sudo/Cargo.toml b/srml/sudo/Cargo.toml index f607385131ce9ed88bb095e79cfff732e4014c9c..ef0bb59b538c5519b6b1f1cb7e4301d115eb5cac 100644 --- a/srml/sudo/Cargo.toml +++ b/srml/sudo/Cargo.toml @@ -6,8 +6,8 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } parity-codec-derive = { version = "3.1", default-features = false } sr-std = { path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } @@ -22,7 +22,7 @@ substrate-primitives = { path = "../../core/primitives" } [features] default = ["std"] std = [ - "serde/std", + "serde", "parity-codec/std", "parity-codec-derive/std", "sr-std/std", diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index 5ff7fee52d2fbf1b3695ceed083e9befb1e5f929..88e3a9c9655918ef4cc95a43dce0c6c94010c9a7 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,8 +14,113 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! The Example: A simple example of a runtime module demonstrating -//! concepts, APIs and structures common to most runtime modules. +//! # Sudo Module +//! +//! ## Overview +//! +//! The sudo module allows for a single account (called the "sudo key") +//! to execute dispatchable functions that require a `Root` call +//! or designate a new account to replace them as the sudo key. +//! Only one account can be the sudo key at a time. +//! +//! You can start using the sudo module by implementing the sudo [`Trait`]. +//! +//! Supported dispatchable functions are documented in the [`Call`] enum. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! Only the sudo key can call the dispatchable functions from the sudo module. +//! +//! * `sudo` - Make a `Root` call to a dispatchable function. +//! * `set_key` - Assign a new account to be the sudo key. +//! +//! Please refer to the [`Call`] enum and its associated variants for documentation on each function. +//! +//! ## Usage +//! +//! ### Prerequisites +//! +//! To use the sudo module in your runtime, you must implement the following trait in your runtime: +//! +//! ```ignore +//! impl sudo::Trait for Runtime { +//! type Event = Event; +//! type Proposal = Call; +//! } +//! ``` +//! +//! You can then import the Sudo module in your `construct_runtime!` macro with: +//! +//! ```ignore +//! Sudo: sudo, +//! ``` +//! +//! ### Executing Privileged Functions +//! +//! The sudo module itself is not intended to be used within other modules. +//! Instead, you can build "privileged functions" in other modules that require `Root` origin. +//! You can execute these privileged functions by calling `sudo` with the sudo key account. +//! Privileged functions cannot be directly executed via an extrinsic. +//! +//! Learn more about privileged functions and `Root` origin in the [`Origin`] type documentation. +//! +//! ### Simple Code Snippet +//! +//! This is an example of a module that exposes a privileged function: +//! +//! ```ignore +//! use support::{decl_module, dispatch::Result}; +//! use system::ensure_root; +//! +//! pub trait Trait: system::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn privileged_function(origin) -> Result { +//! ensure_root(origin)?; +//! +//! // do something... +//! +//! Ok(()) +//! } +//! } +//! } +//! ``` +//! +//! ### Example from SRML +//! +//! The consensus module exposes a `set_code` privileged function +//! that allows you to set the on-chain Wasm runtime code: +//! +//! ```ignore +//! /// Set the new code. +//! pub fn set_code(new: Vec) { +//! storage::unhashed::put_raw(well_known_keys::CODE, &new); +//! } +//! ``` +//! +//! ## Genesis Config +//! +//! To use the sudo module, you need to set an initial superuser account as the sudo `key`. +//! +//! ```ignore +//! GenesisConfig { +//! sudo: Some(SudoConfig { +//! key: AccountId, +//! }) +//! } +//! ``` +//! +//! ## Related Modules +//! +//! * [Consensus](../srml_consensus/index.html) +//! * [Democracy](../srml_democracy/index.html) +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html +//! [`Origin`]: https://docs.substrate.dev/docs/substrate-types #![cfg_attr(not(feature = "std"), no_std)] @@ -33,10 +138,13 @@ pub trait Trait: system::Trait { } decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what its working on. + // Simple declaration of the `Module` type. Lets the macro know what it's working on. pub struct Module for enum Call where origin: T::Origin { fn deposit_event() = default; + /// Authenticates the sudo key and dispatches a function call with `Root` origin. + /// + /// The dispatch origin for this call must be _Signed_. fn sudo(origin, proposal: Box) { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; @@ -46,6 +154,9 @@ decl_module! { Self::deposit_event(RawEvent::Sudid(ok)); } + /// Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo key. + /// + /// The dispatch origin for this call must be _Signed_. fn set_key(origin, new: ::Source) { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; @@ -58,7 +169,6 @@ decl_module! { } } -/// An event in this module. decl_event!( pub enum Event where AccountId = ::AccountId { /// A sudo just took place. @@ -70,6 +180,7 @@ decl_event!( decl_storage! { trait Store for Module as Sudo { + /// The `AccountId` of the sudo key. Key get(key) config(): T::AccountId; } } diff --git a/srml/support/Cargo.toml b/srml/support/Cargo.toml index cda9aaa904d705f13ec19908bb5673135cfe8e01..318eba343b95e1258fd69a439d970ecb63257755 100644 --- a/srml/support/Cargo.toml +++ b/srml/support/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] hex-literal = { version = "0.1.0", optional = true } -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } srml-metadata = { path = "../metadata", default-features = false } sr-std = { path = "../../core/sr-std", default-features = false } runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } @@ -17,6 +17,7 @@ inherents = { package = "substrate-inherents", path = "../../core/inherents", de srml-support-procedural = { path = "./procedural" } paste = "0.1" once_cell = { version = "0.1.6", default-features = false, optional = true } +bitmask = { git = "https://github.com/paritytech/bitmask", default-features = false } [dev-dependencies] pretty_assertions = "0.5.1" @@ -26,7 +27,8 @@ default = ["std"] std = [ "hex-literal", "once_cell", - "serde/std", + "bitmask/std", + "serde", "serde_derive", "runtime_io/std", "parity-codec/std", diff --git a/srml/support/procedural/src/lib.rs b/srml/support/procedural/src/lib.rs index dbf7c216330b3e2a44989652c6f8293693f59673..342745efde0ef4fbb4f203a39a1c7dd172f0787d 100644 --- a/srml/support/procedural/src/lib.rs +++ b/srml/support/procedural/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -33,31 +33,73 @@ use proc_macro::TokenStream; /// ```nocompile /// decl_storage! { /// trait Store for Module as Example { -/// Dummy get(dummy) config(): Option; -/// Foo get(foo) config(): T::Balance; +/// Foo get(foo) config(): u32=12; +/// Bar: map u32 => u32; +/// pub Zed build(|config| vec![(0, 0)]): linked_map u32 => u32; /// } /// } /// ``` /// -/// 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 visible 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. +/// Declaration is set with this header `(pub) trait Store for Module as Example` +/// with `Store` a (pub) trait generated associating each storage to the Module and +/// `as Example` setting the prefix used for storages of this module, it must be unique, +/// another module with same name and same inner storage name will conflict. /// -/// An optional `GenesisConfig` struct for storage initialization can be defined, either specifically as in : +/// Basic storage consist of a name and a type, supported types are: +/// * storage value: `Foo: type`: implements [StorageValue](https://crates.parity.io/srml_support/storage/trait.StorageValue.html) +/// * storage map: `Foo: map type => type`: implements [StorageMap](https://crates.parity.io/srml_support/storage/trait.StorageMap.html) +/// * storage linked map: `Foo: linked_map type => type`: implements [StorageMap](https://crates.parity.io/srml_support/storage/trait.StorageMap.html) and [EnumarableStorageMap](https://crates.parity.io/srml_support/storage/trait.EnumerableStorageMap.html) +/// * storage double map: Foo: double_map u32, $hash(u32) => u32;` implements `StorageDoubleMap` with hasher $hash one available in `Hashable` trait +/// /!\ be careful while choosing the Hash, indeed malicious could craft second keys to lower the trie. +/// +/// And it can be extended as such: +/// +/// `#vis #name get(#getter) config(#field_name) build(#closure): #type = #default;` +/// * `#vis`: set the visibility of the structure +/// * `#name`: name of the storage, used as a prefix in the storage +/// * [optional] `get(#getter)`: implements the function #getter to `Module` +/// * [optional] `config(#field_name)`: `field_name` is optional if get is set: include in `GenesisConfig` +/// * [optional] `build(#closure)`: closure called with storage overlays +/// * `#type`: storage type +/// * [optional] `#default`: value returned when none +/// +/// Storages are accessible in multiples ways, using: +/// * the structure: `Foo::` +/// * the `Store` trait structure: ` as Store>::Foo` +/// * the getter on the module which calls get on the structure: `Module::::foo()` +/// +/// ## GenesisConfig +/// +/// An optional `GenesisConfig` struct for storage initialization can be defined, either +/// when at least one storage field requires default initialization +/// (both `get` and `config` or `build`), or specifically as in : /// ```nocompile /// decl_storage! { /// trait Store for Module as Example { /// } /// add_extra_genesis { /// config(genesis_field): GenesisFieldType; +/// config(genesis_field2): GenesisFieldType; +/// ... /// build(|_: &mut StorageOverlay, _: &mut ChildrenStorageOverlay, _: &GenesisConfig| { +/// // Modification of storages /// }) /// } /// } /// ``` -/// or when at least one storage field requires default initialization (both `get` and `config` or `build`). /// This struct can be expose as `Config` by `decl_runtime` macro. +/// +/// ### Module with instances +/// +/// `decl_storage!` macro support building modules with instances with the following syntax: (DefaultInstance type +/// is optional) +/// ```nocompile +/// trait Store for Module, I: Instance=DefaultInstance> as Example {} +/// ``` +/// +/// Then the genesis config is generated with two generic parameter `GenesisConfig` +/// and storages are now accessible using two generic parameters like: +/// `>::get()` or `Dummy::::get()` #[proc_macro] pub fn decl_storage(input: TokenStream) -> TokenStream { storage::transformation::decl_storage_impl(input) diff --git a/srml/support/procedural/src/storage/impls.rs b/srml/support/procedural/src/storage/impls.rs index 0f953967d8f4fdfafc16f1d9fd205a9172940c9c..5a8f7f65d5d8e835e59fc691844ee18166ffb70a 100644 --- a/srml/support/procedural/src/storage/impls.rs +++ b/srml/support/procedural/src/storage/impls.rs @@ -17,7 +17,7 @@ use proc_macro2::TokenStream as TokenStream2; use syn; use quote::quote; -use crate::storage::transformation::DeclStorageTypeInfos; +use crate::storage::transformation::{DeclStorageTypeInfos, InstanceOpts}; pub fn option_unwrap(is_option: bool) -> TokenStream2 { if !is_option { @@ -29,28 +29,38 @@ pub fn option_unwrap(is_option: bool) -> TokenStream2 { } } -pub(crate) struct Impls<'a> { +// prefix for consts in trait Instance +pub(crate) const PREFIX_FOR: &str = "PREFIX_FOR_"; +pub(crate) const HEAD_KEY_FOR: &str = "HEAD_KEY_FOR_"; + +pub(crate) struct Impls<'a, I: Iterator> { pub scrate: &'a TokenStream2, pub visibility: &'a syn::Visibility, pub traitinstance: &'a syn::Ident, pub traittype: &'a syn::TypeParamBound, + pub instance_opts: &'a InstanceOpts, pub type_infos: DeclStorageTypeInfos<'a>, pub fielddefault: TokenStream2, pub prefix: String, + pub cratename: &'a syn::Ident, pub name: &'a syn::Ident, + pub attrs: I, } -impl<'a> Impls<'a> { +impl<'a, I: Iterator> Impls<'a, I> { pub fn simple_value(self) -> TokenStream2 { let Self { scrate, visibility, traitinstance, traittype, + instance_opts, type_infos, fielddefault, prefix, name, + attrs, + .. } = self; let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; let option_simple_1 = option_unwrap(is_option); @@ -68,17 +78,32 @@ impl<'a> Impls<'a> { } }; + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + + let final_prefix = if let Some(instance) = instance { + let const_name = syn::Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#const_name.as_bytes() } + } else { + quote!{ #prefix.as_bytes() } + }; + // generator for value quote!{ + #( #[ #attrs ] )* + #visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>); - #visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>); - - impl<#traitinstance: #traittype> #scrate::storage::generator::StorageValue<#typ> for #name<#traitinstance> { + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageValue<#typ> for #name<#traitinstance, #instance> { type Query = #value_type; /// Get the storage key. fn key() -> &'static [u8] { - #prefix.as_bytes() + #final_prefix } /// Load the value from the provided storage instance. @@ -102,7 +127,6 @@ impl<'a> Impls<'a> { ret } } - } } @@ -112,10 +136,13 @@ impl<'a> Impls<'a> { visibility, traitinstance, traittype, + instance_opts, type_infos, fielddefault, prefix, name, + attrs, + .. } = self; let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; let option_simple_1 = option_unwrap(is_option); @@ -132,21 +159,38 @@ impl<'a> Impls<'a> { } } }; + + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + + let final_prefix = if let Some(instance) = instance { + let const_name = syn::Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#const_name.as_bytes() } + } else { + quote!{ #prefix.as_bytes() } + }; + // generator for map quote!{ - #visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>); + #( #[ #attrs ] )* + #visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>); - impl<#traitinstance: #traittype> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance> { + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance> { type Query = #value_type; /// Get the prefix key in storage. fn prefix() -> &'static [u8] { - #prefix.as_bytes() + #final_prefix } /// Get the storage key used to fetch a value corresponding to a specific key. fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec { - let mut key = #prefix.as_bytes().to_vec(); + let mut key = >::prefix().to_vec(); #scrate::codec::Encode::encode_to(x, &mut key); key } @@ -182,16 +226,41 @@ impl<'a> Impls<'a> { visibility, traitinstance, traittype, + instance_opts, type_infos, fielddefault, prefix, name, + attrs, + .. } = self; + + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + + let final_prefix = if let Some(instance) = instance { + let const_name = syn::Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#const_name.as_bytes() } + } else { + quote!{ #prefix.as_bytes() } + }; + + // make sure to use different prefix for head and elements. + let final_head_key = if let Some(instance) = instance { + let const_name = syn::Ident::new(&format!("{}{}", HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#const_name.as_bytes() } + } else { + let final_head_key = format!("head of {}", prefix); + quote!{ #final_head_key.as_bytes() } + }; + let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; let option_simple_1 = option_unwrap(is_option); - // make sure to use different prefix for head and elements. - let head_key = format!("head of {}", prefix); - let prefix = format!("{}", prefix); let name_lowercase = name.to_string().to_lowercase(); let inner_module = syn::Ident::new(&format!("__linked_map_details_for_{}_do_not_use", name_lowercase), name.span()); let linkage = syn::Ident::new(&format!("__LinkageFor{}DoNotUse", name), name.span()); @@ -247,30 +316,22 @@ impl<'a> Impls<'a> { pub _data: #phantom_data, } - impl<'a, S: #scrate::GenericStorage, K, V> Iterator for Enumerator<'a, S, K, V> where - K: 'a + #scrate::codec::Codec, - V: 'a + #scrate::codec::Decode, + impl<'a, S: #scrate::GenericStorage, #traitinstance: #traittype, #instance #bound_instantiable> Iterator for Enumerator<'a, S, #kty, (#typ, #traitinstance, #instance)> + where #traitinstance: 'a { - type Item = (K, V); + type Item = (#kty, #typ); fn next(&mut self) -> Option { let next = self.next.take()?; - let key_for = key_for(&next); - let (val, linkage): (V, Linkage) = self.storage.get(&*key_for) + let key_for = as #scrate::storage::generator::StorageMap<#kty, #typ>>::key_for(&next); + let (val, linkage): (#typ, Linkage<#kty>) = self.storage.get(&*key_for) .expect("previous/next only contain existing entires; we enumerate using next; entry exists; qed"); self.next = linkage.next; Some((next, val)) } } - /// Generate a storage key for given item. - pub(crate) fn key_for(key: &Key) -> #scrate::rstd::vec::Vec { - let mut key_for = #prefix.as_bytes().to_vec(); - #scrate::codec::Encode::encode_to(&key, &mut key_for); - key_for - } - - pub(crate) trait Utils<#traitinstance: #traittype> { + pub(crate) trait Utils<#traitinstance: #traittype, #instance #bound_instantiable> { /// Update linkage when this element is removed. /// /// Takes care of updating previous and next elements points @@ -300,17 +361,18 @@ impl<'a> Impls<'a> { }; let structure = quote! { - #visibility struct #name<#traitinstance: #traittype>(#phantom_data<#traitinstance>); + #( #[ #attrs ] )* + #visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#phantom_data<(#traitinstance #comma_instance)>); - impl<#traitinstance: #traittype> self::#inner_module::Utils<#traitinstance> for #name<#traitinstance> { + impl<#traitinstance: #traittype, #instance #bound_instantiable> self::#inner_module::Utils<#traitinstance, #instance> for #name<#traitinstance, #instance> { fn remove_linkage( linkage: self::#inner_module::Linkage<#kty>, storage: &S, ) { - use self::#inner_module::{key_for, Utils}; + use self::#inner_module::Utils; - let next_key = linkage.next.as_ref().map(|x| key_for(x)); - let prev_key = linkage.previous.as_ref().map(|x| key_for(x)); + let next_key = linkage.next.as_ref().map(|x| #as_map::key_for(x)); + let prev_key = linkage.previous.as_ref().map(|x| #as_map::key_for(x)); if let Some(prev_key) = prev_key { // Retrieve previous element and update `next` @@ -343,12 +405,12 @@ impl<'a> Impls<'a> { storage: &S, key: &#kty, ) -> self::#inner_module::Linkage<#kty> { - use self::#inner_module::{key_for, Utils}; + use self::#inner_module::Utils; if let Some(head) = Self::read_head(storage) { // update previous head predecessor { - let head_key = key_for(&head); + let head_key = #as_map::key_for(&head); let (data, linkage) = Self::read_with_linkage(storage, &*head_key).expect(r#" head is set when first element is inserted and unset when last element is removed; if head is Some then it points to existing key; qed @@ -372,13 +434,13 @@ impl<'a> Impls<'a> { } fn read_head(storage: &S) -> Option<#kty> { - storage.get(#head_key.as_bytes()) + storage.get(#final_head_key) } fn write_head(storage: &S, head: Option<&#kty>) { match head { - Some(head) => storage.put(#head_key.as_bytes(), head), - None => storage.kill(#head_key.as_bytes()), + Some(head) => storage.put(#final_head_key, head), + None => storage.kill(#final_head_key), } } } @@ -389,17 +451,19 @@ impl<'a> Impls<'a> { #structure - impl<#traitinstance: #traittype> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance> { + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance> { type Query = #value_type; /// Get the prefix key in storage. fn prefix() -> &'static [u8] { - #prefix.as_bytes() + #final_prefix } /// Get the storage key used to fetch a value corresponding to a specific key. - fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec { - self::#inner_module::key_for(x) + fn key_for(key: &#kty) -> #scrate::rstd::vec::Vec { + let mut key_for = #as_map::prefix().to_vec(); + #scrate::codec::Encode::encode_to(&key, &mut key_for); + key_for } /// Load the value associated with the given key from the map. @@ -409,9 +473,9 @@ impl<'a> Impls<'a> { /// Take the value, reading and removing it. fn take(key: &#kty, storage: &S) -> Self::Query { - use self::#inner_module::{Utils, key_for}; + use self::#inner_module::Utils; - let res: Option<(#value_type, self::#inner_module::Linkage<#kty>)> = storage.take(&*key_for(key)); + let res: Option<(#value_type, self::#inner_module::Linkage<#kty>)> = storage.take(&*#as_map::key_for(key)); match res { Some((data, linkage)) => { Self::remove_linkage(linkage, storage); @@ -428,9 +492,9 @@ impl<'a> Impls<'a> { /// Store a value to be associated with the given key from the map. fn insert(key: &#kty, val: &#typ, storage: &S) { - use self::#inner_module::{Utils, key_for}; + use self::#inner_module::Utils; - let key_for = &*key_for(key); + let key_for = &*#as_map::key_for(key); let linkage = match Self::read_with_linkage(storage, key_for) { // overwrite but reuse existing linkage Some((_data, linkage)) => linkage, @@ -442,9 +506,9 @@ impl<'a> Impls<'a> { /// Mutate the value under a key fn mutate R, S: #scrate::GenericStorage>(key: &#kty, f: F, storage: &S) -> R { - use self::#inner_module::{Utils, key_for}; + use self::#inner_module::Utils; - let key_for = &*key_for(key); + let key_for = &*#as_map::key_for(key); let (mut val, linkage) = Self::read_with_linkage(storage, key_for) .map(|(data, linkage)| (data, Some(linkage))) .unwrap_or_else(|| (#fielddefault, None)); @@ -455,7 +519,7 @@ impl<'a> Impls<'a> { } } - impl<#traitinstance: #traittype> #scrate::storage::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance> { + impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable> #scrate::storage::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance, #instance> { fn head(storage: &S) -> Option<#kty> { use self::#inner_module::Utils; @@ -471,10 +535,99 @@ impl<'a> Impls<'a> { #scrate::storage::generator::Box::new(Enumerator { next: Self::read_head(storage), storage, - _data: #phantom_data::<#typ>::default(), + _data: #phantom_data::<(#typ, #traitinstance, #instance)>::default(), }) } } } } + + pub fn double_map(self, k1ty: &syn::Type, k2ty: &syn::Type, k2_hasher: TokenStream2) -> TokenStream2 { + let Self { + scrate, + visibility, + traitinstance, + traittype, + type_infos, + fielddefault, + prefix, + name, + attrs, + instance_opts, + .. + } = self; + + let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; + let option_simple_1 = option_unwrap(is_option); + + let as_double_map = quote!{ > }; + + let mutate_impl = if !is_option { + quote!{ + #as_double_map::insert(key1, key2, &val, storage) + } + } else { + quote!{ + match val { + Some(ref val) => #as_double_map::insert(key1, key2, &val, storage), + None => #as_double_map::remove(key1, key2, storage), + } + } + }; + + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + + let final_prefix = if let Some(instance) = instance { + let const_name = syn::Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#const_name.as_bytes() } + } else { + quote!{ #prefix.as_bytes() } + }; + + // generator for double map + quote!{ + #( #[ #attrs ] )* + #visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>); + + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::unhashed::generator::StorageDoubleMap<#k1ty, #k2ty, #typ> for #name<#traitinstance, #instance> { + type Query = #value_type; + + fn prefix() -> &'static [u8] { + #final_prefix + } + + fn key_for(k1: &#k1ty, k2: &#k2ty) -> Vec { + let mut key = #as_double_map::prefix_for(k1); + key.extend(&#scrate::Hashable::#k2_hasher(k2)); + key + } + + fn get(key1: &#k1ty, key2: &#k2ty, storage: &S) -> Self::Query { + let key = #as_double_map::key_for(key1, key2); + storage.get(&key).#option_simple_1(|| #fielddefault) + } + + fn take(key1: &#k1ty, key2: &#k2ty, storage: &S) -> Self::Query { + let key = #as_double_map::key_for(key1, key2); + storage.take(&key).#option_simple_1(|| #fielddefault) + } + + fn mutate R, S: #scrate::GenericUnhashedStorage>(key1: &#k1ty, key2: &#k2ty, f: F, storage: &S) -> R { + let mut val = #as_double_map::get(key1, key2, storage); + + let ret = f(&mut val); + #mutate_impl ; + ret + } + + } + } + + } } diff --git a/srml/support/procedural/src/storage/mod.rs b/srml/support/procedural/src/storage/mod.rs index 37f2a2f3f10a9112082ddc4259cf054bfab87c10..82290e0de458fb8f658b96199787d5dd86b97b9f 100644 --- a/srml/support/procedural/src/storage/mod.rs +++ b/srml/support/procedural/src/storage/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -39,14 +39,20 @@ struct StorageDefinition { pub module_ident: Ident, pub mod_lt_token: Token![<], pub mod_param: syn::GenericParam, + pub mod_instance_param_token: Option, + pub mod_instance: Option, + pub mod_instantiable_token: Option, + pub mod_instantiable: Option, + pub mod_default_instance_token: Option, + pub mod_default_instance: Option, pub mod_gt_token: Token![>], pub as_token: Token![as], pub crate_ident: Ident, pub content: ext::Braces>, pub extra_genesis: Option, + pub extra_genesis_skip_phantom_data_field: Option, } - #[derive(Parse, ToTokens, Debug)] struct SpecificHiddenCrate { pub keyword: ext::CustomToken, @@ -59,6 +65,12 @@ struct AddExtraGenesis { pub content: ext::Braces, } +#[derive(Parse, ToTokens, Debug)] +struct ExtraGenesisSkipPhantomDataField { + pub genesis_phantom_keyword: ext::CustomToken, + pub token: Token![;], +} + #[derive(Parse, ToTokens, Debug)] struct AddExtraGenesisContent { pub lines: ext::Punctuated, @@ -119,6 +131,7 @@ struct DeclStorageBuild { enum DeclStorageType { Map(DeclStorageMap), LinkedMap(DeclStorageLinkedMap), + DoubleMap(DeclStorageDoubleMap), Simple(syn::Type), } @@ -138,6 +151,24 @@ struct DeclStorageLinkedMap { pub value: syn::Type, } +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageDoubleMap { + pub map_keyword: ext::CustomToken, + pub key1: syn::Type, + pub comma_keyword: Token![,], + pub key2_hasher: DeclStorageDoubleMapHasher, + pub key2: ext::Parens, + pub ass_keyword: Token![=>], + pub value: syn::Type, +} + +#[derive(Parse, ToTokens, Debug)] +enum DeclStorageDoubleMapHasher { + Blake2_256(ext::CustomToken), + Twox256(ext::CustomToken), + Twox128(ext::CustomToken), +} + #[derive(Parse, ToTokens, Debug)] struct DeclStorageDefault { pub equal_token: Token![=], @@ -153,3 +184,8 @@ custom_keyword_impl!(AddExtraGenesis, "add_extra_genesis", "storage extra genesi custom_keyword_impl!(DeclStorageGetter, "get", "storage getter"); custom_keyword!(MapKeyword, "map", "map as keyword"); custom_keyword!(LinkedMapKeyword, "linked_map", "linked_map as keyword"); +custom_keyword!(DoubleMapKeyword, "double_map", "double_map as keyword"); +custom_keyword!(Blake2_256Keyword, "blake2_256", "Blake2_256 as keyword"); +custom_keyword!(Twox256Keyword, "twox_256", "Twox_256 as keyword"); +custom_keyword!(Twox128Keyword, "twox_128", "Twox_128 as keyword"); +custom_keyword_impl!(ExtraGenesisSkipPhantomDataField, "extra_genesis_skip_phantom_data_field", "extra_genesis_skip_phantom_data_field as keyword"); diff --git a/srml/support/procedural/src/storage/transformation.rs b/srml/support/procedural/src/storage/transformation.rs index 017a217f1c3426519933dd23df1268d4b67ab130..f00b5e8309bcc043b372296bc34e8d39b66e2ea7 100644 --- a/srml/support/procedural/src/storage/transformation.rs +++ b/srml/support/procedural/src/storage/transformation.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -38,6 +38,8 @@ use quote::quote; use super::*; +const NUMBER_OF_INSTANCE: usize = 16; + // try macro but returning tokenized error macro_rules! try_tok(( $expre : expr ) => { match $expre { @@ -57,11 +59,21 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream { ident: storetype, module_ident, mod_param: strait, + mod_instance, + mod_instantiable, + mod_default_instance, crate_ident: cratename, content: ext::Braces { content: storage_lines, ..}, extra_genesis, + extra_genesis_skip_phantom_data_field, .. } = def; + + let instance_opts = match get_instance_opts(mod_instance, mod_instantiable, mod_default_instance) { + Ok(opts) => opts, + Err(err) => return err.to_compile_error().into(), + }; + let hidden_crate_name = hidden_crate.map(|rc| rc.ident.content).map(|i| i.to_string()) .unwrap_or_else(|| "decl_storage".to_string()); let scrate = generate_crate_access(&hidden_crate_name, "srml-support"); @@ -89,13 +101,16 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream { &scrate, &traitinstance, &traittype, + &instance_opts, &storage_lines, &extra_genesis, + extra_genesis_skip_phantom_data_field.is_some(), )); let decl_storage_items = decl_storage_items( &scrate, &traitinstance, &traittype, + &instance_opts, &cratename, &storage_lines, ); @@ -104,19 +119,29 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream { ); let impl_store_items = impl_store_items( &traitinstance, + &instance_opts.instance, &storage_lines, ); let impl_store_fns = impl_store_fns( &scrate, &traitinstance, + &instance_opts.instance, &storage_lines, ); let (store_default_struct, store_functions_to_metadata) = store_functions_to_metadata( &scrate, &traitinstance, &traittype, + &instance_opts, &storage_lines, ); + + let InstanceOpts { + instance, + bound_instantiable, + .. + } = instance_opts; + let cratename_string = cratename.to_string(); let expanded = quote! { #scrate_decl @@ -125,23 +150,25 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream { #decl_store_items } #store_default_struct - impl<#traitinstance: #traittype> #storetype for #module_ident<#traitinstance> { + impl<#traitinstance: #traittype, #instance #bound_instantiable> #storetype for #module_ident<#traitinstance, #instance> { #impl_store_items } - impl<#traitinstance: 'static + #traittype> #module_ident<#traitinstance> { + impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable> #module_ident<#traitinstance, #instance> { #impl_store_fns + #[doc(hidden)] pub fn store_metadata() -> #scrate::storage::generator::StorageMetadata { #scrate::storage::generator::StorageMetadata { functions: #scrate::storage::generator::DecodeDifferent::Encode(#store_functions_to_metadata) , } } + #[doc(hidden)] pub fn store_metadata_functions() -> &'static [#scrate::storage::generator::StorageFunctionMetadata] { #store_functions_to_metadata } + #[doc(hidden)] pub fn store_metadata_name() -> &'static str { #cratename_string } - } #extra_genesis @@ -155,10 +182,20 @@ fn decl_store_extra_genesis( scrate: &TokenStream2, traitinstance: &Ident, traittype: &syn::TypeParamBound, + instance_opts: &InstanceOpts, storage_lines: &ext::Punctuated, extra_genesis: &Option, + extra_genesis_skip_phantom_data_field: bool, ) -> Result { + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + let mut is_trait_needed = false; let mut has_trait_field = false; let mut serde_complete_bound = std::collections::HashSet::new(); @@ -168,6 +205,7 @@ fn decl_store_extra_genesis( for sline in storage_lines.inner.iter() { let DeclStorageLine { + attrs, name, getter, config, @@ -188,7 +226,13 @@ fn decl_store_extra_genesis( let ident = &getter.getfn.content; quote!( #ident ) } else { - return Err(syn::Error::new_spanned(name, format!("Invalid storage definiton, couldn't find config identifier: storage must either have a get identifier `get(ident)` or a defined config identifier `config(ident)`"))); + return Err( + Error::new_spanned( + name, + "Invalid storage definiton, couldn't find config identifier: storage must either have a get identifier \ + `get(ident)` or a defined config identifier `config(ident)`" + ) + ); }; if type_infos.kind.is_simple() && ext::has_parametric_type(type_infos.value_type, traitinstance) { is_trait_needed = true; @@ -199,17 +243,24 @@ fn decl_store_extra_genesis( if let DeclStorageTypeInfosKind::Map { key_type, .. } = type_infos.kind { serde_complete_bound.insert(key_type); } + + // Propagate doc attributes. + let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); + let storage_type = type_infos.typ.clone(); config_field.extend(match type_infos.kind { DeclStorageTypeInfosKind::Simple => { - quote!( pub #ident: #storage_type, ) + quote!( #( #[ #attrs ] )* pub #ident: #storage_type, ) }, DeclStorageTypeInfosKind::Map {key_type, .. } => { - quote!( pub #ident: Vec<(#key_type, #storage_type)>, ) + quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key_type, #storage_type)>, ) + }, + DeclStorageTypeInfosKind::DoubleMap {key1_type, key2_type, .. } => { + quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key1_type, #key2_type, #storage_type)>, ) }, }); opt_build = Some(build.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b )) - .unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance>| config.#ident.clone()) ))); + .unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance, #instance>| config.#ident.clone()) ))); let fielddefault = default_value.inner.as_ref().map(|d| &d.expr).map(|d| if type_infos.is_option { @@ -232,9 +283,8 @@ fn decl_store_extra_genesis( use #scrate::rstd::{cell::RefCell, marker::PhantomData}; use #scrate::codec::{Encode, Decode}; - let storage = (RefCell::new(&mut r), PhantomData::::default()); let v = (#builder)(&self); - <#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>>::put(&v, &storage); + <#name<#traitinstance, #instance> as #scrate::storage::generator::StorageValue<#typ>>::put(&v, &storage); }} }, DeclStorageTypeInfosKind::Map { key_type, .. } => { @@ -242,10 +292,20 @@ fn decl_store_extra_genesis( use #scrate::rstd::{cell::RefCell, marker::PhantomData}; use #scrate::codec::{Encode, Decode}; - let storage = (RefCell::new(&mut r), PhantomData::::default()); let data = (#builder)(&self); for (k, v) in data.into_iter() { - <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#key_type, #typ>>::insert(&k, &v, &storage); + <#name<#traitinstance, #instance> as #scrate::storage::generator::StorageMap<#key_type, #typ>>::insert(&k, &v, &storage); + } + }} + }, + DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => { + quote!{{ + use #scrate::rstd::{cell::RefCell, marker::PhantomData}; + use #scrate::codec::{Encode, Decode}; + + let data = (#builder)(&self); + for (k1, k2, v) in data.into_iter() { + <#name<#traitinstance, #instance> as #scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>>::insert(&k1, &k2, &v, &storage); } }} }, @@ -323,24 +383,26 @@ fn decl_store_extra_genesis( || !genesis_extrafields.is_empty() || !builders.is_empty(); Ok(if is_extra_genesis_needed { - let (fparam, sparam, ph_field, ph_default) = if is_trait_needed { - if has_trait_field { + let (fparam_struct, fparam_impl, sparam, ph_field, ph_default) = if is_trait_needed { + if (has_trait_field && instance.is_none()) || extra_genesis_skip_phantom_data_field { // no phantom data required ( - quote!(<#traitinstance: #traittype>), - quote!(<#traitinstance>), + quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>), + quote!(<#traitinstance: #traittype, #instance #bound_instantiable>), + quote!(<#traitinstance, #instance>), quote!(), quote!(), ) } else { // need phantom data ( - quote!(<#traitinstance: #traittype>), - quote!(<#traitinstance>), + quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>), + quote!(<#traitinstance: #traittype, #instance #bound_instantiable>), + quote!(<#traitinstance, #instance>), quote!{ #[serde(skip)] - pub _genesis_phantom_data: #scrate::storage::generator::PhantomData<#traitinstance>, + pub _genesis_phantom_data: #scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>, }, quote!{ _genesis_phantom_data: Default::default(), @@ -349,7 +411,7 @@ fn decl_store_extra_genesis( } } else { // do not even need type parameter - (quote!(), quote!(), quote!(), quote!()) + (quote!(), quote!(), quote!(), quote!(), quote!()) }; quote!{ @@ -358,14 +420,14 @@ fn decl_store_extra_genesis( #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] #serde_bug_bound - pub struct GenesisConfig#fparam { + pub struct GenesisConfig#fparam_struct { #ph_field #config_field #genesis_extrafields } #[cfg(feature = "std")] - impl#fparam Default for GenesisConfig#sparam { + impl#fparam_impl Default for GenesisConfig#sparam { fn default() -> Self { GenesisConfig { #ph_default @@ -376,17 +438,18 @@ fn decl_store_extra_genesis( } #[cfg(feature = "std")] - impl#fparam #scrate::runtime_primitives::BuildStorage for GenesisConfig#sparam { - - fn build_storage(self) -> ::std::result::Result<(#scrate::runtime_primitives::StorageOverlay, #scrate::runtime_primitives::ChildrenStorageOverlay), String> { - let mut r: #scrate::runtime_primitives::StorageOverlay = Default::default(); - let mut c: #scrate::runtime_primitives::ChildrenStorageOverlay = Default::default(); + impl#fparam_impl #scrate::runtime_primitives::BuildStorage for GenesisConfig#sparam { + fn assimilate_storage(self, r: &mut #scrate::runtime_primitives::StorageOverlay, c: &mut #scrate::runtime_primitives::ChildrenStorageOverlay) -> ::std::result::Result<(), String> { + use #scrate::rstd::{cell::RefCell, marker::PhantomData}; + let storage = (RefCell::new(r), PhantomData::::default()); #builders - #scall(&mut r, &mut c, &self); + let r = storage.0.into_inner(); + + #scall(r, c, &self); - Ok((r, c)) + Ok(()) } } } @@ -399,13 +462,102 @@ fn decl_storage_items( scrate: &TokenStream2, traitinstance: &Ident, traittype: &syn::TypeParamBound, + instance_opts: &InstanceOpts, cratename: &Ident, storage_lines: &ext::Punctuated, ) -> TokenStream2 { let mut impls = TokenStream2::new(); + + let InstanceOpts { + instance, + default_instance, + instantiable, + .. + } = instance_opts; + + let build_prefix = |cratename, name| format!("{} {}", cratename, name); + + // Build Instantiable trait + if instance.is_some() { + let mut const_names = vec![]; + + for sline in storage_lines.inner.iter() { + let DeclStorageLine { + storage_type, + name, + .. + } = sline; + + let prefix = build_prefix(cratename, name); + + let type_infos = get_type_infos(storage_type); + + let const_name = syn::Ident::new(&format!("{}{}", impls::PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); + let partial_const_value = prefix.clone(); + const_names.push((const_name, partial_const_value)); + + if let DeclStorageTypeInfosKind::Map { is_linked: true, .. } = type_infos.kind { + let const_name = syn::Ident::new(&format!("{}{}", impls::HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site()); + let partial_const_value = format!("head of {}", prefix); + const_names.push((const_name, partial_const_value)); + } + } + + // Declare Instance trait + { + let mut const_impls = TokenStream2::new(); + for (const_name, _) in &const_names { + const_impls.extend(quote! { + const #const_name: &'static str; + }); + } + + impls.extend(quote! { + /// Tag a type as an instance of a module. + /// + /// Defines storage prefixes, they must be unique. + pub trait #instantiable: 'static { + #const_impls + } + }); + } + + let instances = (0..NUMBER_OF_INSTANCE) + .map(|i| { + let name = format!("Instance{}", i); + let ident = syn::Ident::new(&name, proc_macro2::Span::call_site()); + (name, ident, quote! {#[doc=r"Module instance"]}) + }) + .chain(default_instance.clone().map(|ident| (String::new(), ident, quote! {#[doc=r"Default module instance"]}))); + + // Impl Instance trait for instances + for (prefix, ident, doc) in instances { + let mut const_impls = TokenStream2::new(); + + for (const_name, partial_const_value) in &const_names { + let const_value = format!("{}{}", partial_const_value, prefix); + const_impls.extend(quote! { + const #const_name: &'static str = #const_value; + }); + } + + impls.extend(quote! { + // Those trait are derived because of wrong bounds for generics + #[cfg_attr(feature = "std", derive(Debug))] + #[derive(Clone, Eq, PartialEq, #scrate::codec::Encode, #scrate::codec::Decode)] + #doc + pub struct #ident; + impl #instantiable for #ident { + #const_impls + } + }); + } + } + for sline in storage_lines.inner.iter() { let DeclStorageLine { + attrs, name, storage_type, default_value, @@ -415,16 +567,22 @@ fn decl_storage_items( let type_infos = get_type_infos(storage_type); let kind = type_infos.kind.clone(); + // Propagate doc attributes. + let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); + let i = impls::Impls { scrate, visibility, + cratename, traitinstance, traittype, + instance_opts, type_infos, fielddefault: default_value.inner.as_ref().map(|d| &d.expr).map(|d| quote!( #d )) .unwrap_or_else(|| quote!{ Default::default() }), - prefix: format!("{} {}", cratename, name), + prefix: build_prefix(cratename, name), name, + attrs, }; let implementation = match kind { @@ -437,6 +595,9 @@ fn decl_storage_items( DeclStorageTypeInfosKind::Map { key_type, is_linked: true } => { i.linked_map(key_type) }, + DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, key2_hasher } => { + i.double_map(key1_type, key2_type, key2_hasher) + }, }; impls.extend(implementation) } @@ -456,23 +617,30 @@ fn decl_store_items( fn impl_store_items( traitinstance: &Ident, + instance: &Option, storage_lines: &ext::Punctuated, ) -> TokenStream2 { storage_lines.inner.iter().map(|sline| &sline.name) .fold(TokenStream2::new(), |mut items, name| { - items.extend(quote!(type #name = #name<#traitinstance>;)); - items + items.extend( + quote!( + type #name = #name<#traitinstance, #instance>; + ) + ); + items }) } fn impl_store_fns( scrate: &TokenStream2, traitinstance: &Ident, + instance: &Option, storage_lines: &ext::Punctuated, ) -> TokenStream2 { let mut items = TokenStream2::new(); for sline in storage_lines.inner.iter() { let DeclStorageLine { + attrs, name, getter, storage_type, @@ -485,19 +653,35 @@ fn impl_store_fns( let type_infos = get_type_infos(storage_type); let value_type = type_infos.value_type; + // Propagate doc attributes. + let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); + let typ = type_infos.typ; let item = match type_infos.kind { DeclStorageTypeInfosKind::Simple => { quote!{ + #( #[ #attrs ] )* pub fn #get_fn() -> #value_type { - <#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage) + <#name<#traitinstance, #instance> as #scrate::storage::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage) } } }, DeclStorageTypeInfosKind::Map { key_type, .. } => { quote!{ + #( #[ #attrs ] )* pub fn #get_fn>(key: K) -> #value_type { - <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#key_type, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage) + <#name<#traitinstance, #instance> as #scrate::storage::generator::StorageMap<#key_type, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage) + } + } + } + DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => { + quote!{ + pub fn #get_fn(k1: KArg1, k2: KArg2) -> #value_type + where + KArg1: #scrate::storage::generator::Borrow<#key1_type>, + KArg2: #scrate::storage::generator::Borrow<#key2_type>, + { + <#name<#traitinstance> as #scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ>> :: get(k1.borrow(), k2.borrow(), &#scrate::storage::RuntimeStorage) } } } @@ -512,9 +696,18 @@ fn store_functions_to_metadata ( scrate: &TokenStream2, traitinstance: &Ident, traittype: &syn::TypeParamBound, + instance_opts: &InstanceOpts, storage_lines: &ext::Punctuated, ) -> (TokenStream2, TokenStream2) { + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + let mut items = TokenStream2::new(); let mut default_getter_struct_def = TokenStream2::new(); for sline in storage_lines.inner.iter() { @@ -539,12 +732,26 @@ fn store_functions_to_metadata ( ) } }, - DeclStorageTypeInfosKind::Map { key_type, .. } => { + DeclStorageTypeInfosKind::Map { key_type, is_linked } => { let kty = clean_type_string("e!(#key_type).to_string()); quote!{ #scrate::storage::generator::StorageFunctionType::Map { key: #scrate::storage::generator::DecodeDifferent::Encode(#kty), value: #scrate::storage::generator::DecodeDifferent::Encode(#styp), + is_linked: #is_linked, + } + } + }, + DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, key2_hasher } => { + let k1ty = clean_type_string("e!(#key1_type).to_string()); + let k2ty = clean_type_string("e!(#key2_type).to_string()); + let k2_hasher = clean_type_string(&key2_hasher.to_string()); + quote!{ + #scrate::storage::generator::StorageFunctionType::DoubleMap { + key1: #scrate::storage::generator::DecodeDifferent::Encode(#k1ty), + key2: #scrate::storage::generator::DecodeDifferent::Encode(#k2ty), + value: #scrate::storage::generator::DecodeDifferent::Encode(#styp), + key2_hasher: #scrate::storage::generator::DecodeDifferent::Encode(#k2_hasher), } } }, @@ -564,7 +771,7 @@ fn store_functions_to_metadata ( }) .unwrap_or_else(|| quote!( Default::default() )); let mut docs = TokenStream2::new(); - for attr in attrs.inner.iter().filter_map(|v| v.interpret_meta()) { + for attr in attrs.inner.iter().filter_map(|v| v.parse_meta().ok()) { if let syn::Meta::NameValue(syn::MetaNameValue{ ref ident, ref lit, @@ -585,7 +792,7 @@ fn store_functions_to_metadata ( ty: #stype, default: #scrate::storage::generator::DecodeDifferent::Encode( #scrate::storage::generator::DefaultByteGetter( - &#struct_name::<#traitinstance>(#scrate::rstd::marker::PhantomData) + &#struct_name::<#traitinstance, #instance>(#scrate::rstd::marker::PhantomData) ) ), documentation: #scrate::storage::generator::DecodeDifferent::Encode(&[ #docs ]), @@ -593,12 +800,13 @@ fn store_functions_to_metadata ( }; items.extend(item); let def_get = quote! { - pub struct #struct_name<#traitinstance>(pub #scrate::rstd::marker::PhantomData<#traitinstance>); + #[doc(hidden)] + pub struct #struct_name<#traitinstance, #instance #bound_instantiable #equal_default_instance>(pub #scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>); #[cfg(feature = "std")] #[allow(non_upper_case_globals)] static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::rstd::vec::Vec> = #scrate::once_cell::sync::OnceCell::INIT; #[cfg(feature = "std")] - impl<#traitinstance: #traittype> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance> { + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance, #instance> { fn default_byte(&self) -> #scrate::rstd::vec::Vec { use #scrate::codec::Encode; #cache_name.get_or_init(|| { @@ -608,7 +816,7 @@ fn store_functions_to_metadata ( } } #[cfg(not(feature = "std"))] - impl<#traitinstance: #traittype> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance> { + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance, #instance> { fn default_byte(&self) -> #scrate::rstd::vec::Vec { use #scrate::codec::Encode; let def_val: #value_type = #default; @@ -643,6 +851,11 @@ enum DeclStorageTypeInfosKind<'a> { key_type: &'a syn::Type, is_linked: bool, }, + DoubleMap { + key1_type: &'a syn::Type, + key2_type: &'a syn::Type, + key2_hasher: TokenStream2, + } } impl<'a> DeclStorageTypeInfosKind<'a> { @@ -665,6 +878,11 @@ fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos { key_type: &map.key, is_linked: true, }), + DeclStorageType::DoubleMap(ref map) => (&map.value, DeclStorageTypeInfosKind::DoubleMap { + key1_type: &map.key1, + key2_type: &map.key2.content, + key2_hasher: { let h = &map.key2_hasher; quote! { #h } }, + }), }; let extracted_type = ext::extract_type_option(value_type); @@ -679,3 +897,44 @@ fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos { } } + +#[derive(Default)] +pub(crate) struct InstanceOpts { + pub instance: Option, + pub default_instance: Option, + pub instantiable: Option, + pub comma_instance: TokenStream2, + pub equal_default_instance: TokenStream2, + pub bound_instantiable: TokenStream2, +} + +fn get_instance_opts( + instance: Option, + instantiable: Option, + default_instance: Option, +) -> syn::Result { + + let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance"; + + match (instance, instantiable, default_instance) { + (Some(instance), Some(instantiable), default_instance_def) => { + let (equal_default_instance, default_instance) = if let Some(default_instance) = default_instance_def { + (quote!{= #default_instance}, Some(default_instance)) + } else { + (quote!{}, None) + }; + Ok(InstanceOpts { + comma_instance: quote!{, #instance}, + equal_default_instance, + bound_instantiable: quote!{: #instantiable}, + instance: Some(instance), + default_instance, + instantiable: Some(instantiable), + }) + }, + (None, None, None) => Ok(Default::default()), + (Some(instance), None, _) => Err(syn::Error::new(instance.span(), format!("Expect instantiable trait bound for instance: {}. {}", instance, right_syntax))), + (None, Some(instantiable), _) => Err(syn::Error::new(instantiable.span(), format!("Expect instance generic for bound instantiable: {}. {}", instantiable, right_syntax))), + (None, _, Some(default_instance)) => Err(syn::Error::new(default_instance.span(), format!("Expect instance generic for default instance: {}. {}", default_instance, right_syntax))), + } +} diff --git a/srml/support/procedural/tools/derive/src/lib.rs b/srml/support/procedural/tools/derive/src/lib.rs index fdaee5dceed40e7bfda233da6b10d975e8161461..0e3fcb22475fc2e9babeeb3a3c7268c4a16ab018 100644 --- a/srml/support/procedural/tools/derive/src/lib.rs +++ b/srml/support/procedural/tools/derive/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/support/procedural/tools/src/lib.rs b/srml/support/procedural/tools/src/lib.rs index 8d0e1ae600905fe53b28f315416727d31039f077..34b96df8104b50e33656a3636cb55530d9f84963 100644 --- a/srml/support/procedural/tools/src/lib.rs +++ b/srml/support/procedural/tools/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -66,7 +66,7 @@ pub fn generate_crate_access(unique_id: &str, def_crate: &str) -> TokenStream { } else { let mod_name = generate_hidden_includes_mod_name(unique_id); quote::quote!( self::#mod_name::hidden_include ) - }.into() + } } /// Generates the hidden includes that are required to make the macro independent from its scope. @@ -92,7 +92,7 @@ pub fn generate_hidden_includes(unique_id: &str, def_crate: &str) -> TokenStream } } - }.into() + } } // fn to remove white spaces arount string types diff --git a/srml/support/procedural/tools/src/syn_ext.rs b/srml/support/procedural/tools/src/syn_ext.rs index 74233b2d0ba64253988d97f64b7d7f13dd48f5e7..c2136b2cd8f96599d09f8ce4ff34d5c6a2349142 100644 --- a/srml/support/procedural/tools/src/syn_ext.rs +++ b/srml/support/procedural/tools/src/syn_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 8e5cc44092b35232fdaffab71aa2e9d74bc23f6e..64ea5938c48c0fc60cbd32295cfb600d83f51917 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -27,7 +27,10 @@ pub use srml_metadata::{ FunctionArgumentMetadata, OuterDispatchMetadata, OuterDispatchCall }; -/// Result of a module function call; either nothing (functions are only called for "side efeects") +/// A type that can not be instantiated. +pub enum Never {} + +/// Result of a module function call; either nothing (functions are only called for "side effects") /// or an error message. pub type Result = result::Result<(), &'static str>; @@ -86,44 +89,54 @@ impl Parameter for T where T: Codec + Clone + Eq {} /// corresponding to a function of the module. This enum implements Callable and thus its values /// can be used as an extrinsic's payload. /// -/// The `on_initialise` and `on_finalise` functions are special, since it can either take no +/// The `on_initialize` and `on_finalize` functions are special, since it can either take no /// parameters, or one parameter, which has the runtime's block number type. +/// +/// ### Module with instances +/// +/// decl_module! support modules with instances with the following syntax: (DefaultInstance type is +/// optionnal) +/// ```nocompile +/// pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {} +/// ``` #[macro_export] macro_rules! decl_module { // Macro transformations (to convert invocations with incomplete parameters to the canonical // form) ( $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty { $($t:tt)* } ) => { - decl_module!(@normalize + $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = system {} {} {} + {} [] $($t)* ); }; ( $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $($t:tt)* } ) => { - decl_module!(@normalize + $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system {} {} {} + {} [] $($t)* ); @@ -131,85 +144,117 @@ macro_rules! decl_module { (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {} - { $( $on_initialise:tt )* } - { $( $on_finalise:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* - $vis:vis fn deposit_event $(<$dpeg:ident>)* () = default; + $vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* () = default; $($rest:tt)* ) => { - decl_module!(@normalize + $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system - { $vis fn deposit_event $(<$dpeg>)* () = default; } - { $( $on_initialise )* } - { $( $on_finalise )* } + { $vis fn deposit_event $(<$dpeg $(, $dpeg_instance)?>)* () = default; } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } [ $($t)* ] $($rest)* ); }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {} - { $( $on_initialise:tt )* } - { $( $on_finalise:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* - $vis:vis fn deposit_event $(<$dpeg:ident>)* ( + $vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* ( $($param_name:ident : $param:ty),* ) { $( $impl:tt )* } $($rest:tt)* ) => { - decl_module!(@normalize + $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system - { $vis fn deposit_event $(<$dpeg>)* ($( $param_name: $param ),* ) { $( $impl )* } } - { $( $on_initialise )* } - { $( $on_finalise )* } + { $vis fn deposit_event $(<$dpeg $(, $dpeg_instance)?>)* ($( $param_name: $param ),* ) { $( $impl )* } } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } [ $($t)* ] $($rest)* ); }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } - { $( $on_initialise:tt )* } + { $( $on_initialize:tt )* } {} + { $( $offchain:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* - fn on_finalise($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + fn on_finalize($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } $($rest:tt)* ) => { - decl_module!(@normalize + $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } - { $( $on_initialise )* } - { fn on_finalise( $( $param_name : $param ),* ) { $( $impl )* } } + { $( $on_initialize )* } + { fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } } + { $( $offchain )* } [ $($t)* ] $($rest)* ); }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } {} - { $( $on_finalise:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + [ $($t:tt)* ] + $(#[doc = $doc_attr:tt])* + fn on_initialize($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> + for enum $call_type where origin: $origin_type, system = $system + { $( $deposit_event )* } + { fn on_initialize( $( $param_name : $param ),* ) { $( $impl )* } } + { $( $on_finalize )* } + { $( $offchain )* } + [ $($t)* ] + $($rest)* + ); + }; + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $deposit_event:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* - fn on_initialise($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + fn offchain_worker($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } $($rest:tt)* ) => { decl_module!(@normalize @@ -217,19 +262,21 @@ macro_rules! decl_module { pub struct $mod_type<$trait_instance: $trait_name> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } - { fn on_initialise( $( $param_name : $param ),* ) { $( $impl )* } } - { $( $on_finalise )* } + { $( $on_initialize )* } + { $( $on_finalize )* } + { fn offchain_worker( $( $param_name : $param ),* ) { $( $impl )* } } [ $($t)* ] $($rest)* ); }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } - { $( $on_initialise:tt )* } - { $( $on_finalise:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( @@ -237,30 +284,33 @@ macro_rules! decl_module { ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { - decl_module!(@normalize + $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, $instance: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } - { $( $on_initialise )* } - { $( $on_finalise )* } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } [ $($t)* $(#[doc = $doc_attr])* $fn_vis fn $fn_name( $origin $( , $(#[$codec_attr])* $param_name : $param )* ) $( -> $result )* { $( $impl )* } + { $($instance: $instantiable)? } ] $($rest)* ); }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } - { $( $on_initialise:tt )* } - { $( $on_finalise:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( @@ -276,11 +326,12 @@ macro_rules! decl_module { }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } - { $( $on_initialise:tt )* } - { $( $on_finalise:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( @@ -296,11 +347,12 @@ macro_rules! decl_module { }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } - { $( $on_initialise:tt )* } - { $( $on_finalise:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( @@ -308,41 +360,45 @@ macro_rules! decl_module { ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { - decl_module!(@normalize + $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, $instance: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } - { $( $on_initialise )* } - { $( $on_finalise )* } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } [ $($t)* $(#[doc = $doc_attr])* $fn_vis fn $fn_name( root $( , $(#[$codec_attr])* $param_name : $param )* ) $( -> $result )* { $( $impl )* } + { $($instance: $instantiable)? } ] $($rest)* ); }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } - { $( $on_initialise:tt )* } - { $( $on_finalise:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } [ $($t:tt)* ] ) => { - decl_module!(@imp + $crate::decl_module!(@imp $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $($t)* } { $( $deposit_event )* } - { $( $on_initialise )* } - { $( $on_finalise )* } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } ); }; @@ -351,194 +407,211 @@ macro_rules! decl_module { (@call root - $mod_type:ident $trait_instance:ident $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ] + $mod_type:ident<$trait_instance:ident $(, $instance:ident)?> $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ] ) => { { $system::ensure_root($origin)?; - <$mod_type<$trait_instance>>::$fn_name( $( $param_name ),* ) + <$mod_type<$trait_instance $(, $instance)?>>::$fn_name( $( $param_name ),* ) } }; (@call $ingore:ident - $mod_type:ident $trait_instance:ident $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ] + $mod_type:ident<$trait_instance:ident $(, $instance:ident)?> $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ] ) => { - <$mod_type<$trait_instance>>::$fn_name( $origin $(, $param_name )* ) + <$mod_type<$trait_instance $(, $instance)?>>::$fn_name( $origin $(, $param_name )* ) }; // no `deposit_event` function wanted (@impl_deposit_event - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path)?>; $system:ident; ) => {}; - // Non-generic event - (@impl_deposit_event - $module:ident<$trait_instance:ident: $trait_name:ident>; - $system:ident; - $vis:vis fn deposit_event() = default; - ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn deposit_event(event: Event) { - <$system::Module<$trait_instance>>::deposit_event( - <$trait_instance as $trait_name>::Event::from(event).into() - ); - } - } - }; - - // Generic event (@impl_deposit_event - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $system:ident; - $vis:vis fn deposit_event<$ignore:ident>() = default; + $vis:vis fn deposit_event$(<$event_trait_instance:ident $(, $event_instance:ident)?>)?() = default; ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn deposit_event(event: Event<$trait_instance>) { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> { + $vis fn deposit_event(event: Event$(<$event_trait_instance $(, $event_instance)?>)?) { <$system::Module<$trait_instance>>::deposit_event( - <$trait_instance as $trait_name>::Event::from(event).into() + <$trait_instance as $trait_name$(<$instance>)?>::Event::from(event).into() ); } } }; (@impl_deposit_event - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $system:ident; $vis:vis fn deposit_event($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> { $vis fn deposit_event($param: $param_ty) { $( $impl )* } } }; - (@impl_on_initialise - $module:ident<$trait_instance:ident: $trait_name:ident>; - fn on_initialise() { $( $impl:tt )* } + (@impl_on_initialize + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + fn on_initialize() { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> - $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> - for $module<$trait_instance> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnInitialize<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> { - fn on_initialise(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } + fn on_initialize(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } } }; - (@impl_on_initialise - $module:ident<$trait_instance:ident: $trait_name:ident>; - fn on_initialise($param:ident : $param_ty:ty) { $( $impl:tt )* } + (@impl_on_initialize + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + fn on_initialize($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> - $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> - for $module<$trait_instance> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnInitialize<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> { - fn on_initialise($param: $param_ty) { $( $impl )* } + fn on_initialize($param: $param_ty) { $( $impl )* } } }; - (@impl_on_initialise - $module:ident<$trait_instance:ident: $trait_name:ident>; + (@impl_on_initialize + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; ) => { - impl<$trait_instance: $trait_name> - $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> - for $module<$trait_instance> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnInitialize<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> {} }; - (@impl_on_finalise - $module:ident<$trait_instance:ident: $trait_name:ident>; - fn on_finalise() { $( $impl:tt )* } + (@impl_on_finalize + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + fn on_finalize() { $( $impl:tt )* } + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnFinalize<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> + { + fn on_finalize(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } + } + }; + + (@impl_on_finalize + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + fn on_finalize($param:ident : $param_ty:ty) { $( $impl:tt )* } + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnFinalize<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> + { + fn on_finalize($param: $param_ty) { $( $impl )* } + } + }; + + (@impl_on_finalize + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; ) => { - impl<$trait_instance: $trait_name> - $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnFinalize<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> { - fn on_finalise(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } } }; - (@impl_on_finalise - $module:ident<$trait_instance:ident: $trait_name:ident>; - fn on_finalise($param:ident : $param_ty:ty) { $( $impl:tt )* } + (@impl_offchain + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + fn offchain_worker() { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> - $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OffchainWorker<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> { - fn on_finalise($param: $param_ty) { $( $impl )* } + fn generate_extrinsics(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } } }; - (@impl_on_finalise - $module:ident<$trait_instance:ident: $trait_name:ident>; + (@impl_offchain + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + fn offchain_worker($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> - $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OffchainWorker<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> { + fn generate_extrinsics($param: $param_ty) { $( $impl )* } } }; + (@impl_offchain + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OffchainWorker<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> + {} + }; + (@impl_function - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; root; + $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( root $(, $param:ident : $param_ty:ty )* ) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::Result { - { $( $impl )* } - Ok(()) - } + $(#[doc = $doc_attr])* + $vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::Result { + { $( $impl )* } + Ok(()) } }; (@impl_function - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; root; + $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( root $(, $param:ident : $param_ty:ty )* ) -> $result:ty { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn $name($( $param: $param_ty ),* ) -> $result { - $( $impl )* - } + $(#[doc = $doc_attr])* + $vis fn $name($( $param: $param_ty ),* ) -> $result { + $( $impl )* } }; (@impl_function - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; $ignore:ident; + $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( $origin:ident $(, $param:ident : $param_ty:ty )* ) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn $name( - $origin: $origin_ty $(, $param: $param_ty )* - ) -> $crate::dispatch::Result { - { $( $impl )* } - Ok(()) - } + $(#[doc = $doc_attr])* + $vis fn $name( + $origin: $origin_ty $(, $param: $param_ty )* + ) -> $crate::dispatch::Result { + { $( $impl )* } + Ok(()) } }; (@impl_function - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; $ignore:ident; + $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( $origin:ident $(, $param:ident : $param_ty:ty )* ) -> $result:ty { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn $name($origin: $origin_ty $(, $param: $param_ty )* ) -> $result { - $( $impl )* - } + $(#[doc = $doc_attr])* + $vis fn $name($origin: $origin_ty $(, $param: $param_ty )* ) -> $result { + $( $impl )* } }; @@ -546,18 +619,20 @@ macro_rules! decl_module { (@imp $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( $from:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* ) $( -> $result:ty )* { $( $impl:tt )* } + { $($fn_instance:ident: $fn_instantiable:path)? } )* } { $( $deposit_event:tt )* } - { $( $on_initialise:tt )* } - { $( $on_finalise:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Copy, PartialEq, Eq)] @@ -566,71 +641,85 @@ macro_rules! decl_module { // serde-derive for when we attempt to derive `Deserialize` on these types, // in a situation where we've imported `srml_support` as another name. #[cfg(feature = "std")] - pub struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>); + pub struct $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable $( = $module_default_instance)?)?>(::std::marker::PhantomData<($trait_instance $(, $instance)?)>); // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] #[cfg(not(feature = "std"))] - pub struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>); + pub struct $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable $( = $module_default_instance)?)?>(::core::marker::PhantomData<($trait_instance $(, $instance)?)>); + + $crate::decl_module! { + @impl_on_initialize + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; + $( $on_initialize )* + } - decl_module! { - @impl_on_initialise - $mod_type<$trait_instance: $trait_name>; - $( $on_initialise )* + $crate::decl_module! { + @impl_on_finalize + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; + $( $on_finalize )* } - decl_module! { - @impl_on_finalise - $mod_type<$trait_instance: $trait_name>; - $( $on_finalise )* + $crate::decl_module! { + @impl_offchain + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; + $( $offchain )* } - decl_module! { + $crate::decl_module! { @impl_deposit_event - $mod_type<$trait_instance: $trait_name>; + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; $system; $( $deposit_event )* } - $( - decl_module! { - @impl_function - $mod_type<$trait_instance: $trait_name>; - $origin_type; - $from; - $fn_vis fn $fn_name ( - $from $(, $param_name : $param )* - ) $( -> $result )* { $( $impl )* } - } - )* + /// Can also be called using [`Call`]. + /// + /// [`Call`]: enum.Call.html + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { + $( + $crate::decl_module! { + @impl_function + $mod_type<$trait_instance: $trait_name $(, $fn_instance: $fn_instantiable)?>; + $origin_type; + $from; + $(#[doc = $doc_attr])* + $fn_vis fn $fn_name ( + $from $(, $param_name : $param )* + ) $( -> $result )* { $( $impl )* } + } + )* + } #[cfg(feature = "std")] $(#[$attr])* - pub enum $call_type<$trait_instance: $trait_name> { - __PhantomItem(::std::marker::PhantomData<$trait_instance>), - __OtherPhantomItem(::std::marker::PhantomData<$trait_instance>), + pub enum $call_type<$trait_instance: $trait_name$(, $instance: $instantiable $( = $module_default_instance)?)?> { + #[doc(hidden)] + __PhantomItem(::std::marker::PhantomData<($trait_instance $(, $instance)?)>, $crate::dispatch::Never), $( #[allow(non_camel_case_types)] + $(#[doc = $doc_attr])* $fn_name ( $( $param ),* ), )* } #[cfg(not(feature = "std"))] $(#[$attr])* - pub enum $call_type<$trait_instance: $trait_name> { - __PhantomItem(::core::marker::PhantomData<$trait_instance>), - __OtherPhantomItem(::core::marker::PhantomData<$trait_instance>), + pub enum $call_type<$trait_instance: $trait_name$(, $instance: $instantiable $( = $module_default_instance)?)?> { + #[doc(hidden)] + __PhantomItem(::core::marker::PhantomData<($trait_instance $(, $instance)?)>, $crate::dispatch::Never), $( #[allow(non_camel_case_types)] + $(#[doc = $doc_attr])* $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> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Clone + for $call_type<$trait_instance $(, $instance)?> { fn clone(&self) -> Self { match *self { @@ -642,8 +731,8 @@ macro_rules! decl_module { } } } - impl<$trait_instance: $trait_name> $crate::dispatch::PartialEq - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::PartialEq + for $call_type<$trait_instance $(, $instance)?> { fn eq(&self, _other: &Self) -> bool { match *self { @@ -654,8 +743,7 @@ macro_rules! decl_module { self_params == ( $( $param_name, )* ) } else { match *_other { - $call_type::__PhantomItem(_) => unreachable!(), - $call_type::__OtherPhantomItem(_) => unreachable!(), + $call_type::__PhantomItem(_, _) => unreachable!(), _ => false, } } @@ -665,13 +753,13 @@ macro_rules! decl_module { } } } - impl<$trait_instance: $trait_name> $crate::dispatch::Eq - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Eq + for $call_type<$trait_instance $(, $instance)?> {} #[cfg(feature = "std")] - impl<$trait_instance: $trait_name> $crate::dispatch::fmt::Debug - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::fmt::Debug + for $call_type<$trait_instance $(, $instance)?> { fn fmt(&self, _f: &mut $crate::dispatch::fmt::Formatter) -> $crate::dispatch::result::Result<(), $crate::dispatch::fmt::Error> { match *self { @@ -687,22 +775,20 @@ macro_rules! decl_module { } } - impl<$trait_instance: $trait_name> $crate::dispatch::Decode for $call_type<$trait_instance> { - fn decode(input: &mut I) -> Option { + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Decode for $call_type<$trait_instance $(, $instance)?> { + fn decode(input: &mut Input) -> Option { let _input_id = input.read_byte()?; $crate::__impl_decode!(input; _input_id; 0; $call_type; $( fn $fn_name( $( $(#[$codec_attr on type $param])* $param_name ),* ); )*) } } - impl<$trait_instance: $trait_name> $crate::dispatch::Encode for $call_type<$trait_instance> { + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Encode for $call_type<$trait_instance $(, $instance)?> { fn encode_to(&self, _dest: &mut W) { $crate::__impl_encode!(_dest; *self; 0; $call_type; $( fn $fn_name( $( $(#[$codec_attr on type $param])* $param_name ),* ); )*); - if let $call_type::__PhantomItem(_) = *self { unreachable!() } - if let $call_type::__OtherPhantomItem(_) = *self { unreachable!() } } } - impl<$trait_instance: $trait_name> $crate::dispatch::Dispatchable - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Dispatchable + for $call_type<$trait_instance $(, $instance)?> { type Trait = $trait_instance; type Origin = $origin_type; @@ -713,27 +799,28 @@ macro_rules! decl_module { $crate::decl_module!( @call $from - $mod_type $trait_instance $fn_name _origin $system [ $( $param_name ),* ] + $mod_type<$trait_instance $(, $fn_instance)?> $fn_name _origin $system [ $( $param_name ),* ] ) }, )* - _ => { panic!("__PhantomItem should never be used.") }, + $call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") }, } } } - impl<$trait_instance: $trait_name> $crate::dispatch::Callable - for $mod_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Callable + for $mod_type<$trait_instance $(, $instance)?> { - type Call = $call_type<$trait_instance>; + type Call = $call_type<$trait_instance $(, $instance)?>; } - impl<$trait_instance: $trait_name> $mod_type<$trait_instance> { + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { + #[doc(hidden)] pub fn dispatch>(d: D, origin: D::Origin) -> $crate::dispatch::Result { d.dispatch(origin) } } $crate::__dispatch_impl_metadata! { - $mod_type $trait_instance $trait_name $call_type $origin_type + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?> $call_type $origin_type {$( $(#[doc = $doc_attr])* fn $fn_name($from $(, $(#[$codec_attr])* $param_name : $param )*); )*} } } @@ -940,10 +1027,11 @@ macro_rules! __impl_outer_dispatch_common { #[doc(hidden)] macro_rules! __dispatch_impl_metadata { ( - $mod_type:ident $trait_instance:ident $trait_name:ident + $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?> $($rest:tt)* ) => { - impl<$trait_instance: $trait_name> $mod_type<$trait_instance> { + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { + #[doc(hidden)] pub fn call_functions() -> &'static [$crate::dispatch::FunctionMetadata] { $crate::__call_to_functions!($($rest)*) } @@ -1055,7 +1143,7 @@ macro_rules! __function_to_metadata { #[allow(dead_code)] mod tests { use super::*; - use crate::runtime_primitives::traits::{OnInitialise, OnFinalise}; + use crate::runtime_primitives::traits::{OnInitialize, OnFinalize}; pub trait Trait { type Origin; @@ -1079,8 +1167,9 @@ mod tests { fn aux_3() -> Result { unreachable!() } fn aux_4(_data: i32) -> Result { unreachable!() } - fn on_initialise(n: T::BlockNumber) { if n.into() == 42 { panic!("on_initialise") } } - fn on_finalise(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalise") } } + fn on_initialize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_initialize") } } + fn on_finalize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalize") } } + fn offchain_worker() {} } } @@ -1154,14 +1243,14 @@ mod tests { } #[test] - #[should_panic(expected = "on_initialise")] - fn on_initialise_should_work() { - as OnInitialise>::on_initialise(42); + #[should_panic(expected = "on_initialize")] + fn on_initialize_should_work() { + as OnInitialize>::on_initialize(42); } #[test] - #[should_panic(expected = "on_finalise")] - fn on_finalise_should_work() { - as OnFinalise>::on_finalise(42); + #[should_panic(expected = "on_finalize")] + fn on_finalize_should_work() { + as OnFinalize>::on_finalize(42); } } diff --git a/srml/support/src/double_map.rs b/srml/support/src/double_map.rs index bd3fd973c2b2ee46d8bc073429b046cc65ad951d..80d974064dedd41bbebd506e890e58575fd6f32c 100644 --- a/srml/support/src/double_map.rs +++ b/srml/support/src/double_map.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -31,7 +31,9 @@ use sr_std::borrow::Borrow; /// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. /// The first part is a hash of a concatenation of the `PREFIX` and `Key1`. And the second part /// is a hash of a `Key2`. -pub trait StorageDoubleMap { +/// +/// Hasher are implemented in derive_key* methods. +pub trait StorageDoubleMapWithHasher { type Key1: Codec; type Key2: Codec; type Value: Codec + Default; @@ -121,7 +123,7 @@ pub trait StorageDoubleMap { fn derive_key2(key2_data: Vec) -> Vec; /// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`. - /// The first part is hased and then concatenated with a hash of `k2`. + /// The first part is hashed and then concatenated with a hash of `k2`. fn full_key(k1: &Q, k2: &R) -> Vec where Self::Key1: Borrow, diff --git a/srml/support/src/event.rs b/srml/support/src/event.rs index 6d00e6b10b5453653b018dfa5d9f62fd30a603b3..9ca2bcf5321af5688b3395d9dea81770e4f2bb4c 100644 --- a/srml/support/src/event.rs +++ b/srml/support/src/event.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -67,7 +67,7 @@ pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEn /// /// mod event2 { /// // Event that uses the generic parameter `Balance`. -/// // If no name for the generic parameter is speciefied explicitly, +/// // If no name for the generic parameter is specified explicitly, /// // the name will be taken from the type name of the trait. /// decl_event!( /// pub enum Event where ::Balance { @@ -88,16 +88,48 @@ pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEn /// ``` /// /// The syntax for generic events requires the `where`. +/// +/// # Generic Event with Instance Example: +/// +/// ```rust +/// #[macro_use] +/// extern crate srml_support; +/// extern crate parity_codec as codec; +/// #[macro_use] +/// extern crate parity_codec; +/// #[macro_use] +/// extern crate serde_derive; +/// +///# struct DefaultInstance; +///# trait Instance {} +///# impl Instance for DefaultInstance {} +/// trait Trait { +/// type Balance; +/// type Token; +/// } +/// +/// // For module with instances, DefaultInstance is optionnal +/// decl_event!( +/// pub enum Event where +/// ::Balance, +/// ::Token +/// { +/// Message(Balance, Token), +/// } +/// ); +///# fn main() {} +/// ``` #[macro_export] macro_rules! decl_event { ( $(#[$attr:meta])* - pub enum Event<$evt_generic_param:ident> where + pub enum Event<$evt_generic_param:ident $(, $instance:ident $(: $instantiable:ident)? $( = $event_default_instance:path)? )?> where $( $tt:tt )* ) => { $crate::__decl_generic_event!( $( #[ $attr ] )*; $evt_generic_param; + $($instance $( = $event_default_instance)? )?; { $( $tt )* }; ); }; @@ -112,6 +144,8 @@ macro_rules! decl_event { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] #[cfg_attr(feature = "std", derive(Debug))] + /// Events for this module. + /// $(#[$attr])* pub enum Event { $( @@ -138,25 +172,61 @@ macro_rules! __decl_generic_event { ( $(#[$attr:meta])*; $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; { $( $tt:tt )* }; ) => { $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; + $($instance $( = $event_default_instance)? )?; { $( $tt )* }; {}; ); }; + // Finish formatting on an unnamed one + (@format_generic + $(#[$attr:meta])*; + $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; + { <$generic:ident as $trait:path>::$trait_type:ident $(,)? { $( $events:tt )* } }; + {$( $parsed:tt)*}; + ) => { + $crate::__decl_generic_event!(@generate + $( #[ $attr ] )*; + $event_generic_param; + $($instance $( = $event_default_instance)? )?; + { $($events)* }; + { $($parsed)*, $trait_type = <$generic as $trait>::$trait_type }; + ); + }; + // Finish formatting on a named one + (@format_generic + $(#[$attr:meta])*; + $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; + { $generic_rename:ident = $generic_type:ty $(,)? { $( $events:tt )* } }; + { $($parsed:tt)* }; + ) => { + $crate::__decl_generic_event!(@generate + $(#[$attr])*; + $event_generic_param; + $($instance $( = $event_default_instance)? )?; + { $($events)* }; + { $($parsed)*, $generic_rename = $generic_type }; + ); + }; // Parse named (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; { $generic_rename:ident = $generic_type:ty, $($rest:tt)* }; {$( $parsed:tt)*}; ) => { $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; + $( $instance $( = $event_default_instance)? )?; { $($rest)* }; { $($parsed)*, $generic_rename = $generic_type }; ); @@ -165,12 +235,14 @@ macro_rules! __decl_generic_event { (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; { <$generic:ident as $trait:path>::$trait_type:ident, $($rest:tt)* }; {$($parsed:tt)*}; ) => { $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; + $($instance $( = $event_default_instance)? )?; { $($rest)* }; { $($parsed)*, $trait_type = <$generic as $trait>::$trait_type }; ); @@ -179,43 +251,17 @@ macro_rules! __decl_generic_event { (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; { $generic_type:ty, $($rest:tt)* }; - {$($parsed:tt)*}; + { $($parsed:tt)* }; ) => { $crate::__decl_generic_event!(@cannot_parse $generic_type); }; - // Finish formatting on an unnamed one - (@format_generic - $(#[$attr:meta])*; - $event_generic_param:ident; - { <$generic:ident as $trait:path>::$trait_type:ident { $( $events:tt )* } }; - {$( $parsed:tt)*}; - ) => { - $crate::__decl_generic_event!(@generate - $( #[ $attr ] )*; - $event_generic_param; - { $($events)* }; - { $($parsed)*, $trait_type = <$generic as $trait>::$trait_type}; - ); - }; - // Finish formatting on a named one - (@format_generic - $(#[$attr:meta])*; - $event_generic_param:ident; - { $generic_rename:ident = $generic_type:ty { $( $events:tt )* } }; - {$( $parsed:tt)*}; - ) => { - $crate::__decl_generic_event!(@generate - $(#[$attr])*; - $event_generic_param; - { $($events)* }; - { $($parsed)*, $generic_rename = $generic_type}; - ); - }; // Final unnamed type can't be parsed (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; { $generic_type:ty { $( $events:tt )* } }; {$( $parsed:tt)*}; ) => { @@ -224,23 +270,35 @@ macro_rules! __decl_generic_event { (@generate $(#[$attr:meta])*; $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; { $( $events:tt )* }; { ,$( $generic_param:ident = $generic_type:ty ),* }; ) => { - pub type Event<$event_generic_param> = RawEvent<$( $generic_type ),*>; + /// [`RawEvent`] specialized for the configuration [`Trait`] + /// + /// [`RawEvent`]: enum.RawEvent.html + /// [`Trait`]: trait.Trait.html + pub type Event<$event_generic_param $(, $instance $( = $event_default_instance)? )?> = RawEvent<$( $generic_type ),* $(, $instance)? >; + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] #[cfg_attr(feature = "std", derive(Debug))] + /// Events for this module. + /// $(#[$attr])* - pub enum RawEvent<$( $generic_param ),*> { + pub enum RawEvent<$( $generic_param ),* $(, $instance)? > { $( $events )* + $( + #[doc(hidden)] + PhantomData($crate::rstd::marker::PhantomData<$instance>), + )? } - impl<$( $generic_param ),*> From> for () { - fn from(_: RawEvent<$( $generic_param ),*>) -> () { () } + impl<$( $generic_param ),* $(, $instance)? > From> for () { + fn from(_: RawEvent<$( $generic_param ),* $(, $instance)?>) -> () { () } } - impl<$( $generic_param ),*> RawEvent<$( $generic_param ),*> { + impl<$( $generic_param ),* $(, $instance)?> RawEvent<$( $generic_param ),* $(, $instance)?> { #[allow(dead_code)] pub fn metadata() -> &'static [$crate::event::EventMetadata] { $crate::__events_to_metadata!(; $( $events )* ) @@ -293,7 +351,7 @@ macro_rules! impl_outer_event { ( $(#[$attr:meta])* pub enum $name:ident for $runtime:ident { - $( $rest:tt $( <$t:ident> )*, )* + $( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )* } ) => { $crate::impl_outer_event!( @@ -301,14 +359,14 @@ macro_rules! impl_outer_event { $name; $runtime; system; - Modules { $( $rest $(<$t>)*, )* }; + Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* }; ; ); }; ( $(#[$attr:meta])* pub enum $name:ident for $runtime:ident where system = $system:ident { - $( $rest:tt $( <$t:ident> )*, )* + $( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )* } ) => { $crate::impl_outer_event!( @@ -316,7 +374,7 @@ macro_rules! impl_outer_event { $name; $runtime; $system; - Modules { $( $rest $(<$t>)*, )* }; + Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* }; ; ); }; @@ -326,18 +384,18 @@ macro_rules! impl_outer_event { $runtime:ident; $system:ident; Modules { - $module:ident, - $( $rest:tt $( <$t:ident> )*, )* + $module:ident, + $( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )* }; - $( $module_name:ident::Event $( <$generic_param:ident> )*, )*; + $( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*; ) => { $crate::impl_outer_event!( $( #[$attr] )*; $name; $runtime; $system; - Modules { $( $rest $(<$t>)*, )* }; - $( $module_name::Event $( <$generic_param> )*, )* $module::Event<$runtime>,; + Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* }; + $( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )* $module::Event<$runtime $(, $instance)? >,; ); }; ( @@ -347,17 +405,17 @@ macro_rules! impl_outer_event { $system:ident; Modules { $module:ident, - $( $rest:tt, )* + $( $rest:tt )* }; - $( $module_name:ident::Event $( <$generic_param:ident> )*, )*; + $( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*; ) => { $crate::impl_outer_event!( $( #[$attr] )*; $name; $runtime; $system; - Modules { $( $rest, )* }; - $( $module_name::Event $( <$generic_param> )*, )* $module::Event,; + Modules { $( $rest )* }; + $( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )* $module::Event,; ); }; @@ -369,7 +427,7 @@ macro_rules! impl_outer_event { $runtime:ident; $system:ident; Modules {}; - $( $module_name:ident::Event $( <$generic_param:ident> )*, )*; + $( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*; ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] @@ -379,7 +437,7 @@ macro_rules! impl_outer_event { pub enum $name { system($system::Event), $( - $module_name( $module_name::Event $( <$generic_param> )* ), + $module_name( $module_name::Event $( <$generic_param $(, $generic_instance)? > )* ), )* } impl From<$system::Event> for $name { @@ -388,8 +446,8 @@ macro_rules! impl_outer_event { } } $( - impl From<$module_name::Event $( <$generic_param> )*> for $name { - fn from(x: $module_name::Event $( <$generic_param> )*) -> Self { + impl From<$module_name::Event $( <$generic_param $(, $generic_instance)? > )*> for $name { + fn from(x: $module_name::Event $( <$generic_param $(, $generic_instance)? > )*) -> Self { $name::$module_name(x) } } @@ -398,7 +456,7 @@ macro_rules! impl_outer_event { $runtime; $name; $system; - $( $module_name::Event $( <$generic_param> )*, )*; + $( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )*; ); } } @@ -410,7 +468,7 @@ macro_rules! __impl_outer_event_json_metadata { $runtime:ident; $event_name:ident; $system:ident; - $( $module_name:ident::Event $( <$generic_param:ident> )*, )*; + $( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*; ) => { impl $runtime { #[allow(dead_code)] @@ -423,7 +481,7 @@ macro_rules! __impl_outer_event_json_metadata { , ( stringify!($module_name), $crate::event::FnEncode( - $module_name::Event $( ::<$generic_param> )* ::metadata + $module_name::Event $( ::<$generic_param $(, $generic_instance)? > )* ::metadata ) ) )* @@ -438,7 +496,7 @@ macro_rules! __impl_outer_event_json_metadata { #[allow(dead_code)] $crate::paste::item!{ pub fn [< __module_events_ $module_name >] () -> &'static [$crate::event::EventMetadata] { - $module_name::Event $( ::<$generic_param> )* ::metadata() + $module_name::Event $( ::<$generic_param $(, $generic_instance)? > )* ::metadata() } } )* @@ -541,6 +599,50 @@ mod tests { ); } + mod event_module4 { + pub trait Trait { + type Origin; + type Balance; + type BlockNumber; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + /// Event finish formatting on an unnamed one with trailling comma + pub enum Event where + ::Balance, + ::Origin, + { + TestEvent(Balance, Origin), + } + ); + } + + mod event_module5 { + pub trait Trait { + type Origin; + type Balance; + type BlockNumber; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + /// Event finish formatting on an named one with trailling comma + pub enum Event where + BalanceRenamed = ::Balance, + OriginRenamed = ::Origin, + { + TestEvent(BalanceRenamed, OriginRenamed), + } + ); + } + #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)] pub struct TestRuntime; diff --git a/srml/support/src/hashable.rs b/srml/support/src/hashable.rs index 3d8b706b89abb4f583b15d52ac50abb8c45ec43b..886c88b23a3e83a360b6f344d03ef1abb8a9590d 100644 --- a/srml/support/src/hashable.rs +++ b/srml/support/src/hashable.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -27,12 +27,12 @@ pub trait Hashable: Sized { impl Hashable for T { fn blake2_256(&self) -> [u8; 32] { - blake2_256(&self.encode()) + self.using_encoded(blake2_256) } fn twox_128(&self) -> [u8; 16] { - twox_128(&self.encode()) + self.using_encoded(twox_128) } fn twox_256(&self) -> [u8; 32] { - twox_256(&self.encode()) + self.using_encoded(twox_256) } } diff --git a/srml/support/src/inherent.rs b/srml/support/src/inherent.rs index 671059ebe1346240e9aa8594950aeb3ee663181d..8a4fb669d15daafacb4cfaf6643374c70d2206cb 100644 --- a/srml/support/src/inherent.rs +++ b/srml/support/src/inherent.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index a7bbf329381e6e6968bcaaff56427a3c0b6d6633..d99db6ddb828799039c10ce743c52d9c51ca4d5f 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,6 +19,9 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] +#[macro_use] +extern crate bitmask; + #[cfg(feature = "std")] pub use serde; #[doc(hidden)] @@ -33,6 +36,7 @@ pub use paste; pub use sr_primitives as runtime_primitives; pub use self::storage::generator::Storage as GenericStorage; +pub use self::storage::unhashed::generator::UnhashedStorage as GenericUnhashedStorage; #[macro_use] pub mod dispatch; @@ -52,10 +56,10 @@ pub mod inherent; mod double_map; pub mod traits; -pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap, EnumerableStorageMap}; +pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap, EnumerableStorageMap, StorageDoubleMap}; pub use self::hashable::Hashable; pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType}; -pub use self::double_map::StorageDoubleMap; +pub use self::double_map::StorageDoubleMapWithHasher; pub use runtime_io::print; #[doc(inline)] @@ -106,6 +110,47 @@ macro_rules! assert_ok { } } +/// Panic when the vectors are different, without taking the order into account. +/// +/// # Examples +/// +/// ```rust +/// #[macro_use] +/// # extern crate srml_support; +/// # use srml_support::{assert_eq_uvec}; +/// # fn main() { +/// assert_eq_uvec!(vec![1,2], vec![2,1]); +/// # } +/// ``` +/// +/// ```rust,should_panic +/// #[macro_use] +/// # extern crate srml_support; +/// # use srml_support::{assert_eq_uvec}; +/// # fn main() { +/// assert_eq_uvec!(vec![1,2,3], vec![2,1]); +/// # } +/// ``` +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_eq_uvec { + ( $x:expr, $y:expr ) => { + $crate::__assert_eq_uvec!($x, $y); + $crate::__assert_eq_uvec!($y, $x); + } +} + +#[macro_export] +#[doc(hidden)] +#[cfg(feature = "std")] +macro_rules! __assert_eq_uvec { + ( $x:expr, $y:expr ) => { + $x.iter().for_each(|e| { + if !$y.contains(e) { panic!(format!("vectors not equal: {:?} != {:?}", $x, $y)); } + }); + } +} + /// The void type - it cannot exist. // Oh rust, you crack me up... #[derive(Clone, Eq, PartialEq)] @@ -137,6 +182,12 @@ mod tests { use parity_codec::Codec; use runtime_io::{with_externalities, Blake2Hasher}; use runtime_primitives::BuildStorage; + pub use srml_metadata::{ + DecodeDifferent, StorageMetadata, StorageFunctionMetadata, + StorageFunctionType, StorageFunctionModifier, + DefaultByte, DefaultByteGetter, + }; + pub use rstd::marker::PhantomData; pub trait Trait { type BlockNumber: Codec + Default; @@ -161,6 +212,10 @@ mod tests { pub Data get(data) build(|_| vec![(15u32, 42u64)]): linked_map u32 => u64; pub GenericData get(generic_data): linked_map T::BlockNumber => T::BlockNumber; pub GenericData2 get(generic_data2): linked_map T::BlockNumber => Option; + + pub DataDM config(test_config) build(|_| vec![(15u32, 16u32, 42u64)]): double_map u32, blake2_256(u32) => u64; + pub GenericDataDM: double_map T::BlockNumber, twox_128(T::BlockNumber) => T::BlockNumber; + pub GenericData2DM: double_map T::BlockNumber, twox_256(T::BlockNumber) => Option; } } @@ -177,9 +232,9 @@ mod tests { type Map = Data; #[test] - fn basic_insert_remove_should_work() { + fn linked_map_basic_insert_remove_should_work() { with_externalities(&mut new_test_ext(), || { - // initialised during genesis + // initialized during genesis assert_eq!(Map::get(&15u32), 42u64); // get / insert / take @@ -203,7 +258,7 @@ mod tests { } #[test] - fn enumeration_and_head_should_work() { + fn linked_map_enumeration_and_head_should_work() { with_externalities(&mut new_test_ext(), || { assert_eq!(Map::head(), Some(15)); assert_eq!(Map::enumerate().collect::>(), vec![(15, 42)]); @@ -254,4 +309,128 @@ mod tests { }); } + #[test] + fn double_map_basic_insert_remove_remove_prefix_should_work() { + with_externalities(&mut new_test_ext(), || { + type DoubleMap = DataDM; + // initialized during genesis + assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64); + + // get / insert / take + let key1 = 17u32; + let key2 = 18u32; + assert_eq!(DoubleMap::get(key1, key2), 0u64); + DoubleMap::insert(key1, key2, 4u64); + assert_eq!(DoubleMap::get(key1, key2), 4u64); + assert_eq!(DoubleMap::take(key1, key2), 4u64); + assert_eq!(DoubleMap::get(key1, key2), 0u64); + + // mutate + DoubleMap::mutate(key1, key2, |val| { + *val = 15; + }); + assert_eq!(DoubleMap::get(key1, key2), 15u64); + + // remove + DoubleMap::remove(key1, key2); + assert_eq!(DoubleMap::get(key1, key2), 0u64); + + // remove prefix + DoubleMap::insert(key1, key2, 4u64); + DoubleMap::insert(key1, key2+1, 4u64); + DoubleMap::insert(key1+1, key2, 4u64); + DoubleMap::insert(key1+1, key2+1, 4u64); + DoubleMap::remove_prefix(key1); + assert_eq!(DoubleMap::get(key1, key2), 0u64); + assert_eq!(DoubleMap::get(key1, key2+1), 0u64); + assert_eq!(DoubleMap::get(key1+1, key2), 4u64); + assert_eq!(DoubleMap::get(key1+1, key2+1), 4u64); + }); + } + + const EXPECTED_METADATA: StorageMetadata = StorageMetadata { + functions: DecodeDifferent::Encode(&[ + StorageFunctionMetadata { + name: DecodeDifferent::Encode("Data"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::Map{ + key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("u64"), is_linked: true + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructData(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("GenericData"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::Map{ + key: DecodeDifferent::Encode("T::BlockNumber"), value: DecodeDifferent::Encode("T::BlockNumber"), is_linked: true + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericData(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("GenericData2"), + modifier: StorageFunctionModifier::Optional, + ty: StorageFunctionType::Map{ + key: DecodeDifferent::Encode("T::BlockNumber"), value: DecodeDifferent::Encode("T::BlockNumber"), is_linked: true + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericData2(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("DataDM"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::DoubleMap{ + key1: DecodeDifferent::Encode("u32"), + key2: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("u64"), + key2_hasher: DecodeDifferent::Encode("blake2_256"), + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructDataDM(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("GenericDataDM"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::DoubleMap{ + key1: DecodeDifferent::Encode("T::BlockNumber"), + key2: DecodeDifferent::Encode("T::BlockNumber"), + value: DecodeDifferent::Encode("T::BlockNumber"), + key2_hasher: DecodeDifferent::Encode("twox_128"), + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericDataDM(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("GenericData2DM"), + modifier: StorageFunctionModifier::Optional, + ty: StorageFunctionType::DoubleMap{ + key1: DecodeDifferent::Encode("T::BlockNumber"), + key2: DecodeDifferent::Encode("T::BlockNumber"), + value: DecodeDifferent::Encode("T::BlockNumber"), + key2_hasher: DecodeDifferent::Encode("twox_256"), + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + ]) + }; + + #[test] + fn store_metadata() { + let metadata = Module::::store_metadata(); + assert_eq!(EXPECTED_METADATA, metadata); + } } diff --git a/srml/support/src/metadata.rs b/srml/support/src/metadata.rs index 229f132ac9f894c80ffc036180b139ba1cbea921..f7594d27b7c2b79a1cca6ea2bfb5e8135e5a3b9b 100644 --- a/srml/support/src/metadata.rs +++ b/srml/support/src/metadata.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ pub use srml_metadata::{ DecodeDifferent, FnEncode, RuntimeMetadata, - ModuleMetadata, RuntimeMetadataV1, + ModuleMetadata, RuntimeMetadataV3, DefaultByteGetter, RuntimeMetadataPrefixed, }; @@ -36,8 +36,8 @@ macro_rules! impl_runtime_metadata { ) => { impl $runtime { pub fn metadata() -> $crate::metadata::RuntimeMetadataPrefixed { - $crate::metadata::RuntimeMetadata::V1 ( - $crate::metadata::RuntimeMetadataV1 { + $crate::metadata::RuntimeMetadata::V3 ( + $crate::metadata::RuntimeMetadataV3 { modules: $crate::__runtime_modules_to_metadata!($runtime;; $( $rest )*), } ).into() @@ -52,17 +52,17 @@ macro_rules! __runtime_modules_to_metadata { ( $runtime: ident; $( $metadata:expr ),*; - $mod:ident::$module:ident $(with)+ $($kw:ident)*, + $mod:ident::$module:ident $( < $instance:ident > )? $(with)+ $($kw:ident)*, $( $rest:tt )* ) => { $crate::__runtime_modules_to_metadata!( $runtime; $( $metadata, )* $crate::metadata::ModuleMetadata { name: $crate::metadata::DecodeDifferent::Encode(stringify!($mod)), - prefix: $crate::__runtime_modules_to_metadata_calls_storagename!($mod, $module, $runtime, $(with $kw)*), - storage: $crate::__runtime_modules_to_metadata_calls_storage!($mod, $module, $runtime, $(with $kw)*), - calls: $crate::__runtime_modules_to_metadata_calls_call!($mod, $module, $runtime, $(with $kw)*), - event: $crate::__runtime_modules_to_metadata_calls_event!($mod, $module, $runtime, $(with $kw)*), + prefix: $crate::__runtime_modules_to_metadata_calls_storagename!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*), + storage: $crate::__runtime_modules_to_metadata_calls_storage!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*), + calls: $crate::__runtime_modules_to_metadata_calls_call!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*), + event: $crate::__runtime_modules_to_metadata_calls_event!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*), }; $( $rest )* ) @@ -81,7 +81,7 @@ macro_rules! __runtime_modules_to_metadata_calls_call { // skip system ( system, - $skip_module: ident, + $skip_module: ident $( <$instance:ident> )?, $skip_runtime: ident, with Call $(with $kws:ident)* @@ -90,29 +90,29 @@ macro_rules! __runtime_modules_to_metadata_calls_call { }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, with Call $(with $kws:ident)* ) => { Some($crate::metadata::DecodeDifferent::Encode( $crate::metadata::FnEncode( - $mod::$module::<$runtime>::call_functions + $mod::$module::<$runtime $(, $mod::$instance )?>::call_functions ) )) }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, with $_:ident $(with $kws:ident)* ) => { - $crate::__runtime_modules_to_metadata_calls_call!( $mod, $module, $runtime, $(with $kws)* ); + $crate::__runtime_modules_to_metadata_calls_call!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* ); }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, ) => { None @@ -125,7 +125,7 @@ macro_rules! __runtime_modules_to_metadata_calls_call { macro_rules! __runtime_modules_to_metadata_calls_event { ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, with Event $(with $kws:ident)* @@ -133,23 +133,23 @@ macro_rules! __runtime_modules_to_metadata_calls_event { Some($crate::metadata::DecodeDifferent::Encode( $crate::metadata::FnEncode( $crate::paste::expr!{ - $runtime:: [< __module_events_ $mod >] + $runtime:: [< __module_events_ $mod $(_ $instance)?>] } ) )) }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, with $_:ident $(with $kws:ident)* ) => { - $crate::__runtime_modules_to_metadata_calls_event!( $mod, $module, $runtime, $(with $kws)* ); + $crate::__runtime_modules_to_metadata_calls_event!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* ); }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, ) => { None @@ -161,29 +161,29 @@ macro_rules! __runtime_modules_to_metadata_calls_event { macro_rules! __runtime_modules_to_metadata_calls_storagename { ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, with Storage $(with $kws:ident)* ) => { $crate::metadata::DecodeDifferent::Encode( $crate::metadata::FnEncode( - $mod::$module::<$runtime>::store_metadata_name + $mod::$module::<$runtime $(, $mod::$instance )?>::store_metadata_name ) ) }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, with $_:ident $(with $kws:ident)* ) => { - $crate::__runtime_modules_to_metadata_calls_storagename!( $mod, $module, $runtime, $(with $kws)* ); + $crate::__runtime_modules_to_metadata_calls_storagename!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* ); }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, ) => { $crate::metadata::DecodeDifferent::Encode( @@ -197,29 +197,29 @@ macro_rules! __runtime_modules_to_metadata_calls_storagename { macro_rules! __runtime_modules_to_metadata_calls_storage { ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, with Storage $(with $kws:ident)* ) => { Some($crate::metadata::DecodeDifferent::Encode( $crate::metadata::FnEncode( - $mod::$module::<$runtime>::store_metadata_functions + $mod::$module::<$runtime $(, $mod::$instance )?>::store_metadata_functions ) )) }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, with $_:ident $(with $kws:ident)* ) => { - $crate::__runtime_modules_to_metadata_calls_storage!( $mod, $module, $runtime, $(with $kws)* ); + $crate::__runtime_modules_to_metadata_calls_storage!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* ); }; ( $mod: ident, - $module: ident, + $module: ident $( <$instance:ident> )?, $runtime: ident, ) => { None @@ -377,8 +377,8 @@ mod tests { event_module2::Module with Event Storage Call, ); - const EXPECTED_METADATA: RuntimeMetadata = RuntimeMetadata::V1( - RuntimeMetadataV1 { + const EXPECTED_METADATA: RuntimeMetadata = RuntimeMetadata::V3( + RuntimeMetadataV3 { modules: DecodeDifferent::Encode(&[ ModuleMetadata { name: DecodeDifferent::Encode("system"), diff --git a/srml/support/src/origin.rs b/srml/support/src/origin.rs index 5832a4f7b8c72f4269544ddbcb75c86d26e0c9c8..2d97f218e095819fb41f8868a7b17929d7a4bcd2 100644 --- a/srml/support/src/origin.rs +++ b/srml/support/src/origin.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -28,34 +28,20 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])* pub enum $name:ident for $runtime:ident { - $( $module:ident $( <$generic:ident> )* ),* $(,)* + $( $module:ident $( <$generic:ident $(, $instance:path )? > )? ),* $(,)? } ) => { $crate::impl_outer_origin! { $(#[$attr])* pub enum $name for $runtime where system = system { - $( $module $( <$generic> )*, )* + $( $module $( <$generic $(, $instance )? > )?, )* } } }; - ( - $(#[$attr:meta])* - pub enum $name:ident for $runtime:ident where system = $system:ident {} - ) => { - $crate::impl_outer_origin!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { }; - ; - ); - }; ( $(#[$attr:meta])* pub enum $name:ident for $runtime:ident where system = $system:ident { - $module:ident, - $( $rest_module:ident $( <$rest_generic:ident> )* ),* $(,)* + $( $module:ident $( <$generic:ident $(, $instance:path )?> )? ),* $(,)? } ) => { $crate::impl_outer_origin!( @@ -63,64 +49,30 @@ macro_rules! impl_outer_origin { $name; $runtime; $system; - Modules { $( $rest_module $( <$rest_generic> )*, )* }; - $module; - ); - }; - ( - $(#[$attr:meta])* - pub enum $name:ident for $runtime:ident where system = $system:ident { - $module:ident, - $( $rest_module:ident $( <$rest_generic:ident> )* ),* $(,)* - } - ) => { - $crate::impl_outer_origin!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_module $( <$rest_generic> )*, )* }; - $module<$runtime>; - ); - }; - ( - $(#[$attr:meta])*; - $name:ident; - $runtime:ident; - $system:ident; - Modules { - $module:ident, - $( $rest_module:ident $( <$rest_generic:ident> )*, )* - }; - $( $parsed_module:ident $( <$generic_param:ident> )* ),*; - ) => { - $crate::impl_outer_origin!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_module $( <$rest_generic> )*, )* }; - $( $parsed_module $( <$generic_param> )* ),*, $module; + Modules { $( $module $( <$generic $(, $instance )? > )*, )* }; ); }; + + // Replace generic param with runtime + ( $(#[$attr:meta])*; $name:ident; $runtime:ident; $system:ident; Modules { - $module:ident, - $( $rest_module:ident $( <$rest_generic:ident> )*, )* + $module:ident $( )?, + $( $rest_module:tt )* }; - $( $parsed_module:ident $( <$generic_param:ident> )* ),*; + $( $parsed:tt )* ) => { $crate::impl_outer_origin!( $( #[$attr] )*; $name; $runtime; $system; - Modules { $( $rest_module $( <$rest_generic> )*, )* }; - $( $parsed_module $( <$generic_param> )* ),*, $module<$runtime>; + Modules { $( $rest_module )* }; + $( $parsed )* $module $( <$runtime $(, $instance )? > )?, ); }; @@ -131,8 +83,8 @@ macro_rules! impl_outer_origin { $name:ident; $runtime:ident; $system:ident; - Modules {}; - $( $module:ident $( <$generic_param:ident> )* ),*; + Modules { }; + $( $module:ident $( <$generic_param:ident $(, $generic_instance:path )? > )* ,)* ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq)] @@ -142,7 +94,7 @@ macro_rules! impl_outer_origin { pub enum $name { system($system::Origin<$runtime>), $( - $module($module::Origin $( <$generic_param> )* ), + $module($module::Origin $( <$generic_param $(, $generic_instance )? > )* ), )* #[allow(dead_code)] Void($crate::Void) @@ -175,13 +127,13 @@ macro_rules! impl_outer_origin { } } $( - impl From<$module::Origin $( <$generic_param> )*> for $name { - fn from(x: $module::Origin $( <$generic_param> )*) -> Self { + impl From<$module::Origin $( <$generic_param $(, $generic_instance )? > )*> for $name { + fn from(x: $module::Origin $( <$generic_param $(, $generic_instance )? > )*) -> Self { $name::$module(x) } } - impl Into )*>> for $name { - fn into(self) -> Option<$module::Origin $( <$generic_param> )*> { + impl Into )*>> for $name { + fn into(self) -> Option<$module::Origin $( <$generic_param $(, $generic_instance )? > )*> { if let $name::$module(l) = self { Some(l) } else { diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs index a1093dae5b27e381e99e434b29d2d5202a344333..4f402da8d5b545c099a9db7307f0467dc34d6323 100644 --- a/srml/support/src/runtime.rs +++ b/srml/support/src/runtime.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -37,6 +37,10 @@ /// System: system, /// Test: test::{default, Log(Test)}, /// Test2: test_with_long_module::{Module}, +/// +/// // Module with instances +/// Test3_Instance1: test3::::{Module, Call, Storage, Event, Config, Origin}, +/// Test3_DefaultInstance: test3::{Module, Call, Storage, Event, Config, Origin}, /// } /// ) /// ``` @@ -55,13 +59,18 @@ /// - `Module` /// - `Call` /// - `Storage` -/// - `Event` or `Event` (if the event is generic) -/// - `Origin` or `Origin` (if the origin is generic) -/// - `Config` or `Config` (if the config is generic) +/// - `Event` or `Event` (if the event is generic) or `Event` (if also over instance) +/// - `Origin` or `Origin` (if the origin is generic) or `Origin` (if also over instance) +/// - `Config` or `Config` (if the config is generic) or `Config` (if also over instance) /// - `Log( $(IDENT),* )` /// - `Inherent $( (CALL) )*` - If the module provides/can check inherents. The optional parameter /// is for modules that use a `Call` from a different module as /// inherent. +/// +/// # Note +/// +/// The population of the genesis storage depends on the order of modules. So, if one of your +/// modules depends on another module. The dependent module need to come before the module depending on it. #[macro_export] macro_rules! construct_runtime { @@ -78,156 +87,61 @@ macro_rules! construct_runtime { $( $rest:tt )* } ) => { - construct_runtime!( - $runtime; - $block; - $node_block; - $uncheckedextrinsic; - $log_internal < $( $log_genarg ),* >; - ; + $crate::construct_runtime!( + { + $runtime; + $block; + $node_block; + $uncheckedextrinsic; + $log_internal < $( $log_genarg ),* >; + }; + {}; $( $rest )* ); }; ( - $runtime:ident; - $block:ident; - $node_block:ty; - $uncheckedextrinsic:ident; - $log_internal:ident <$( $log_genarg:ty ),+>; - $( - $expanded_name:ident: $expanded_module:ident::{ - $( - $expanded_modules:ident - $( <$expanded_modules_generic:ident> )* - $( ( $( $expanded_modules_args:ident ),* ) )* - ),* - } - ),*; + { $( $preset:tt )* }; + { $( $expanded:tt )* }; $name:ident: $module:ident, - $( - $rest_name:ident: $rest_module:ident $( - ::{ - $( - $rest_modules:ident - $( <$rest_modules_generic:ident> )* - $( ( $( $rest_modules_args:ident ),* ) )* - ),* - } - )*, - )* + $( $rest:tt )* ) => { - construct_runtime!( - $runtime; - $block; - $node_block; - $uncheckedextrinsic; - $log_internal < $( $log_genarg ),* >; - $( - $expanded_name: $expanded_module::{ - $( - $expanded_modules - $( <$expanded_modules_generic> )* - $( ( $( $expanded_modules_args ),* ) )* - ),* - }, - )* $name: $module::{Module, Call, Storage, Event, Config}; - $( - $rest_name: $rest_module $( - ::{ - $( - $rest_modules - $( <$rest_modules_generic> )* - $( ( $( $rest_modules_args ),* ) )* - ),* - } - )*, - )* + $crate::construct_runtime!( + { $( $preset )* }; + { $( $expanded )* $name: $module::{Module, Call, Storage, Event, Config}, }; + $( $rest )* ); }; ( - $runtime:ident; - $block:ident; - $node_block:ty; - $uncheckedextrinsic:ident; - $log_internal:ident <$( $log_genarg:ty ),+>; - $( - $expanded_name:ident: $expanded_module:ident::{ - $( - $expanded_modules:ident - $( <$expanded_modules_generic:ident> )* - $( ( $( $expanded_modules_args:ident ),* ) )* - ),* - } - ),*; + { $( $preset:tt )* }; + { $( $expanded:tt )* }; $name:ident: $module:ident::{ default, $( $modules:ident - $( <$modules_generic:ident> )* + $( <$modules_generic:ident $(, $modules_instance:ident)?> )* $( ( $( $modules_args:ident ),* ) )* ),* }, - $( - $rest_name:ident: $rest_module:ident $( - ::{ + $( $rest:tt )* + ) => { + $crate::construct_runtime!( + { $( $preset )* }; + { + $( $expanded )* + $name: $module::{ + Module, Call, Storage, Event, Config, $( - $rest_modules:ident - $( <$rest_modules_generic:ident> )* - $( ( $( $rest_modules_args:ident ),* ) )* - ),* - } - )*, - )* - ) => { - construct_runtime!( - $runtime; - $block; - $node_block; - $uncheckedextrinsic; - $log_internal < $( $log_genarg ),* >; - $( - $expanded_name: $expanded_module::{ - $( - $expanded_modules - $( <$expanded_modules_generic> )* - $( ( $( $expanded_modules_args ),* ) )* + $modules $( <$modules_generic $(, $modules_instance)?> )* + $( ( $( $modules_args ),* ) )* ),* }, - )* - $name: $module::{ - Module, Call, Storage, Event, Config, - $( - $modules $( <$modules_generic> )* $( ( $( $modules_args ),* ) )* - ),* }; - $( - $rest_name: $rest_module $( - ::{ - $( - $rest_modules - $( <$rest_modules_generic> )* - $( ( $( $rest_modules_args ),* ) )* - ),* - } - )*, - )* + $( $rest )* ); }; ( - $runtime:ident; - $block:ident; - $node_block:ty; - $uncheckedextrinsic:ident; - $log_internal:ident <$( $log_genarg:ty ),+>; - $( - $expanded_name:ident: $expanded_module:ident::{ - $( - $expanded_modules:ident - $( <$expanded_modules_generic:ident> )* - $( ( $( $expanded_modules_args:ident ),* ) )* - ),* - } - ),*; + { $( $preset:tt )* }; + { $( $expanded:tt )* }; $name:ident: $module:ident::{ $( $modules:ident @@ -235,69 +149,70 @@ macro_rules! construct_runtime { $( ( $( $modules_args:ident ),* ) )* ),* }, - $( - $rest_name:ident: $rest_module:ident $( - ::{ + $( $rest:tt )* + ) => { + $crate::construct_runtime!( + { $( $preset )* }; + { + $( $expanded )* + $name: $module::{ $( - $rest_modules:ident - $( <$rest_modules_generic:ident> )* - $( ( $( $rest_modules_args:ident ),* ) )* + $modules $( <$modules_generic> )* + $( ( $( $modules_args ),* ) )* ),* - } - )*, - )* - ) => { - construct_runtime!( - $runtime; - $block; - $node_block; - $uncheckedextrinsic; - $log_internal < $( $log_genarg ),* >; + }, + }; + $( $rest )* + ); + }; + ( // Instance module: we indicate the generic instance `I` with the full instance path + { $( $preset:tt )* }; + { $( $expanded:tt )* }; + $name:ident: $module:ident ::< $module_instance:ident >::{ $( - $expanded_name: $expanded_module::{ + $modules:ident + $( <$modules_generic:ident $(, $modules_instance:ident )?> )* + $( ( $( $modules_args:ident ),* ) )* + ),* + }, + $( $rest:tt )* + ) => { + $crate::construct_runtime!( + { $( $preset )* }; + { + $( $expanded )* + $name: $module::<$module_instance>::{ $( - $expanded_modules - $( <$expanded_modules_generic> )* - $( ( $( $expanded_modules_args ),* ) )* + $modules $( <$modules_generic $(, $modules_instance=$module::$module_instance)?> )* + $( ( $( $modules_args ),* ) )* ),* }, - )* - $name: $module::{ - $( - $modules $( <$modules_generic> )* $( ( $( $modules_args ),* ) )* - ),* }; - $( - $rest_name: $rest_module $( - ::{ - $( - $rest_modules - $( <$rest_modules_generic> )* - $( ( $( $rest_modules_args ),* ) )* - ),* - } - )*, - )* + $( $rest )* ); }; // The main macro expansion that actually renders the Runtime code. ( - $runtime:ident; - $block:ident; - $node_block:ty; - $uncheckedextrinsic:ident; - $log_internal:ident <$( $log_genarg:ty ),+>; - $( - $name:ident: $module:ident::{ - $( - $modules:ident - $( <$modules_generic:ident> )* - $( ( $( $modules_args:ident ),* ) )* - ),* - } - ),*; + { + $runtime:ident; + $block:ident; + $node_block:ty; + $uncheckedextrinsic:ident; + $log_internal:ident <$( $log_genarg:ty ),+>; + }; + { + $( + $name:ident: $module:ident :: $( < $module_instance:ident >:: )? { + $( + $modules:ident + $( <$modules_generic:ident $(, I=$modules_instance:path)?> )* + $( ( $( $modules_args:ident ),* ) )* + ),* + }, + )* + }; ) => { #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] @@ -308,54 +223,59 @@ macro_rules! construct_runtime { impl $crate::runtime_primitives::traits::GetRuntimeBlockType for $runtime { type RuntimeBlock = $block; } + $crate::__decl_instance_import!( + $( $( $module < $module_instance > )? )* + ); $crate::__decl_outer_event!( $runtime; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* } ),* ); $crate::__decl_outer_origin!( $runtime; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* } ),* ); $crate::__decl_all_modules!( $runtime; ; - ; + {}; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - ),*; + $name: $module:: $( < $module_instance >:: )? { $( $modules ),* }, + )* ); $crate::__decl_outer_dispatch!( $runtime; ; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $name: $module::{ $( $modules ),* } ),*; ); $crate::__decl_runtime_metadata!( $runtime; - ; + {}; $( - $name: $module::{ $( $modules )* } + $name: $module:: $( < $module_instance >:: )? { $( $modules )* } )* ); $crate::__decl_outer_log!( $runtime; $log_internal < $( $log_genarg ),* >; - ; + {}; $( - $name: $module::{ $( $modules $( ( $( $modules_args ),* ) )* ),* } - ),*; + $name: $module:: $( < $module_instance >:: )? { $( $modules $( ( $( $modules_args )* ) )* )* } + )* ); $crate::__decl_outer_config!( $runtime; - ; + {}; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - ),*; + $name: $module:: $( < $module_instance >:: )? { + $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* + }, + )* ); $crate::__decl_outer_inherent!( $runtime; @@ -387,121 +307,135 @@ macro_rules! __create_decl_macro { macro_rules! $macro_name { ( $runtime:ident; - $d( $name:ident : $module:ident::{ - $d( $modules:ident $d( <$modules_generic:ident> )* ),* + $d( $name:ident : $module:ident:: $d( < $module_instance:ident >:: )? { + $d( $modules:ident $d( <$modules_generic:ident $d(, $modules_instance:path)?> ),* ),* }),* ) => { $d crate::$macro_name!(@inner $runtime; ; - ; + {}; $d( - $name: $module::{ - $d( $modules $d( <$modules_generic> )* ),* - } - ),*; + $name: $module:: $d( < $module_instance >:: )? { + $d( $modules $d( <$modules_generic $d(, $modules_instance)?> )* ),* + }, + )* ); }; (@inner $runtime:ident; ; // there can not be multiple `System`s - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; + { $d( $parsed:tt )* }; System: $module:ident::{ - $ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - } - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })*; + $d( $modules:ident $d( <$modules_generic:ident> )* ),* + }, + $d( $rest:tt )* ) => { $d crate::$macro_name!(@inner $runtime; $module; - $d( $parsed_modules $d( <$parsed_generic> )* ),*; - $d( - $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - ),*; + { $d( $parsed )* }; + $d( $rest )* ); }; (@inner $runtime:ident; - $d( $system:ident )*; - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; - $name:ident: $module:ident::{ - $macro_enum_name $d( <$event_gen:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - } - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })*; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: < $module_instance:ident >:: { + $macro_enum_name <$event_generic:ident, $event_instance:path> $d(, $ingore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )* + }, + $d( $rest:tt )* ) => { $d crate::$macro_name!(@inner $runtime; - $d( $system )*; - $d( - $parsed_modules $d( <$parsed_generic> )* , )* - $module $d( <$event_gen> )*; - $d( - $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - ),*; + $d( $system )?; + { + $d( $parsed )* + $module $module_instance <$event_generic, $event_instance>, + }; + $d( $rest )* ); }; (@inner $runtime:ident; - $d( $system:ident )*; - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; - $name:ident: $module:ident::{ - $ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - } - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })*; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: < $module_instance:ident >:: { + $macro_enum_name $d( <$event_generic:ident> )* $d(, $ingore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )* + }, + $d( $rest:tt )* + ) => { + compile_error!{concat!{ + "Module `", stringify!{$name}, "` must have `", stringify!{$macro_enum_name}, "`", + " but has `", stringify!{$macro_enum_name} $d(, "<", stringify!{$event_generic}, ">")*, "`", + ": Instantiated modules must have ", stringify!{$macro_enum_name}, + " generic over instance to be able to convert to outer ", stringify!{$macro_enum_name} + }} + }; + (@inner + $runtime:ident; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: { + $macro_enum_name $d( <$event_generic:ident $d(, $event_instance:path)?> )* $d(, $ingore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )* + }, + $d( $rest:tt )* ) => { $d crate::$macro_name!(@inner $runtime; - $d( $system )*; - $d( $parsed_modules $d( <$parsed_generic> )* ),*; - $name: $module::{ $d( $modules $d( <$modules_generic> )* ),* } - $d( - , $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - )*; + $d( $system )?; + { + $d( $parsed )* + $module $d( <$event_generic $d(, $event_instance)?> )*, + }; + $d( $rest )* ); }; (@inner $runtime:ident; - $d( $system:ident )*; - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; - $name:ident: $module:ident::{} - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })*; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: $d( < $module_instance:ident >:: )? { + $ingore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* $d(, $modules:ident $d( <$modules_generic:ident $d(, $modules_instance:path)?> )* )* + }, + $d( $rest:tt )* ) => { $d crate::$macro_name!(@inner $runtime; - $d( $system )*; - $d( $parsed_modules $d( <$parsed_generic> )* ),*; - $d( - $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - ),*; + $d( $system )?; + { $d( $parsed )* }; + $name: $module:: $d( < $module_instance >:: )? { $d( $modules $d( <$modules_generic $d(, $modules_instance)?> )* ),* }, + $d( $rest )* ); }; (@inner $runtime:ident; - $d( $system:ident )+; - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; - ; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident: $module:ident:: $d( < $module_instance:ident >:: )? {}, + $d( $rest:tt )* ) => { - $d crate::$macro_outer_name! { - pub enum $macro_enum_name for $runtime where system = $d( $system )* { - $d( - $parsed_modules $d( <$parsed_generic> )*, - )* + $d crate::$macro_name!(@inner + $runtime; + $d( $system )?; + { $d( $parsed )* }; + $d( $rest )* + ); + }; + (@inner + $runtime:ident; + $system:ident; + { $d( $parsed_modules:ident $d( $instance:ident )? $d( <$parsed_generic:ident $d(, $parsed_instance_full_path:path)?> )* ,)* }; + ) => { + $d crate::paste::item! { + $d crate::$macro_outer_name! { + + pub enum $macro_enum_name for $runtime where system = $system { + $d( + [< $parsed_modules $d(_ $instance )? >] $d( <$parsed_generic $d(, $parsed_instance_full_path)?> )*, + )* + } } } } @@ -519,99 +453,71 @@ macro_rules! __decl_all_modules { ( $runtime:ident; ; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - System: $module:ident::{ - Module $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + System: $module:ident::{ Module $(, $modules:ident )* }, + $( $rest:tt )* ) => { $crate::__decl_all_modules!( $runtime; $module; - $( $parsed_modules :: $parsed_name ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { $( $parsed )* }; + $( $rest )* ); }; ( $runtime:ident; - $( $system:ident )*; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{ - Module $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + $( $system:ident )?; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $(, $modules:ident )* }, + $( $rest:tt )* ) => { $crate::__decl_all_modules!( $runtime; - $( $system )*; - $( $parsed_modules :: $parsed_name, )* $module::$name; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + $( $system )?; + { + $( $parsed )* + $module::$name $(<$module_instance>)?, + }; + $( $rest )* ); }; ( $runtime:ident; - $( $system:ident )*; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{ - $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + $( $system:ident )?; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { $ingore:ident $(, $modules:ident )* }, + $( $rest:tt )* ) => { $crate::__decl_all_modules!( $runtime; - $( $system )*; - $( $parsed_modules :: $parsed_name ),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - )*; + $( $system )?; + { $( $parsed )* }; + $name: $module::{ $( $modules ),* }, + $( $rest )* ); }; ( $runtime:ident; - $( $system:ident )*; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + $( $system:ident )?; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {}, + $( $rest:tt )* ) => { $crate::__decl_all_modules!( $runtime; - $( $system )*; - $( $parsed_modules :: $parsed_name ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + $( $system )?; + { $( $parsed )* }; + $( $rest )* ); }; ( $runtime:ident; $system:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - ; + { $( $parsed_module:ident :: $parsed_name:ident $(<$instance:ident>)? ,)*}; ) => { pub type System = system::Module<$runtime>; $( - pub type $parsed_name = $parsed_modules::Module<$runtime>; + pub type $parsed_name = $parsed_module::Module<$runtime $(, $parsed_module::$instance )?>; )* type AllModules = ( $( $parsed_name, )* ); } @@ -721,84 +627,68 @@ macro_rules! __decl_runtime_metadata { // leading is Module : parse ( $runtime:ident; - $( $parsed_modules:ident { $( $withs:ident )* } )*; + { $( $parsed:tt )* }; $( { leading_module: $( $leading_module:ident )* } )? - $name:ident: $module:ident::{ + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $( $modules:ident )* } - $( $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident )* - })* + $( $rest:tt )* ) => { $crate::__decl_runtime_metadata!( $runtime; - $( $parsed_modules { $( $withs )* } )* $module { $( $( $leading_module )* )? $( $modules )* }; - $( - $rest_name: $rest_module::{ - $( $rest_modules )* - } - )* + { + $( $parsed )* + $module $( < $module_instance > )? { $( $( $leading_module )* )? $( $modules )* } + }; + $( $rest )* ); }; // leading isn't Module : put it in leadings ( $runtime:ident; - $( $parsed_modules:ident { $( $withs:ident )* } )*; + { $( $parsed:tt )* }; $( { leading_module: $( $leading_module:ident )* } )? - $name:ident: $module:ident::{ + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { $other_module:ident $( $modules:ident )* } - $( $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident )* - })* + $( $rest:tt )* ) => { $crate::__decl_runtime_metadata!( $runtime; - $( $parsed_modules { $( $withs )* } )*; + { $( $parsed )* }; { leading_module: $( $( $leading_module )* )? $other_module } - $name: $module::{ + $name: $module:: $( < $module_instance >:: )? { $( $modules )* } - $( - $rest_name: $rest_module::{ - $( $rest_modules )* - } - )* + $( $rest )* ); }; // does not contain Module : skip ( $runtime:ident; - $( $parsed_modules:ident { $( $withs:ident )* } )*; + { $( $parsed:tt )* }; $( { leading_module: $( $leading_module:ident )* } )? - $name:ident: $module:ident::{} - $( $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident )* - })* + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {} + $( $rest:tt )* ) => { $crate::__decl_runtime_metadata!( $runtime; - $( $parsed_modules { $( $withs )* } )*; - $( - $rest_name: $rest_module::{ - $( $rest_modules )* - } - )* + { $( $parsed )* }; + $( $rest )* ); }; // end of decl ( $runtime:ident; - $( $parsed_modules:ident { $( $withs:ident )* } )*; + { $( $parsed_modules:ident $( < $module_instance:ident > )? { $( $withs:ident )* } )* }; ) => { $crate::impl_runtime_metadata!( for $runtime with modules - $( $parsed_modules::Module with $( $withs )* , )* + $( $parsed_modules::Module $( < $module_instance > )? with $( $withs )* , )* ); } } - /// A private macro that generates Log enum for the runtime. See impl_outer_log macro. #[macro_export] #[doc(hidden)] @@ -806,80 +696,65 @@ macro_rules! __decl_outer_log { ( $runtime:ident; $log_internal:ident <$( $log_genarg:ty ),+>; - $( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*; - $name:ident: $module:ident::{ - Log ( $( $args:ident ),* ) $(, $modules:ident $( ( $( $modules_args:ident )* ) )* )* + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? { + Log ( $( $args:ident )* ) $( $modules:ident $( ( $( $modules_args:ident )* ) )* )* } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),* - })*; + $( $rest:tt )* ) => { $crate::__decl_outer_log!( $runtime; $log_internal < $( $log_genarg ),* >; - $( $parsed_modules ( $( $parsed_args ),* ), )* $module ( $( $args ),* ); - $( - $rest_name: $rest_module::{ - $( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),* - } - ),*; + { $( $parsed )* $module $(<$module_instance>)? ( $( $args )* )}; + $( $rest )* ); }; ( $runtime:ident; $log_internal:ident <$( $log_genarg:ty ),+>; - $( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*; - $name:ident: $module:ident::{ - $ignore:ident $( ( $( $args_ignore:ident ),* ) )* - $(, $modules:ident $( ( $( $modules_args:ident ),* ) )* )* + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? { + $ignore:ident $( ( $( $args_ignore:ident )* ) )* + $( $modules:ident $( ( $( $modules_args:ident )* ) )* )* } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),* - })*; + $( $rest:tt )* ) => { $crate::__decl_outer_log!( $runtime; $log_internal < $( $log_genarg ),* >; - $( $parsed_modules ( $( $parsed_args ),* ) ),*; - $name: $module::{ $( $modules $( ( $( $modules_args ),* ) )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),* - } - )*; + { $( $parsed )* }; + $name: $module:: $(<$module_instance>::)? { $( $modules $( ( $( $modules_args )* ) )* )* } + $( $rest )* ); }; ( $runtime:ident; $log_internal:ident <$( $log_genarg:ty ),+>; - $( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),* - })*; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? {} + $( $rest:tt )* ) => { $crate::__decl_outer_log!( $runtime; $log_internal < $( $log_genarg ),* >; - $( $parsed_modules ( $( $parsed_args ),* ) ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),* - } - ),*; + { $( $parsed )* }; + $( $rest )* ); }; ( $runtime:ident; $log_internal:ident <$( $log_genarg:ty ),+>; - $( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*; - ; + { $( + $parsed_modules:ident $(< $parsed_instance:ident >)? ( $( $parsed_args:ident )* ) + )* }; ) => { - $crate::runtime_primitives::impl_outer_log!( - pub enum Log($log_internal: DigestItem<$( $log_genarg ),*>) for $runtime { - $( $parsed_modules ( $( $parsed_args ),* ) ),* - } - ); + $crate::paste::item! { + $crate::runtime_primitives::impl_outer_log!( + pub enum Log($log_internal: DigestItem<$( $log_genarg ),*>) for $runtime { + $( [< $parsed_modules $(_ $parsed_instance)? >] $(< $parsed_modules::$parsed_instance >)? ( $( $parsed_args ),* ) ),* + } + ); + } }; } @@ -889,93 +764,57 @@ macro_rules! __decl_outer_log { macro_rules! __decl_outer_config { ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - $name:ident: $module:ident::{ - Config $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - $crate::__decl_outer_config!( - $runtime; - $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*, )* $module::$name; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; - ); - }; - ( - $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - $name:ident: $module:ident::{ - Config $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { + Config $(< $config_generic:ident $(, $config_instance:path)?>)? $(, $modules:ident $( <$modules_generic:ident $(, $modules_instance:path)?> )* )* + }, + $( $rest:tt )* ) => { $crate::__decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*, )* $module::$name; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { + $( $parsed )* + $module::$name $( $module_instance )? $(<$config_generic $(, $config_instance)?>)?, + }; + $( $rest )* ); }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - $name:ident: $module:ident::{ - $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { + $ingore:ident $( <$ignor:ident $(, $ignore_instance:path)?> )* $(, $modules:ident $( <$modules_generic:ident $(, $modules_instance:path)?> )* )* + }, + $( $rest:tt )* ) => { $crate::__decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - )*; + { $( $parsed )* }; + $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* }, + $( $rest )* ); }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {}, + $( $rest:tt )* ) => { $crate::__decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { $( $parsed )* }; + $( $rest )* ); }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - ; + {$( $parsed_modules:ident :: $parsed_name:ident $( $parsed_instance:ident )? $( < $parsed_generic:ident $(, $parsed_instance_full_path:path)? > )* ,)* }; ) => { $crate::paste::item! { $crate::runtime_primitives::impl_outer_config!( pub struct GenesisConfig for $runtime { $( - [< $parsed_name Config >] => $parsed_modules $( < $parsed_generic > )*, + [< $parsed_name Config >] => [< $parsed_modules $( _ $parsed_instance)? >] $( < $parsed_generic $(, $parsed_instance_full_path)? > )*, )* } ); @@ -1097,3 +936,14 @@ macro_rules! __decl_outer_inherent { ); }; } + +#[macro_export] +#[doc(hidden)] +// Those imports are used by event, config, origin and log macros to get access to its inner type +macro_rules! __decl_instance_import { + ( $( $module:ident <$instance:ident> )* ) => { + $crate::paste::item! { + $(use $module as [< $module _ $instance >];)* + } + }; +} diff --git a/srml/support/src/storage/generator.rs b/srml/support/src/storage/generator.rs index e9c38e872c1f1fddd7a7210ccf61275bbc8f5bf0..97bfc6dc200ec2d1b1d1cdb1ca26d30873a34cb5 100644 --- a/srml/support/src/storage/generator.rs +++ b/srml/support/src/storage/generator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -48,6 +48,8 @@ use crate::codec; use crate::rstd::vec::Vec; +#[cfg(feature = "std")] +use crate::storage::unhashed::generator::UnhashedStorage; #[doc(hidden)] pub use crate::rstd::borrow::Borrow; #[doc(hidden)] @@ -101,20 +103,19 @@ pub trait Storage { #[cfg(feature = "std")] impl Storage for (crate::rstd::cell::RefCell<&mut sr_primitives::StorageOverlay>, PhantomData) { fn exists(&self, key: &[u8]) -> bool { - self.0.borrow().contains_key(S::hash(key).as_ref()) + UnhashedStorage::exists(self, &S::hash(key)) } fn get(&self, key: &[u8]) -> Option { - self.0.borrow().get(S::hash(key).as_ref()) - .map(|x| codec::Decode::decode(&mut x.as_slice()).expect("Unable to decode expected type.")) + UnhashedStorage::get(self, &S::hash(key)) } fn put(&self, key: &[u8], val: &T) { - self.0.borrow_mut().insert(S::hash(key).to_vec(), codec::Encode::encode(val)); + UnhashedStorage::put(self, &S::hash(key), val) } fn kill(&self, key: &[u8]) { - self.0.borrow_mut().remove(S::hash(key).as_ref()); + UnhashedStorage::kill(self, &S::hash(key)) } } @@ -226,7 +227,7 @@ pub trait EnumerableStorageMap: StorageMap(storage: &'a S) -> Box + 'a> where K: 'a, V: 'a; } -// FIXME #1466 Remove this in favour of `decl_storage` macro. +// FIXME #1466 Remove this in favor of `decl_storage` macro. /// Declares strongly-typed wrappers around codec-compatible types in storage. #[macro_export] macro_rules! storage_items { @@ -667,6 +668,12 @@ mod tests { GETMAPU32MYDEF get(map_u32_getter_mydef): map u32 => String = "map".into(); pub PUBGETMAPU32MYDEF get(pub_map_u32_getter_mydef): map u32 => String = "pubmap".into(); + // linked map + LINKEDMAPU32 : linked_map u32 => Option; + pub PUBLINKEDMAPU32MYDEF : linked_map u32 => Option = Some("hello".into()); + GETLINKEDMAPU32 get(linked_map_u32_getter): linked_map u32 => String; + pub PUBGETLINKEDMAPU32MYDEF get(pub_linked_map_u32_getter_mydef): linked_map u32 => String = "pubmap".into(); + COMPLEXTYPE1: ::std::vec::Vec<::Origin>; COMPLEXTYPE2: (Vec)>>, u32); COMPLEXTYPE3: ([u32;25]); @@ -806,8 +813,10 @@ mod tests { StorageFunctionMetadata { name: DecodeDifferent::Encode("MAPU32"), modifier: StorageFunctionModifier::Optional, - ty: StorageFunctionType::Map{ - key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructMAPU32(PhantomData::)) @@ -817,8 +826,10 @@ mod tests { StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBMAPU32"), modifier: StorageFunctionModifier::Optional, - ty: StorageFunctionType::Map{ - key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBMAPU32(PhantomData::)) @@ -828,8 +839,10 @@ mod tests { StorageFunctionMetadata { name: DecodeDifferent::Encode("MAPU32MYDEF"), modifier: StorageFunctionModifier::Optional, - ty: StorageFunctionType::Map{ - key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructMAPU32MYDEF(PhantomData::)) @@ -839,8 +852,10 @@ mod tests { StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBMAPU32MYDEF"), modifier: StorageFunctionModifier::Optional, - ty: StorageFunctionType::Map{ - key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBMAPU32MYDEF(PhantomData::)) @@ -850,8 +865,10 @@ mod tests { StorageFunctionMetadata { name: DecodeDifferent::Encode("GETMAPU32"), modifier: StorageFunctionModifier::Default, - ty: StorageFunctionType::Map{ - key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETMAPU32(PhantomData::)) @@ -861,8 +878,10 @@ mod tests { StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBGETMAPU32"), modifier: StorageFunctionModifier::Default, - ty: StorageFunctionType::Map{ - key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETMAPU32(PhantomData::)) @@ -872,8 +891,10 @@ mod tests { StorageFunctionMetadata { name: DecodeDifferent::Encode("GETMAPU32MYDEF"), modifier: StorageFunctionModifier::Default, - ty: StorageFunctionType::Map{ - key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETMAPU32MYDEF(PhantomData::)) @@ -883,14 +904,68 @@ mod tests { StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBGETMAPU32MYDEF"), modifier: StorageFunctionModifier::Default, - ty: StorageFunctionType::Map{ - key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETMAPU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("LINKEDMAPU32"), + modifier: StorageFunctionModifier::Optional, + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructLINKEDMAPU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("PUBLINKEDMAPU32MYDEF"), + modifier: StorageFunctionModifier::Optional, + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBLINKEDMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("GETLINKEDMAPU32"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETLINKEDMAPU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("PUBGETLINKEDMAPU32MYDEF"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::Map { + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETLINKEDMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, StorageFunctionMetadata { name: DecodeDifferent::Encode("COMPLEXTYPE1"), modifier: StorageFunctionModifier::Default, diff --git a/srml/support/src/storage/mod.rs b/srml/support/src/storage/mod.rs index 6b6e68be19aae2d810a51d213f5d61d4d23217d6..b1b8766b9028a466f30d6b7440be20b01a3b84af 100644 --- a/srml/support/src/storage/mod.rs +++ b/srml/support/src/storage/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ use crate::codec::{Codec, Encode, Decode, KeyedVec, Input}; #[macro_use] pub mod generator; +pub mod unhashed; struct IncrementalInput<'a> { key: &'a [u8], @@ -38,86 +39,91 @@ impl<'a> Input for IncrementalInput<'a> { } } - /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. +struct IncrementalChildInput<'a> { + storage_key: &'a [u8], + key: &'a [u8], + pos: usize, +} + +impl<'a> Input for IncrementalChildInput<'a> { + fn read(&mut self, into: &mut [u8]) -> usize { + let len = runtime_io::read_child_storage(self.storage_key, self.key, into, self.pos).unwrap_or(0); + let read = crate::rstd::cmp::min(len, into.len()); + self.pos += read; + read + } +} + + +/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(key: &[u8]) -> Option { - let key = twox_128(key); - runtime_io::read_storage(&key[..], &mut [0; 0][..], 0).map(|_| { - let mut input = IncrementalInput { - key: &key[..], - pos: 0, - }; - Decode::decode(&mut input).expect("storage is not null, therefore must be a valid type") - }) + unhashed::get(&twox_128(key)) } /// Return the value of the item in storage under `key`, or the type's default if there is no /// explicit entry. pub fn get_or_default(key: &[u8]) -> T { - get(key).unwrap_or_else(Default::default) + unhashed::get_or_default(&twox_128(key)) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. pub fn get_or(key: &[u8], default_value: T) -> T { - get(key).unwrap_or(default_value) + unhashed::get_or(&twox_128(key), default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. pub fn get_or_else T>(key: &[u8], default_value: F) -> T { - get(key).unwrap_or_else(default_value) + unhashed::get_or_else(&twox_128(key), default_value) } /// Put `value` in storage under `key`. pub fn put(key: &[u8], value: &T) { - value.using_encoded(|slice| runtime_io::set_storage(&twox_128(key)[..], slice)); + unhashed::put(&twox_128(key), value) } /// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. pub fn take(key: &[u8]) -> Option { - let r = get(key); - if r.is_some() { - kill(key); - } - r + unhashed::take(&twox_128(key)) } /// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, /// the default for its type. pub fn take_or_default(key: &[u8]) -> T { - take(key).unwrap_or_else(Default::default) + unhashed::take_or_default(&twox_128(key)) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. Ensure there is no explicit entry on return. pub fn take_or(key: &[u8], default_value: T) -> T { - take(key).unwrap_or(default_value) + unhashed::take_or(&twox_128(key), default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. Ensure there is no explicit entry on return. pub fn take_or_else T>(key: &[u8], default_value: F) -> T { - take(key).unwrap_or_else(default_value) + unhashed::take_or_else(&twox_128(key), default_value) } /// Check to see if `key` has an explicit entry in storage. pub fn exists(key: &[u8]) -> bool { - runtime_io::exists_storage(&twox_128(key)[..]) + unhashed::exists(&twox_128(key)) } /// Ensure `key` has no explicit entry in storage. pub fn kill(key: &[u8]) { - runtime_io::clear_storage(&twox_128(key)[..]); + unhashed::kill(&twox_128(key)) } /// Get a Vec of bytes from storage. pub fn get_raw(key: &[u8]) -> Option> { - runtime_io::storage(&twox_128(key)[..]) + unhashed::get_raw(&twox_128(key)) } /// Put a raw byte slice into storage. pub fn put_raw(key: &[u8], value: &[u8]) { - runtime_io::set_storage(&twox_128(key)[..], value) + unhashed::put_raw(&twox_128(key), value) } /// The underlying runtime storage. @@ -125,27 +131,58 @@ pub struct RuntimeStorage; impl crate::GenericStorage for RuntimeStorage { fn exists(&self, key: &[u8]) -> bool { - super::storage::exists(key) + exists(key) } /// Load the bytes of a key from storage. Can panic if the type is incorrect. fn get(&self, key: &[u8]) -> Option { - super::storage::get(key) + get(key) } /// Put a value in under a key. fn put(&self, key: &[u8], val: &T) { - super::storage::put(key, val) + put(key, val) } /// Remove the bytes of a key from storage. fn kill(&self, key: &[u8]) { - super::storage::kill(key) + kill(key) } /// Take a value from storage, deleting it after reading. fn take(&self, key: &[u8]) -> Option { - super::storage::take(key) + take(key) + } +} + +impl crate::GenericUnhashedStorage for RuntimeStorage { + fn exists(&self, key: &[u8]) -> bool { + unhashed::exists(key) + } + + /// Load the bytes of a key from storage. Can panic if the type is incorrect. + fn get(&self, key: &[u8]) -> Option { + unhashed::get(key) + } + + /// Put a value in under a key. + fn put(&self, key: &[u8], val: &T) { + unhashed::put(key, val) + } + + /// Remove the bytes of a key from storage. + fn kill(&self, key: &[u8]) { + unhashed::kill(key) + } + + /// Remove the bytes of a key from storage. + fn kill_prefix(&self, prefix: &[u8]) { + unhashed::kill_prefix(prefix) + } + + /// Take a value from storage, deleting it after reading. + fn take(&self, key: &[u8]) -> Option { + unhashed::take(key) } } @@ -358,6 +395,109 @@ impl EnumerableStorageMap for U where U: generator: } } +/// An implementation of a map with a two keys. +/// +/// It provides an important ability to efficiently remove all entries +/// that have a common first key. +/// +/// # Mapping of keys to a storage path +/// +/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. +/// The first part is a hash of a concatenation of the `PREFIX` and `Key1`. And the second part +/// is a hash of a `Key2`. +/// +/// /!\ be careful while choosing the Hash, indeed malicious could craft second keys to lower the trie. +pub trait StorageDoubleMap { + /// The type that get/take returns. + type Query; + + /// Get the prefix key in storage. + fn prefix() -> &'static [u8]; + + /// Get the storage key used to fetch a value corresponding to a specific key. + fn key_for, KArg2: Borrow>(k1: KArg1, k2: KArg2) -> Vec; + + /// Get the storage prefix used to fetch keys corresponding to a specific key1. + fn prefix_for>(k1: KArg1) -> Vec; + + /// true if the value is defined in storage. + fn exists, KArg2: Borrow>(k1: KArg1, k2: KArg2) -> bool; + + /// Load the value associated with the given key from the map. + fn get, KArg2: Borrow>(k1: KArg1, k2: KArg2) -> Self::Query; + + /// Take the value under a key. + fn take, KArg2: Borrow>(k1: KArg1, k2: KArg2) -> Self::Query; + + /// Store a value to be associated with the given key from the map. + fn insert, KArg2: Borrow, VArg: Borrow>(k1: KArg1, k2: KArg2, val: VArg); + + /// Remove the value under a key. + fn remove, KArg2: Borrow>(k1: KArg1, k2: KArg2); + + /// Removes all entries that shares the `k1` as the first key. + fn remove_prefix>(k1: KArg1); + + /// Mutate the value under a key. + fn mutate(k1: KArg1, k2: KArg2, f: F) -> R + where + KArg1: Borrow, + KArg2: Borrow, + F: FnOnce(&mut Self::Query) -> R; +} + +impl StorageDoubleMap for U +where + U: unhashed::generator::StorageDoubleMap +{ + type Query = U::Query; + + fn prefix() -> &'static [u8] { + >::prefix() + } + + fn key_for, KArg2: Borrow>(k1: KArg1, k2: KArg2) -> Vec { + >::key_for(k1.borrow(), k2.borrow()) + } + + fn prefix_for>(k1: KArg1) -> Vec { + >::prefix_for(k1.borrow()) + } + + fn exists, KArg2: Borrow>(k1: KArg1, k2: KArg2) -> bool { + U::exists(k1.borrow(), k2.borrow(), &RuntimeStorage) + } + + fn get, KArg2: Borrow>(k1: KArg1, k2: KArg2) -> Self::Query { + U::get(k1.borrow(), k2.borrow(), &RuntimeStorage) + } + + fn take, KArg2: Borrow>(k1: KArg1, k2: KArg2) -> Self::Query { + U::take(k1.borrow(), k2.borrow(), &RuntimeStorage) + } + + fn insert, KArg2: Borrow, VArg: Borrow>(k1: KArg1, k2: KArg2, val: VArg) { + U::insert(k1.borrow(), k2.borrow(), val.borrow(), &RuntimeStorage) + } + + fn remove, KArg2: Borrow>(k1: KArg1, k2: KArg2) { + U::remove(k1.borrow(), k2.borrow(), &RuntimeStorage) + } + + fn remove_prefix>(k1: KArg1) { + U::remove_prefix(k1.borrow(), &RuntimeStorage) + } + + fn mutate(k1: KArg1, k2: KArg2, f: F) -> R + where + KArg1: Borrow, + KArg2: Borrow, + F: FnOnce(&mut Self::Query) -> R + { + U::mutate(k1.borrow(), k2.borrow(), f, &RuntimeStorage) + } +} + /// A trait to conveniently store a vector of storable data. pub trait StorageVec { type Item: Default + Sized + Codec; @@ -417,14 +557,19 @@ pub trait StorageVec { } } -pub mod unhashed { - use crate::rstd::borrow::Borrow; - use super::{runtime_io, Codec, Decode, KeyedVec, Vec, IncrementalInput}; +/// child storage NOTE could replace unhashed by having only one kind of storage (root being null storage +/// key (storage_key can become Option<&[u8]>). +/// This module is a currently only a variant of unhashed with additional `storage_key`. +/// Note that `storage_key` must be unique and strong (strong in the sense of being long enough to +/// avoid collision from a resistant hash function (which unique implies)). +pub mod child { + use super::{runtime_io, Codec, Decode, Vec, IncrementalChildInput}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. - pub fn get(key: &[u8]) -> Option { - runtime_io::read_storage(key, &mut [0; 0][..], 0).map(|_| { - let mut input = IncrementalInput { + pub fn get(storage_key: &[u8], key: &[u8]) -> Option { + runtime_io::read_child_storage(storage_key, key, &mut [0; 0][..], 0).map(|_| { + let mut input = IncrementalChildInput { + storage_key, key, pos: 0, }; @@ -434,130 +579,80 @@ pub mod unhashed { /// Return the value of the item in storage under `key`, or the type's default if there is no /// explicit entry. - pub fn get_or_default(key: &[u8]) -> T { - get(key).unwrap_or_else(Default::default) + pub fn get_or_default(storage_key: &[u8], key: &[u8]) -> T { + get(storage_key, key).unwrap_or_else(Default::default) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. - pub fn get_or(key: &[u8], default_value: T) -> T { - get(key).unwrap_or(default_value) + pub fn get_or(storage_key: &[u8], key: &[u8], default_value: T) -> T { + get(storage_key, key).unwrap_or(default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. - pub fn get_or_else T>(key: &[u8], default_value: F) -> T { - get(key).unwrap_or_else(default_value) + pub fn get_or_else T>(storage_key: &[u8], key: &[u8], default_value: F) -> T { + get(storage_key, key).unwrap_or_else(default_value) } /// Put `value` in storage under `key`. - pub fn put(key: &[u8], value: &T) { - value.using_encoded(|slice| runtime_io::set_storage(key, slice)); + pub fn put(storage_key: &[u8], key: &[u8], value: &T) { + value.using_encoded(|slice| runtime_io::set_child_storage(storage_key, key, slice)); } /// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. - pub fn take(key: &[u8]) -> Option { - let r = get(key); + pub fn take(storage_key: &[u8], key: &[u8]) -> Option { + let r = get(storage_key, key); if r.is_some() { - kill(key); + kill(storage_key, key); } r } /// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, /// the default for its type. - pub fn take_or_default(key: &[u8]) -> T { - take(key).unwrap_or_else(Default::default) + pub fn take_or_default(storage_key: &[u8], key: &[u8]) -> T { + take(storage_key, key).unwrap_or_else(Default::default) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. Ensure there is no explicit entry on return. - pub fn take_or(key: &[u8], default_value: T) -> T { - take(key).unwrap_or(default_value) + pub fn take_or(storage_key: &[u8],key: &[u8], default_value: T) -> T { + take(storage_key, key).unwrap_or(default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. Ensure there is no explicit entry on return. - pub fn take_or_else T>(key: &[u8], default_value: F) -> T { - take(key).unwrap_or_else(default_value) + pub fn take_or_else T>(storage_key: &[u8], key: &[u8], default_value: F) -> T { + take(storage_key, key).unwrap_or_else(default_value) } /// Check to see if `key` has an explicit entry in storage. - pub fn exists(key: &[u8]) -> bool { - runtime_io::read_storage(key, &mut [0;0][..], 0).is_some() + pub fn exists(storage_key: &[u8], key: &[u8]) -> bool { + runtime_io::read_child_storage(storage_key, key, &mut [0;0][..], 0).is_some() } - /// Ensure `key` has no explicit entry in storage. - pub fn kill(key: &[u8]) { - runtime_io::clear_storage(key); + /// Remove all `storage_key` key/values + pub fn kill_storage(storage_key: &[u8]) { + runtime_io::kill_child_storage(storage_key) } - /// Ensure keys with the given `prefix` have no entries in storage. - pub fn kill_prefix(prefix: &[u8]) { - runtime_io::clear_prefix(prefix); + /// Ensure `key` has no explicit entry in storage. + pub fn kill(storage_key: &[u8], key: &[u8]) { + runtime_io::clear_child_storage(storage_key, key); } /// Get a Vec of bytes from storage. - pub fn get_raw(key: &[u8]) -> Option> { - runtime_io::storage(key) + pub fn get_raw(storage_key: &[u8], key: &[u8]) -> Option> { + runtime_io::child_storage(storage_key, key) } /// Put a raw byte slice into storage. - pub fn put_raw(key: &[u8], value: &[u8]) { - runtime_io::set_storage(key, value) + pub fn put_raw(storage_key: &[u8], key: &[u8], value: &[u8]) { + runtime_io::set_child_storage(storage_key, key, value) } - /// A trait to conveniently store a vector of storable data. - pub trait StorageVec { - type Item: Default + Sized + Codec; - const PREFIX: &'static [u8]; - - /// Get the current set of items. - fn items() -> Vec { - (0..Self::count()).into_iter().map(Self::item).collect() - } - - /// Set the current set of items. - fn set_items(items: I) - where - I: IntoIterator, - T: Borrow, - { - let mut count: u32 = 0; - - for i in items.into_iter() { - put(&count.to_keyed_vec(Self::PREFIX), i.borrow()); - count = count.checked_add(1).expect("exceeded runtime storage capacity"); - } - - Self::set_count(count); - } - - fn set_item(index: u32, item: &Self::Item) { - if index < Self::count() { - put(&index.to_keyed_vec(Self::PREFIX), item); - } - } - - fn clear_item(index: u32) { - if index < Self::count() { - kill(&index.to_keyed_vec(Self::PREFIX)); - } - } - - fn item(index: u32) -> Self::Item { - get_or_default(&index.to_keyed_vec(Self::PREFIX)) - } - - fn set_count(count: u32) { - (count..Self::count()).for_each(Self::clear_item); - put(&b"len".to_keyed_vec(Self::PREFIX), &count); - } - - fn count() -> u32 { - get_or_default(&b"len".to_keyed_vec(Self::PREFIX)) - } - } + pub use super::unhashed::StorageVec; } #[cfg(test)] diff --git a/srml/support/src/storage/unhashed/generator.rs b/srml/support/src/storage/unhashed/generator.rs new file mode 100644 index 0000000000000000000000000000000000000000..2b046013bb9445da68348ca10cd0de2cdfe6419c --- /dev/null +++ b/srml/support/src/storage/unhashed/generator.rs @@ -0,0 +1,144 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::codec; +use runtime_io::twox_128; +use crate::rstd::vec::Vec; + +/// Abstraction around storage with unhashed access. +pub trait UnhashedStorage { + /// true if the key exists in storage. + fn exists(&self, key: &[u8]) -> bool; + + /// Load the bytes of a key from storage. Can panic if the type is incorrect. + fn get(&self, key: &[u8]) -> Option; + + /// Load the bytes of a key from storage. Can panic if the type is incorrect. Will panic if + /// it's not there. + fn require(&self, key: &[u8]) -> T { self.get(key).expect("Required values must be in storage") } + + /// Load the bytes of a key from storage. Can panic if the type is incorrect. The type's + /// default is returned if it's not there. + fn get_or_default(&self, key: &[u8]) -> T { self.get(key).unwrap_or_default() } + + /// Put a value in under a key. + fn put(&self, key: &[u8], val: &T); + + /// Remove the bytes of a key from storage. + fn kill(&self, key: &[u8]); + + /// Remove the bytes of a key from storage. + fn kill_prefix(&self, prefix: &[u8]); + + /// Take a value from storage, deleting it after reading. + fn take(&self, key: &[u8]) -> Option { + let value = self.get(key); + self.kill(key); + value + } + + /// Take a value from storage, deleting it after reading. + fn take_or_panic(&self, key: &[u8]) -> T { self.take(key).expect("Required values must be in storage") } + + /// Take a value from storage, deleting it after reading. + fn take_or_default(&self, key: &[u8]) -> T { self.take(key).unwrap_or_default() } +} + +// We use a construct like this during when genesis storage is being built. +#[cfg(feature = "std")] +impl UnhashedStorage for (crate::rstd::cell::RefCell<&mut sr_primitives::StorageOverlay>, H) { + fn exists(&self, key: &[u8]) -> bool { + self.0.borrow().contains_key(key) + } + + fn get(&self, key: &[u8]) -> Option { + self.0.borrow().get(key) + .map(|x| codec::Decode::decode(&mut x.as_slice()).expect("Unable to decode expected type.")) + } + + fn put(&self, key: &[u8], val: &T) { + self.0.borrow_mut().insert(key.to_vec(), codec::Encode::encode(val)); + } + + fn kill(&self, key: &[u8]) { + self.0.borrow_mut().remove(key); + } + + fn kill_prefix(&self, prefix: &[u8]) { + self.0.borrow_mut().retain(|key, _| { + !key.starts_with(prefix) + }) + } +} + +/// An implementation of a map with a two keys. +/// +/// It provides an important ability to efficiently remove all entries +/// that have a common first key. +/// +/// # Mapping of keys to a storage path +/// +/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. +/// The first part is a hash of a concatenation of the `PREFIX` and `Key1`. And the second part +/// is a hash of a `Key2`. +/// +/// /!\ be careful while choosing the Hash, indeed malicious could craft second keys to lower the trie. +pub trait StorageDoubleMap { + /// The type that get/take returns. + type Query; + + /// Get the prefix key in storage. + fn prefix() -> &'static [u8]; + + /// Get the storage key used to fetch a value corresponding to a specific key. + fn key_for(k1: &K1, k2: &K2) -> Vec; + + /// Get the storage prefix used to fetch keys corresponding to a specific key1. + fn prefix_for(k1: &K1) -> Vec { + let mut key = Self::prefix().to_vec(); + codec::Encode::encode_to(k1, &mut key); + twox_128(&key).to_vec() + } + + /// true if the value is defined in storage. + fn exists(k1: &K1, k2: &K2, storage: &S) -> bool { + storage.exists(&Self::key_for(k1, k2)) + } + + /// Load the value associated with the given key from the map. + fn get(k1: &K1, k2: &K2, storage: &S) -> Self::Query; + + /// Take the value under a key. + fn take(k1: &K1, k2: &K2, storage: &S) -> Self::Query; + + /// Store a value to be associated with the given key from the map. + fn insert(k1: &K1, k2: &K2, val: &V, storage: &S) { + storage.put(&Self::key_for(k1, k2), val); + } + + /// Remove the value under a key. + fn remove(k1: &K1, k2: &K2, storage: &S) { + storage.kill(&Self::key_for(k1, k2)); + } + + /// Removes all entries that shares the `k1` as the first key. + fn remove_prefix(k1: &K1, storage: &S) { + storage.kill_prefix(&Self::prefix_for(k1)); + } + + /// Mutate the value under a key. + fn mutate R, S: UnhashedStorage>(k1: &K1, k2: &K2, f: F, storage: &S) -> R; +} diff --git a/srml/support/src/storage/unhashed/mod.rs b/srml/support/src/storage/unhashed/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..225c6756b80de3788fa7faeda73533a78899e41b --- /dev/null +++ b/srml/support/src/storage/unhashed/mod.rs @@ -0,0 +1,160 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Operation on unhashed runtime storage + +use crate::rstd::borrow::Borrow; +use super::{runtime_io, Codec, Encode, Decode, KeyedVec, Vec, IncrementalInput}; + +pub mod generator; + +/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. +pub fn get(key: &[u8]) -> Option { + runtime_io::read_storage(key, &mut [0; 0][..], 0).map(|_| { + let mut input = IncrementalInput { + key, + pos: 0, + }; + Decode::decode(&mut input).expect("storage is not null, therefore must be a valid type") + }) +} + +/// Return the value of the item in storage under `key`, or the type's default if there is no +/// explicit entry. +pub fn get_or_default(key: &[u8]) -> T { + get(key).unwrap_or_else(Default::default) +} + +/// Return the value of the item in storage under `key`, or `default_value` if there is no +/// explicit entry. +pub fn get_or(key: &[u8], default_value: T) -> T { + get(key).unwrap_or(default_value) +} + +/// Return the value of the item in storage under `key`, or `default_value()` if there is no +/// explicit entry. +pub fn get_or_else T>(key: &[u8], default_value: F) -> T { + get(key).unwrap_or_else(default_value) +} + +/// Put `value` in storage under `key`. +pub fn put(key: &[u8], value: &T) { + value.using_encoded(|slice| runtime_io::set_storage(key, slice)); +} + +/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. +pub fn take(key: &[u8]) -> Option { + let r = get(key); + if r.is_some() { + kill(key); + } + r +} + +/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, +/// the default for its type. +pub fn take_or_default(key: &[u8]) -> T { + take(key).unwrap_or_else(Default::default) +} + +/// Return the value of the item in storage under `key`, or `default_value` if there is no +/// explicit entry. Ensure there is no explicit entry on return. +pub fn take_or(key: &[u8], default_value: T) -> T { + take(key).unwrap_or(default_value) +} + +/// Return the value of the item in storage under `key`, or `default_value()` if there is no +/// explicit entry. Ensure there is no explicit entry on return. +pub fn take_or_else T>(key: &[u8], default_value: F) -> T { + take(key).unwrap_or_else(default_value) +} + +/// Check to see if `key` has an explicit entry in storage. +pub fn exists(key: &[u8]) -> bool { + runtime_io::read_storage(key, &mut [0;0][..], 0).is_some() +} + +/// Ensure `key` has no explicit entry in storage. +pub fn kill(key: &[u8]) { + runtime_io::clear_storage(key); +} + +/// Ensure keys with the given `prefix` have no entries in storage. +pub fn kill_prefix(prefix: &[u8]) { + runtime_io::clear_prefix(prefix); +} + +/// Get a Vec of bytes from storage. +pub fn get_raw(key: &[u8]) -> Option> { + runtime_io::storage(key) +} + +/// Put a raw byte slice into storage. +pub fn put_raw(key: &[u8], value: &[u8]) { + runtime_io::set_storage(key, value) +} + +/// A trait to conveniently store a vector of storable data. +pub trait StorageVec { + type Item: Default + Sized + Codec; + const PREFIX: &'static [u8]; + + /// Get the current set of items. + fn items() -> Vec { + (0..Self::count()).into_iter().map(Self::item).collect() + } + + /// Set the current set of items. + fn set_items(items: I) + where + I: IntoIterator, + T: Borrow, + { + let mut count: u32 = 0; + + for i in items.into_iter() { + put(&count.to_keyed_vec(Self::PREFIX), i.borrow()); + count = count.checked_add(1).expect("exceeded runtime storage capacity"); + } + + Self::set_count(count); + } + + fn set_item(index: u32, item: &Self::Item) { + if index < Self::count() { + put(&index.to_keyed_vec(Self::PREFIX), item); + } + } + + fn clear_item(index: u32) { + if index < Self::count() { + kill(&index.to_keyed_vec(Self::PREFIX)); + } + } + + fn item(index: u32) -> Self::Item { + get_or_default(&index.to_keyed_vec(Self::PREFIX)) + } + + fn set_count(count: u32) { + (count..Self::count()).for_each(Self::clear_item); + put(&b"len".to_keyed_vec(Self::PREFIX), &count); + } + + fn count() -> u32 { + get_or_default(&b"len".to_keyed_vec(Self::PREFIX)) + } +} diff --git a/srml/support/src/traits.rs b/srml/support/src/traits.rs index 81d0239e5cdc07b179bd381b9f4133c95e1c1709..6f0435a77a01d36160fa9ace1e4156bb8765e373 100644 --- a/srml/support/src/traits.rs +++ b/srml/support/src/traits.rs @@ -17,7 +17,7 @@ //! Traits for SRML use crate::rstd::result; -use crate::codec::Codec; +use crate::codec::{Codec, Encode, Decode}; use crate::runtime_primitives::traits::{ MaybeSerializeDebug, SimpleArithmetic, As }; @@ -53,241 +53,422 @@ impl OnDilution for () { fn on_dilution(_minted: Balance, _portion: Balance) {} } -/// Determinator for whether a given account is able to use its **free** balance. -/// -/// By convention, `ensure_account_liquid` overrules `ensure_account_can_withdraw`. If a -/// caller gets `Ok` from the former, then they do not need to call the latter. -/// -/// This implies that if you define the latter away from its default of replicating the -/// former, then ensure you also redefine the former to return an `Err` in corresponding -/// situations, otherwise you'll end up giving inconsistent information. -// TODO: Remove in favour of explicit functionality in balances module: #1896 -pub trait EnsureAccountLiquid { - /// Ensures that the account is completely unencumbered. If this is `Ok` then there's no need to - /// check any other items. If it's an `Err`, then you must use one pair of the other items. - fn ensure_account_liquid(who: &AccountId) -> result::Result<(), &'static str>; +/// Outcome of a balance update. +pub enum UpdateBalanceOutcome { + /// Account balance was simply updated. + Updated, + /// The update led to killing the account. + AccountKilled, +} - /// Returns `Ok` iff the account is able to make a withdrawal of the given amount - /// for the given reason. - /// - /// `Err(...)` with the reason why not otherwise. - /// - /// By default this just reflects the results of `ensure_account_liquid`. - /// - /// @warning If you redefine this away from the default, ensure that you define - /// `ensure_account_liquid` in accordance. - fn ensure_account_can_withdraw( - who: &AccountId, - _amount: Balance, - _reason: WithdrawReason - ) -> result::Result<(), &'static str> { - Self::ensure_account_liquid(who) - } +/// Simple trait designed for hooking into a transaction payment. +/// +/// It operates over a single generic `AccountId` type. +pub trait MakePayment { + /// Make transaction payment from `who` for an extrinsic of encoded length + /// `encoded_len` bytes. Return `Ok` iff the payment was successful. + fn make_payment(who: &AccountId, encoded_len: usize) -> Result<(), &'static str>; } -impl< - AccountId, - Balance: Copy, - X: EnsureAccountLiquid, - Y: EnsureAccountLiquid, -> EnsureAccountLiquid for (X, Y) { - fn ensure_account_liquid(who: &AccountId) -> result::Result<(), &'static str> { - X::ensure_account_liquid(who)?; - Y::ensure_account_liquid(who) + +impl MakePayment for () { + fn make_payment(_: &T, _: usize) -> Result<(), &'static str> { Ok(()) } +} + +/// Handler for when some currency "account" decreased in balance for +/// some reason. +/// +/// The only reason at present for an increase would be for validator rewards, but +/// there may be other reasons in the future or for other chains. +/// +/// Reasons for decreases include: +/// +/// - Someone got slashed. +/// - Someone paid for a transaction to be included. +pub trait OnUnbalanced { + /// Handler for some imbalance. Infallible. + fn on_unbalanced(amount: Imbalance); +} + +impl OnUnbalanced for () { + fn on_unbalanced(amount: Imbalance) { drop(amount); } +} + +/// Simple boolean for whether an account needs to be kept in existence. +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum ExistenceRequirement { + /// Operation must not result in the account going out of existence. + KeepAlive, + /// Operation may result in account going out of existence. + AllowDeath, +} + +/// A trait for a not-quite Linear Type that tracks an imbalance. +/// +/// Functions that alter account balances return an object of this trait to +/// express how much account balances have been altered in aggregate. If +/// dropped, the currency system will take some default steps to deal with +/// the imbalance (`balances` module simply reduces or increases its +/// total issuance). Your module should generally handle it in some way, +/// good practice is to do so in a configurable manner using an +/// `OnUnbalanced` type for each situation in which your module needs to +/// handle an imbalance. +/// +/// Imbalances can either be Positive (funds were added somewhere without +/// being subtracted elsewhere - e.g. a reward) or Negative (funds deducted +/// somewhere without an equal and opposite addition - e.g. a slash or +/// system fee payment). +/// +/// Since they are unsigned, the actual type is always Positive or Negative. +/// The trait makes no distinction except to define the `Opposite` type. +/// +/// New instances of zero value can be created (`zero`) and destroyed +/// (`drop_zero`). +/// +/// Existing instances can be `split` and merged either consuming `self` with +/// `merge` or mutating `self` with `subsume`. If the target is an `Option`, +/// then `maybe_merge` and `maybe_subsume` might work better. Instances can +/// also be `offset` with an `Opposite` that is less than or equal to in value. +/// +/// You can always retrieve the raw balance value using `peek`. +#[must_use] +pub trait Imbalance: Sized { + /// The oppositely imbalanced type. They come in pairs. + type Opposite: Imbalance; + + /// The zero imbalance. Can be destroyed with `drop_zero`. + fn zero() -> Self; + + /// Drop an instance cleanly. Only works if its `value()` is zero. + fn drop_zero(self) -> Result<(), Self>; + + /// Consume `self` and return two independent instances; the first + /// is guaranteed to be at most `amount` and the second will be the remainder. + fn split(self, amount: Balance) -> (Self, Self); + + /// Consume `self` and an `other` to return a new instance that combines + /// both. + fn merge(self, other: Self) -> Self; + + /// Consume `self` and maybe an `other` to return a new instance that combines + /// both. + fn maybe_merge(self, other: Option) -> Self { + if let Some(o) = other { + self.merge(o) + } else { + self + } } - fn ensure_account_can_withdraw( - who: &AccountId, - amount: Balance, - reason: WithdrawReason - ) -> result::Result<(), &'static str> { - X::ensure_account_can_withdraw(who, amount, reason)?; - Y::ensure_account_can_withdraw(who, amount, reason) + /// Consume an `other` to mutate `self` into a new instance that combines + /// both. + fn subsume(&mut self, other: Self); + + /// Maybe consume an `other` to mutate `self` into a new instance that combines + /// both. + fn maybe_subsume(&mut self, other: Option) { + if let Some(o) = other { + self.subsume(o) + } } -} -impl EnsureAccountLiquid for () { - fn ensure_account_liquid(_who: &AccountId) -> result::Result<(), &'static str> { Ok(()) } + + /// Consume self and along with an opposite counterpart to return + /// a combined result. + /// + /// Returns `Ok` along with a new instance of `Self` if this instance has a + /// greater value than the `other`. Otherwise returns `Err` with an instance of + /// the `Opposite`. In both cases the value represents the combination of `self` + /// and `other`. + fn offset(self, other: Self::Opposite) -> Result; + + /// The raw value of self. + fn peek(&self) -> Balance; } -/// Outcome of a balance update. -pub enum UpdateBalanceOutcome { - /// Account balance was simply updated. - Updated, - /// The update has led to killing of the account. - AccountKilled, +/// Either a positive or a negative imbalance. +pub enum SignedImbalance>{ + /// A positive imbalance (funds have been created but none destroyed). + Positive(P), + /// A negative imbalance (funds have been destroyed but none created). + Negative(P::Opposite), } -pub trait ArithmeticType { - type Type: SimpleArithmetic + As + As + Codec + Copy + MaybeSerializeDebug + Default; +impl< + P: Imbalance, + N: Imbalance, + B: SimpleArithmetic + As + As + Codec + Copy + MaybeSerializeDebug + Default, +> SignedImbalance { + pub fn zero() -> Self { + SignedImbalance::Positive(P::zero()) + } + + pub fn drop_zero(self) -> Result<(), Self> { + match self { + SignedImbalance::Positive(x) => x.drop_zero().map_err(SignedImbalance::Positive), + SignedImbalance::Negative(x) => x.drop_zero().map_err(SignedImbalance::Negative), + } + } + + /// Consume `self` and an `other` to return a new instance that combines + /// both. + pub fn merge(self, other: Self) -> Self { + match (self, other) { + (SignedImbalance::Positive(one), SignedImbalance::Positive(other)) => + SignedImbalance::Positive(one.merge(other)), + (SignedImbalance::Negative(one), SignedImbalance::Negative(other)) => + SignedImbalance::Negative(one.merge(other)), + (SignedImbalance::Positive(one), SignedImbalance::Negative(other)) => + if one.peek() > other.peek() { + SignedImbalance::Positive(one.offset(other).ok().unwrap_or_else(P::zero)) + } else { + SignedImbalance::Negative(other.offset(one).ok().unwrap_or_else(N::zero)) + }, + (one, other) => other.merge(one), + } + } } /// Abstraction over a fungible assets system. pub trait Currency { /// The balance of an account. - type Balance; + type Balance: SimpleArithmetic + As + As + Codec + Copy + MaybeSerializeDebug + Default; + + /// The opaque token type for an imbalance. This is returned by unbalanced operations + /// and must be dealt with. It may be dropped but cannot be cloned. + type PositiveImbalance: Imbalance; + + /// The opaque token type for an imbalance. This is returned by unbalanced operations + /// and must be dealt with. It may be dropped but cannot be cloned. + type NegativeImbalance: Imbalance; // PUBLIC IMMUTABLES /// The combined balance of `who`. fn total_balance(who: &AccountId) -> Self::Balance; - /// Some result as `slash(who, value)` (but without the side-effects) assuming there are no + /// Same result as `slash(who, value)` (but without the side-effects) assuming there are no /// balance changes in the meantime and only the reserved balance is not taken into account. fn can_slash(who: &AccountId, value: Self::Balance) -> bool; - /// Same result as `reserve(who, value)` (but without the side-effects) assuming there - /// are no balance changes in the meantime. - fn can_reserve(who: &AccountId, value: Self::Balance) -> bool; - - /// The total amount of stake on the system. + /// The total amount of issuance in the system. fn total_issuance() -> Self::Balance; - /// The minimum balance any single account may have. This is equivalent to Balances module's - /// Existential Deposit. + /// The minimum balance any single account may have. This is equivalent to the `Balances` module's + /// `ExistentialDeposit`. fn minimum_balance() -> Self::Balance; /// The 'free' balance of a given account. /// - /// This is the only balance that matters in terms of most operations on tokens. It is - /// alone used to determine the balance when in the contract execution environment. When this + /// This is the only balance that matters in terms of most operations on tokens. It alone + /// is used to determine the balance when in the contract execution environment. When this /// balance falls below the value of `ExistentialDeposit`, then the 'current account' is - /// deleted: specifically `FreeBalance`. Furthermore, `OnFreeBalanceZero` callback - /// is invoked, giving a chance to external modules to cleanup data associated with + /// deleted: specifically `FreeBalance`. Further, the `OnFreeBalanceZero` callback + /// is invoked, giving a chance to external modules to clean up data associated with /// the deleted account. /// /// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. fn free_balance(who: &AccountId) -> Self::Balance; - /// The amount of the balance of a given account that is externally reserved; this can still get - /// slashed, but gets slashed last of all. - /// - /// This balance is a 'reserve' balance that other subsystems use in order to set aside tokens - /// that are still 'owned' by the account holder, but which are suspendable. (This is different - /// and wholly unrelated to the `Bondage` system used in the staking module.) - /// - /// When this balance falls below the value of `ExistentialDeposit`, then this 'reserve account' - /// is deleted: specifically, `ReservedBalance`. + /// Returns `Ok` iff the account is able to make a withdrawal of the given amount + /// for the given reason. Basically, it's just a dry-run of `withdraw`. /// - /// `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets - /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. - fn reserved_balance(who: &AccountId) -> Self::Balance; + /// `Err(...)` with the reason why not otherwise. + fn ensure_can_withdraw( + who: &AccountId, + _amount: Self::Balance, + reason: WithdrawReason, + new_balance: Self::Balance, + ) -> result::Result<(), &'static str>; // PUBLIC MUTABLES (DANGEROUS) + /// Transfer some liquid free balance to another staker. + /// + /// This is a very high-level function. It will ensure all appropriate fees are paid + /// and no imbalance in the system remains. + fn transfer( + source: &AccountId, + dest: &AccountId, + value: Self::Balance, + ) -> result::Result<(), &'static str>; + /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the /// free balance. This function cannot fail. /// + /// The resulting imbalance is the first item of the tuple returned. + /// /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - fn slash(who: &AccountId, value: Self::Balance) -> Option; + /// then a non-zero second item will be returned. + fn slash( + who: &AccountId, + value: Self::Balance + ) -> (Self::NegativeImbalance, Self::Balance); - /// Adds up to `value` to the free balance of `who`. + /// Mints `value` to the free balance of `who`. /// /// If `who` doesn't exist, nothing is done and an Err returned. - fn reward(who: &AccountId, value: Self::Balance) -> result::Result<(), &'static str>; + fn deposit_into_existing( + who: &AccountId, + value: Self::Balance + ) -> result::Result; - /// Adds up to `value` to the free balance of `who`. + /// Removes some free balance from `who` account for `reason` if possible. If `liveness` is `KeepAlive`, + /// then no less than `ExistentialDeposit` must be left remaining. /// - /// If `who` doesn't exist, it is created + /// This checks any locks, vesting, and liquidity requirements. If the removal is not possible, then it + /// returns `Err`. + fn withdraw( + who: &AccountId, + value: Self::Balance, + reason: WithdrawReason, + liveness: ExistenceRequirement, + ) -> result::Result; + + /// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created. /// - /// Returns if the account was successfully updated or update has led to killing of the account. + /// Infallible. + fn deposit_creating( + who: &AccountId, + value: Self::Balance, + ) -> Self::PositiveImbalance; + + /// Ensure an account's free balance equals some value; this will create the account + /// if needed. + /// + /// Returns a signed imbalance and status to indicate if the account was successfully updated or update + /// has led to killing of the account. + fn make_free_balance_be( + who: &AccountId, + balance: Self::Balance, + ) -> ( + SignedImbalance, + UpdateBalanceOutcome, + ); +} + +/// A currency where funds can be reserved from the user. +pub trait ReservableCurrency: Currency { + /// Same result as `reserve(who, value)` (but without the side-effects) assuming there + /// are no balance changes in the meantime. + fn can_reserve(who: &AccountId, value: Self::Balance) -> bool; + + /// Deducts up to `value` from reserved balance of `who`. This function cannot fail. /// - /// NOTE: This assumes that the total stake remains unchanged after this operation. - fn increase_free_balance_creating(who: &AccountId, value: Self::Balance) -> UpdateBalanceOutcome; + /// As much funds up to `value` will be deducted as possible. If the reserve balance of `who` + /// is less than `value`, then a non-zero second item will be returned. + fn slash_reserved( + who: &AccountId, + value: Self::Balance + ) -> (Self::NegativeImbalance, Self::Balance); + + /// The amount of the balance of a given account that is externally reserved; this can still get + /// slashed, but gets slashed last of all. + /// + /// This balance is a 'reserve' balance that other subsystems use in order to set aside tokens + /// that are still 'owned' by the account holder, but which are suspendable. + /// + /// When this balance falls below the value of `ExistentialDeposit`, then this 'reserve account' + /// is deleted: specifically, `ReservedBalance`. + /// + /// `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets + /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. + fn reserved_balance(who: &AccountId) -> Self::Balance; + /// Moves `value` from balance to reserved balance. /// /// If the free balance is lower than `value`, then no funds will be moved and an `Err` will - /// be returned to notify of this. This is different behaviour to `unreserve`. + /// be returned to notify of this. This is different behavior than `unreserve`. fn reserve(who: &AccountId, value: Self::Balance) -> result::Result<(), &'static str>; - /// Moves up to `value` from reserved balance to balance. This function cannot fail. + /// Moves up to `value` from reserved balance to free balance. This function cannot fail. /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - /// NOTE: This is different to `reserve`. - fn unreserve(who: &AccountId, value: Self::Balance) -> Option; - - /// Deducts up to `value` from reserved balance of `who`. This function cannot fail. + /// As much funds up to `value` will be moved as possible. If the reserve balance of `who` + /// is less than `value`, then the remaining amount will be returned. /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - fn slash_reserved(who: &AccountId, value: Self::Balance) -> Option; + /// # NOTES + /// + /// - This is different from `reserve`. + /// - If the remaining reserved balance is less than `ExistentialDeposit`, it will + /// invoke `on_reserved_too_low` and could reap the account. + fn unreserve(who: &AccountId, value: Self::Balance) -> Self::Balance; /// Moves up to `value` from reserved balance of account `slashed` to free balance of account /// `beneficiary`. `beneficiary` must exist for this to succeed. If it does not, `Err` will be /// returned. /// - /// As much funds up to `value` will be moved as possible. If this is less than `value`, then - /// `Ok(Some(remaining))` will be returned. Full completion is given by `Ok(None)`. + /// As much funds up to `value` will be deducted as possible. If this is less than `value`, + /// then `Ok(non_zero)` will be returned. fn repatriate_reserved( slashed: &AccountId, beneficiary: &AccountId, value: Self::Balance - ) -> result::Result, &'static str>; + ) -> result::Result; } -/// Charge bytes fee trait -pub trait ChargeBytesFee { - /// Charge fees from `transactor` for an extrinsic (transaction) of encoded length - /// `encoded_len` bytes. Return Ok iff the payment was successful. - fn charge_base_bytes_fee(transactor: &AccountId, encoded_len: usize) -> Result<(), &'static str>; -} - -/// Charge fee trait -pub trait ChargeFee: ChargeBytesFee { - /// The type of fee amount. - type Amount; +/// An identifier for a lock. Used for disambiguating different locks so that +/// they can be individually replaced or removed. +pub type LockIdentifier = [u8; 8]; - /// Charge `amount` of fees from `transactor`. Return Ok iff the payment was successful. - fn charge_fee(transactor: &AccountId, amount: Self::Amount) -> Result<(), &'static str>; - - /// Refund `amount` of previous charged fees from `transactor`. Return Ok iff the refund was successful. - fn refund_fee(transactor: &AccountId, amount: Self::Amount) -> Result<(), &'static str>; -} - -/// Reason for moving funds out of an account. -#[derive(Copy, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub enum WithdrawReason { - /// In order to pay for (system) transaction costs. - TransactionPayment, - /// In order to transfer ownership. - Transfer, - /// In order to reserve some funds for a later return or repatriation - Reserve, -} +/// A currency whose accounts can have liquidity restrictions. +pub trait LockableCurrency: Currency { + /// The quantity used to denote time; usually just a `BlockNumber`. + type Moment; -/// Transfer fungible asset trait -pub trait TransferAsset { - /// The type of asset amount. - type Amount; - - /// Transfer asset from `from` account to `to` account with `amount` of asset. - fn transfer(from: &AccountId, to: &AccountId, amount: Self::Amount) -> Result<(), &'static str>; - - /// Remove asset from `who` account by deducting `amount` in the account balances. - fn withdraw(who: &AccountId, amount: Self::Amount, reason: WithdrawReason) -> Result<(), &'static str>; - - /// Add asset to `who` account by increasing `amount` in the account balances. - fn deposit(who: &AccountId, amount: Self::Amount) -> Result<(), &'static str>; -} + /// Create a new balance lock on account `who`. + /// + /// If the new lock is valid (i.e. not already expired), it will push the struct to + /// the `Locks` vec in storage. Note that you can lock more funds than a user has. + /// + /// If the lock `id` already exists, this will update it. + fn set_lock( + id: LockIdentifier, + who: &AccountId, + amount: Self::Balance, + until: Self::Moment, + reasons: WithdrawReasons, + ); -impl ChargeBytesFee for () { - fn charge_base_bytes_fee(_: &T, _: usize) -> Result<(), &'static str> { Ok(()) } + /// Changes a balance lock (selected by `id`) so that it becomes less liquid in all + /// parameters or creates a new one if it does not exist. + /// + /// Calling `extend_lock` on an existing lock `id` differs from `set_lock` in that it + /// applies the most severe constraints of the two, while `set_lock` replaces the lock + /// with the new parameters. As in, `extend_lock` will set: + /// - maximum `amount` + /// - farthest duration (`until`) + /// - bitwise mask of all `reasons` + fn extend_lock( + id: LockIdentifier, + who: &AccountId, + amount: Self::Balance, + until: Self::Moment, + reasons: WithdrawReasons, + ); + + /// Remove an existing lock. + fn remove_lock( + id: LockIdentifier, + who: &AccountId, + ); } -impl ChargeFee for () { - type Amount = (); - - fn charge_fee(_: &T, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } - fn refund_fee(_: &T, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } +bitmask! { + /// Reasons for moving funds out of an account. + #[derive(Encode, Decode)] + pub mask WithdrawReasons: i8 where + + /// Reason for moving funds out of an account. + #[derive(Encode, Decode)] + flags WithdrawReason { + /// In order to pay for (system) transaction costs. + TransactionPayment = 0b00000001, + /// In order to transfer ownership. + Transfer = 0b00000010, + /// In order to reserve some funds for a later return or repatriation + Reserve = 0b00000100, + /// In order to pay some other (higher-level) fees. + Fee = 0b00001000, + } } -impl TransferAsset for () { - type Amount = (); - - fn transfer(_: &T, _: &T, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } - fn withdraw(_: &T, _: Self::Amount, _: WithdrawReason) -> Result<(), &'static str> { Ok(()) } - fn deposit(_: &T, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } -} diff --git a/srml/support/test/Cargo.toml b/srml/support/test/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e1113eb46851f3a82a5848c42ab3441b934e6fb6 --- /dev/null +++ b/srml/support/test/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "srml-support-test" +version = "0.1.0" +authors = ["thiolliere "] +edition = "2018" + +[dev-dependencies] +serde = { version = "1.0", default-features = false } +serde_derive = { version = "1.0" } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +runtime_io = { package = "sr-io", path = "../../../core/sr-io", default-features = false } +srml-support = { path = "../", default-features = false } +inherents = { package = "substrate-inherents", path = "../../../core/inherents", default-features = false } +primitives = { package = "substrate-primitives", path = "../../../core/primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "parity-codec/std", + "runtime_io/std", + "srml-support/std", + "inherents/std", + "primitives/std", +] diff --git a/srml/support/test/src/lib.rs b/srml/support/test/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/srml/support/test/tests/instance.rs b/srml/support/test/tests/instance.rs new file mode 100644 index 0000000000000000000000000000000000000000..28ad3ee0063056a217bf99fef01f0674ef849306 --- /dev/null +++ b/srml/support/test/tests/instance.rs @@ -0,0 +1,498 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![recursion_limit="128"] + +#[cfg(feature = "std")] +use serde_derive::Serialize; +use runtime_io::{with_externalities, Blake2Hasher}; +use srml_support::rstd::prelude::*; +use srml_support::rstd as rstd; +use srml_support::codec::{Encode, Decode}; +use srml_support::runtime_primitives::{generic, BuildStorage}; +use srml_support::runtime_primitives::traits::{BlakeTwo256, Block as _, Verify, Digest}; +use srml_support::Parameter; +use inherents::{ + ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError +}; +use srml_support::{StorageValue, StorageMap, StorageDoubleMap}; +use primitives::{H256, sr25519}; + +pub trait Currency { +} + +// Mock +mod system { + use super::*; + + pub trait Trait: 'static + Eq + Clone { + type Origin: Into>> + From>; + type BlockNumber; + type Digest: Digest; + type Hash; + type AccountId; + type Event: From; + type Log: From> + Into>; + } + + pub type DigestItemOf = <::Digest as Digest>::Item; + + srml_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin { + pub fn deposit_event(_event: T::Event) { + } + } + } + impl Module { + pub fn deposit_log(_item: ::Item) { + unimplemented!(); + } + } + + srml_support::decl_event!( + pub enum Event { + ExtrinsicSuccess, + ExtrinsicFailed, + } + ); + + /// Origin for the system module. + #[derive(PartialEq, Eq, Clone)] + #[cfg_attr(feature = "std", derive(Debug))] + pub enum RawOrigin { + Root, + Signed(AccountId), + Inherent, + } + + impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::Inherent, + } + } + } + + pub type Origin = RawOrigin<::AccountId>; + + pub type Log = RawLog< + ::Hash, + >; + + #[cfg_attr(feature = "std", derive(Serialize, Debug))] + #[derive(Encode, Decode, PartialEq, Eq, Clone)] + pub enum RawLog { + ChangesTrieRoot(H), + } + + pub fn ensure_root(o: OuterOrigin) -> Result<(), &'static str> + where OuterOrigin: Into>> + { + match o.into() { + Some(RawOrigin::Root) => Ok(()), + _ => Err("bad origin: expected to be a root origin"), + } + } +} + +// Test for: +// * No default instance +// * Custom InstantiableTrait +// * Origin, Inherent, Log, Event +mod module1 { + use super::*; + + pub trait Trait: system::Trait { + type Event: From> + Into<::Event>; + type Origin: From>; + type Log: From> + Into>; + } + + srml_support::decl_module! { + pub struct Module, I: InstantiableThing> for enum Call where origin: ::Origin { + fn deposit_event() = default; + + fn one() { + Self::deposit_event(RawEvent::AnotherVariant(3)); + Self::deposit_log(RawLog::AmountChange(3)); + } + } + } + + impl, I: InstantiableThing> Module { + /// Deposit one of this module's logs. + fn deposit_log(log: Log) { + >::deposit_log(>::Log::from(log).into()); + } + } + + srml_support::decl_storage! { + trait Store for Module, I: InstantiableThing> as Module1 { + pub Value config(value): u64; + pub Map: map u32 => u64; + pub LinkedMap: linked_map u32 => u64; + } + } + + srml_support::decl_event! { + pub enum Event where Phantom = rstd::marker::PhantomData { + _Phantom(Phantom), + AnotherVariant(u32), + } + } + + #[derive(PartialEq, Eq, Clone)] + #[cfg_attr(feature = "std", derive(Debug))] + pub enum Origin, I> { + Members(u32), + _Phantom(rstd::marker::PhantomData<(T, I)>), + } + + pub type Log = RawLog< + T, + I, + >; + + /// A logs in this module. + #[cfg_attr(feature = "std", derive(serde_derive::Serialize, Debug))] + #[derive(parity_codec::Encode, parity_codec::Decode, PartialEq, Eq, Clone)] + pub enum RawLog { + _Phantom(rstd::marker::PhantomData<(T, I)>), + AmountChange(u32), + } + + pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678"; + + impl, I: InstantiableThing> ProvideInherent for Module { + type Call = Call; + type Error = MakeFatalError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(_data: &InherentData) -> Option { + unimplemented!(); + } + + fn check_inherent(_call: &Self::Call, _data: &InherentData) -> rstd::result::Result<(), Self::Error> { + unimplemented!(); + } + } +} + +// Test for: +// * default instance +// * use of no_genesis_config_phantom_data +mod module2 { + use super::*; + + pub trait Trait: system::Trait { + type Amount: Parameter + Default; + type Event: From> + Into<::Event>; + type Origin: From>; + type Log: From> + Into>; + } + + impl, I: Instance> Currency for Module {} + + srml_support::decl_module! { + pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { + fn deposit_event() = default; + } + } + + srml_support::decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as Module2 { + pub Value config(value): T::Amount; + pub Map config(map): map u64 => u64; + pub LinkedMap config(linked_map): linked_map u64 => u64; + pub DoubleMap config(double_map): double_map u64, blake2_256(u64) => u64; + } + extra_genesis_skip_phantom_data_field; + } + + srml_support::decl_event! { + pub enum Event where Amount = >::Amount { + Variant(Amount), + } + } + + #[derive(PartialEq, Eq, Clone)] + #[cfg_attr(feature = "std", derive(Debug))] + pub enum Origin, I=DefaultInstance> { + Members(u32), + _Phantom(rstd::marker::PhantomData<(T, I)>), + } + + pub type Log = RawLog< + T, + I, + >; + + /// A logs in this module. + #[cfg_attr(feature = "std", derive(serde_derive::Serialize, Debug))] + #[derive(parity_codec::Encode, parity_codec::Decode, PartialEq, Eq, Clone)] + pub enum RawLog { + _Phantom(rstd::marker::PhantomData<(T, I)>), + AmountChange(u32), + } + + pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678"; + + impl, I: Instance> ProvideInherent for Module { + type Call = Call; + type Error = MakeFatalError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(_data: &InherentData) -> Option { + unimplemented!(); + } + + fn check_inherent(_call: &Self::Call, _data: &InherentData) -> rstd::result::Result<(), Self::Error> { + unimplemented!(); + } + } +} + +// Test for: +// * Depends on multiple instances of a module with instances +mod module3 { + use super::*; + + pub trait Trait: module2::Trait + module2::Trait + system::Trait { + type Currency: Currency; + type Currency2: Currency; + } + + srml_support::decl_module! { + pub struct Module for enum Call where origin: ::Origin { + } + } +} + +impl module1::Trait for Runtime { + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module1::Trait for Runtime { + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module2::Trait for Runtime { + type Amount = u16; + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module2::Trait for Runtime { + type Amount = u32; + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module2::Trait for Runtime { + type Amount = u32; + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module2::Trait for Runtime { + type Amount = u64; + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module3::Trait for Runtime { + type Currency = Module2_2; + type Currency2 = Module2_3; +} + +pub type Signature = sr25519::Signature; +pub type AccountId = ::Signer; +pub type BlockNumber = u64; +pub type Index = u64; + +impl system::Trait for Runtime { + type Hash = H256; + type Origin = Origin; + type BlockNumber = BlockNumber; + type Digest = generic::Digest; + type AccountId = AccountId; + type Event = Event; + type Log = Log; +} + +srml_support::construct_runtime!( + pub enum Runtime with Log(InternalLog: DigestItem) where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event, Log(ChangesTrieRoot)}, + Module1_1: module1::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module1_2: module1::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module2: module2::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module2_1: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module2_2: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module2_3: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module3: module3::{Module, Call}, + } +); + +pub type Header = generic::Header; +pub type Block = generic::Block; +pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; + +fn new_test_ext() -> runtime_io::TestExternalities { + GenesisConfig{ + module1_Instance1: Some(module1::GenesisConfig { + value: 3, + .. Default::default() + }), + module1_Instance2: Some(module1::GenesisConfig { + value: 4, + _genesis_phantom_data: Default::default(), + }), + module2: Some(module2::GenesisConfig { + value: 4, + map: vec![(0, 0)], + linked_map: vec![(0, 0)], + double_map: vec![(0, 0, 0)], + }), + module2_Instance1: Some(module2::GenesisConfig { + value: 4, + map: vec![(0, 0)], + linked_map: vec![(0, 0)], + double_map: vec![(0, 0, 0)], + }), + module2_Instance2: None, + module2_Instance3: None, + }.build_storage().unwrap().0.into() +} + +#[test] +fn storage_instance_independance() { + with_externalities(&mut new_test_ext(), || { + let mut map = rstd::collections::btree_map::BTreeMap::new(); + for key in [ + module2::Value::::key().to_vec(), + module2::Value::::key().to_vec(), + module2::Value::::key().to_vec(), + module2::Value::::key().to_vec(), + module2::Map::::prefix().to_vec(), + module2::Map::::prefix().to_vec(), + module2::Map::::prefix().to_vec(), + module2::Map::::prefix().to_vec(), + module2::LinkedMap::::prefix().to_vec(), + module2::LinkedMap::::prefix().to_vec(), + module2::LinkedMap::::prefix().to_vec(), + module2::LinkedMap::::prefix().to_vec(), + module2::DoubleMap::::prefix().to_vec(), + module2::DoubleMap::::prefix().to_vec(), + module2::DoubleMap::::prefix().to_vec(), + module2::DoubleMap::::prefix().to_vec(), + module2::Map::::key_for(0), + module2::Map::::key_for(0).to_vec(), + module2::Map::::key_for(0).to_vec(), + module2::Map::::key_for(0).to_vec(), + module2::LinkedMap::::key_for(0), + module2::LinkedMap::::key_for(0).to_vec(), + module2::LinkedMap::::key_for(0).to_vec(), + module2::LinkedMap::::key_for(0).to_vec(), + module2::Map::::key_for(1), + module2::Map::::key_for(1).to_vec(), + module2::Map::::key_for(1).to_vec(), + module2::Map::::key_for(1).to_vec(), + module2::LinkedMap::::key_for(1), + module2::LinkedMap::::key_for(1).to_vec(), + module2::LinkedMap::::key_for(1).to_vec(), + module2::LinkedMap::::key_for(1).to_vec(), + module2::DoubleMap::::prefix_for(1), + module2::DoubleMap::::prefix_for(1).to_vec(), + module2::DoubleMap::::prefix_for(1).to_vec(), + module2::DoubleMap::::prefix_for(1).to_vec(), + module2::DoubleMap::::key_for(1, 1), + module2::DoubleMap::::key_for(1, 1).to_vec(), + module2::DoubleMap::::key_for(1, 1).to_vec(), + module2::DoubleMap::::key_for(1, 1).to_vec(), + ].iter() { + assert!(map.insert(key, ()).is_none()) + } + }); +} + +// TODO TODO: check configuration doublemapstorage in instances + +#[test] +fn storage_with_instance_basic_operation() { + with_externalities(&mut new_test_ext(), || { + type Value = module2::Value; + type Map = module2::Map; + type LinkedMap = module2::LinkedMap; + type DoubleMap = module2::DoubleMap; + + assert_eq!(Value::exists(), true); + assert_eq!(Value::get(), 4); + Value::put(1); + assert_eq!(Value::get(), 1); + assert_eq!(Value::take(), 1); + assert_eq!(Value::get(), 0); + Value::mutate(|a| *a=2); + assert_eq!(Value::get(), 2); + Value::kill(); + assert_eq!(Value::exists(), false); + assert_eq!(Value::get(), 0); + + let key = 1; + assert_eq!(Map::exists(0), true); + assert_eq!(Map::exists(key), false); + Map::insert(key, 1); + assert_eq!(Map::get(key), 1); + assert_eq!(Map::take(key), 1); + assert_eq!(Map::get(key), 0); + Map::mutate(key, |a| *a=2); + assert_eq!(Map::get(key), 2); + Map::remove(key); + assert_eq!(Map::exists(key), false); + assert_eq!(Map::get(key), 0); + + assert_eq!(LinkedMap::exists(0), true); + assert_eq!(LinkedMap::exists(key), false); + LinkedMap::insert(key, 1); + assert_eq!(LinkedMap::get(key), 1); + assert_eq!(LinkedMap::take(key), 1); + assert_eq!(LinkedMap::get(key), 0); + LinkedMap::mutate(key, |a| *a=2); + assert_eq!(LinkedMap::get(key), 2); + LinkedMap::remove(key); + assert_eq!(LinkedMap::exists(key), false); + assert_eq!(LinkedMap::get(key), 0); + + let key1 = 1; + let key2 = 1; + assert_eq!(DoubleMap::exists(0, 0), true); + assert_eq!(DoubleMap::exists(key1, key2), false); + DoubleMap::insert(key1, key2, 1); + assert_eq!(DoubleMap::get(key1, key2), 1); + assert_eq!(DoubleMap::take(key1, key2), 1); + assert_eq!(DoubleMap::get(key1, key2), 0); + DoubleMap::mutate(key1, key2, |a| *a=2); + assert_eq!(DoubleMap::get(key1, key2), 2); + DoubleMap::remove(key1, key2); + assert_eq!(DoubleMap::get(key1, key2), 0); + }); +} diff --git a/srml/system/Cargo.toml b/srml/system/Cargo.toml index f1f3692aa35f61c78effc30869de0ee265b6e00d..bd199b97f902a300b2a3d387203262a9712a3a62 100644 --- a/srml/system/Cargo.toml +++ b/srml/system/Cargo.toml @@ -6,10 +6,10 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } @@ -19,7 +19,7 @@ srml-support = { path = "../support", default-features = false } [features] default = ["std"] std = [ - "serde/std", + "serde", "serde_derive", "safe-mix/std", "parity-codec/std", diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 0a0cf624e756146ed2d3fc228bb570d5b8b7810d..f226fcb7d18552da3de82ea70ba80c31f659f1c6 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,8 +14,59 @@ // You should have received a copy of the GNU General Public License // along with Substrate. 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. +//! # System module +//! +//! The system module provides low-level access to core types and cross-cutting utilities. +//! It acts as the base layer for other SRML modules to interact with the Substrate framework components. +//! To use it in your module, you should ensure your module's trait implies the system [`Trait`]. +//! +//! ## Overview +//! +//! The system module defines the core data types used in a Substrate runtime. +//! It also provides several utility functions (see [`Module`]) for other runtime modules. +//! +//! In addition, it manages the storage items for extrinsics data, indexes, event record and digest items, +//! among other things that support the execution of the current block. +//! +//! It also handles low level tasks like depositing logs, basic set up and take down of +//! temporary storage entries and access to previous block hashes. +//! +//! ## Interface +//! +//! ### Dispatchable functions +//! +//! The system module does not implement any dispatchable functions. +//! +//! ### Public functions +//! +//! All public functions are available as part of the [`Module`] type. +//! +//! ## Usage +//! +//! ### Prerequisites +//! +//! Import the system module and derive your module's configuration trait from the system trait. +//! +//! ### Example - Get random seed and extrinsic count for the current block +//! +//! ``` +//! use srml_support::{decl_module, dispatch::Result}; +//! use srml_system::{self as system, ensure_signed}; +//! +//! pub trait Trait: system::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn system_module_example(origin) -> Result { +//! let _sender = ensure_signed(origin)?; +//! let _random_seed = >::random_seed(); +//! let _extrinsic_count = >::extrinsic_count(); +//! Ok(()) +//! } +//! } +//! } +//! # fn main() { } +//! ``` #![cfg_attr(not(feature = "std"), no_std)] @@ -60,32 +111,64 @@ impl IsDeadAccount for () { } } -/// Compute the extrinsics root of a list of extrinsics. +/// Compute the trie root of a list of extrinsics. pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { extrinsics_data_root::(extrinsics.iter().map(parity_codec::Encode::encode).collect()) } -/// Compute the extrinsics root of a list of extrinsics. +/// Compute the trie root of a list of extrinsics. pub fn extrinsics_data_root(xts: Vec>) -> H::Output { let xts = xts.iter().map(Vec::as_slice).collect::>(); H::enumerated_trie_root(&xts) } pub trait Trait: 'static + Eq + Clone { + /// The aggregated `Origin` type used by dispatchable calls. type Origin: Into>> + From>; - type Index: Parameter + Member + MaybeSerializeDebugButNotDeserialize + Default + MaybeDisplay + SimpleArithmetic + Copy; - type BlockNumber: Parameter + Member + MaybeSerializeDebug + MaybeDisplay + SimpleArithmetic + Default + Bounded + Copy + rstd::hash::Hash; - type Hash: Parameter + Member + MaybeSerializeDebug + MaybeDisplay + SimpleBitOps + Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]>; + + /// Account index (aka nonce) type. This stores the number of previous transactions associated with a sender + /// account. + type Index: + Parameter + Member + MaybeSerializeDebugButNotDeserialize + Default + MaybeDisplay + SimpleArithmetic + Copy; + + /// The block number type used by the runtime. + type BlockNumber: + Parameter + Member + MaybeSerializeDebug + MaybeDisplay + SimpleArithmetic + Default + Bounded + Copy + + rstd::hash::Hash; + + /// The output of the `Hashing` function. + type Hash: + Parameter + Member + MaybeSerializeDebug + MaybeDisplay + SimpleBitOps + Default + Copy + CheckEqual + + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]>; + + /// The hashing system (algorithm) being used in the runtime (e.g. Blake2). type Hashing: Hash; - type Digest: Parameter + Member + MaybeSerializeDebugButNotDeserialize + Default + traits::Digest; + + /// Collection of (light-client-relevant) logs for a block to be included verbatim in the block header. + type Digest: + Parameter + Member + MaybeSerializeDebugButNotDeserialize + Default + traits::Digest; + + /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDebug + MaybeDisplay + Ord + Default; + + /// Converting trait to take a source type and convert to `AccountId`. + /// + /// Used to define the type and conversion mechanism for referencing accounts in transactions. It's perfectly + /// reasonable for this to be an identity conversion (with the source type being `AccountId`), but other modules + /// (e.g. Indices module) may provide more functional/efficient alternatives. type Lookup: StaticLookup; + + /// The block header. type Header: Parameter + traits::Header< Number = Self::BlockNumber, Hash = Self::Hash, Digest = Self::Digest >; + + /// The aggregated event type of the runtime. type Event: Parameter + Member + From; + + /// A piece of information which can be part of the digest (as a digest item). type Log: From> + Into>; } @@ -124,8 +207,8 @@ pub struct EventRecord { pub event: E, } -/// Event for the system module. decl_event!( + /// Event for the system module. pub enum Event { /// An extrinsic completed successfully. ExtrinsicSuccess, @@ -191,7 +274,7 @@ impl From> for primitives::testing::DigestIte } // Create a Hash with 69 for each byte, -// only used to build genesis config +// only used to build genesis config. #[cfg(feature = "std")] fn hash69 + Default>() -> T { let mut h = T::default(); @@ -201,20 +284,27 @@ fn hash69 + Default>() -> T { decl_storage! { trait Store for Module as System { - + /// Extrinsics nonce for accounts. pub AccountNonce get(account_nonce): map T::AccountId => T::Index; - + /// Total extrinsics count for the current block. ExtrinsicCount: Option; + /// Total length in bytes for all extrinsics put together, for the current block. AllExtrinsicsLen: Option; + /// Map of block numbers to block hashes. pub BlockHash get(block_hash) build(|_| vec![(T::BlockNumber::zero(), hash69())]): map T::BlockNumber => T::Hash; + /// Extrinsics data for the current block (maps extrinsic's index to its data). ExtrinsicData get(extrinsic_data): map u32 => Vec; + /// Random seed of the current block. RandomSeed get(random_seed) build(|_| T::Hash::default()): T::Hash; /// The current block number being processed. Set by `execute_block`. Number get(block_number) build(|_| T::BlockNumber::sa(1u64)): T::BlockNumber; + /// Hash of the previous block. ParentHash get(parent_hash) build(|_| hash69()): T::Hash; + /// Extrinsics root of the current block, also part of the block header. ExtrinsicsRoot get(extrinsics_root): T::Hash; + /// Digest of the current block, also part of the block header. Digest get(digest): T::Digest; - + /// Events deposited for the current block. Events get(events): Vec>; } add_extra_genesis { @@ -290,7 +380,7 @@ impl Module { } /// Start the execution of a particular block. - pub fn initialise(number: &T::BlockNumber, parent_hash: &T::Hash, txs_root: &T::Hash) { + pub fn initialize(number: &T::BlockNumber, parent_hash: &T::Hash, txs_root: &T::Hash) { // populate environment. storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); >::put(number); @@ -302,7 +392,7 @@ impl Module { } /// Remove temporary "environment" entries in storage. - pub fn finalise() -> T::Header { + pub fn finalize() -> T::Header { >::kill(); >::kill(); >::kill(); @@ -324,8 +414,7 @@ impl Module { // > stays to be inspected by the client. - ::new(number, extrinsics_root, storage_root, - parent_hash, digest) + ::new(number, extrinsics_root, storage_root, parent_hash, digest) } /// Deposits a log and ensures it matches the blocks log data. @@ -359,7 +448,7 @@ impl Module { } /// 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. + /// `initialize` 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); @@ -372,14 +461,14 @@ impl Module { } /// Set the parent hash 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. + /// `initialize` for tests that don't need to bother with the other environment entries. #[cfg(any(feature = "std", test))] pub fn set_parent_hash(n: T::Hash) { >::put(n); } /// Set the random seed 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. + /// `initialize` for tests that don't need to bother with the other environment entries. #[cfg(any(feature = "std", test))] pub fn set_random_seed(seed: T::Hash) { >::put(seed); @@ -482,7 +571,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = u16; type Log = DigestItem; @@ -506,19 +595,19 @@ mod tests { #[test] fn deposit_event_should_work() { with_externalities(&mut new_test_ext(), || { - System::initialise(&1, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&1, &[0u8; 32].into(), &[0u8; 32].into()); System::note_finished_extrinsics(); System::deposit_event(1u16); - System::finalise(); + System::finalize(); assert_eq!(System::events(), vec![EventRecord { phase: Phase::Finalization, event: 1u16 }]); - System::initialise(&2, &[0u8; 32].into(), &[0u8; 32].into()); + System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into()); System::deposit_event(42u16); System::note_applied_extrinsic(&Ok(()), 0); System::note_applied_extrinsic(&Err(""), 0); System::note_finished_extrinsics(); System::deposit_event(3u16); - System::finalise(); + System::finalize(); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16 }, EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16 }, diff --git a/srml/timestamp/Cargo.toml b/srml/timestamp/Cargo.toml index d2133daebbda03814f2410aa4066a9b5d91feecb..30c3779f31c6435e39383cd86d789b87de5f1138 100644 --- a/srml/timestamp/Cargo.toml +++ b/srml/timestamp/Cargo.toml @@ -6,14 +6,13 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } srml-support = { path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } -consensus = { package = "srml-consensus", path = "../consensus", default-features = false } [dev-dependencies] runtime_io = { package = "sr-io", path = "../../core/sr-io" } @@ -22,12 +21,11 @@ substrate-primitives = { path = "../../core/primitives" } [features] default = ["std"] std = [ + "inherents/std", + "parity-codec/std", "rstd/std", - "srml-support/std", "runtime_primitives/std", - "consensus/std", - "serde/std", - "parity-codec/std", + "srml-support/std", + "serde", "system/std", - "inherents/std", ] diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index a7fa9e9663e331acbf962e3111f1233156df9023..43cf669e7e701a3935d7f0ec470201bf12ce2846 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,35 +14,84 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Timestamp manager: provides means to find out the current time. +//! # Timestamp Module +//! +//! The timestamp module provides functionality to get and set the on-chain time. +//! To use it in your module, you need to implement the timestamp [`Trait`]. +//! The supported dispatchable functions are documented as part of the [`Call`] enum. +//! +//! ## Overview +//! +//! The timestamp module allows the validators to set and validate a timestamp with each block. //! -//! It is expected that the timestamp is set by the validator in the -//! beginning of each block, typically one of the first extrinsics. The timestamp -//! can be set only once per block and must be set each block. +//! It uses inherents for timestamp data, which is provided by the block author and validated/verified by other validators. +//! The timestamp can be set only once per block and must be set each block. There could be a constraint on how much time must pass before setting the new timestamp. +//! +//! **NOTE:** The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. +//! The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. +//! +//! ## Interface +//! +//! ### Dispatchable functions ([`Call`]) +//! +//! * `set` - Sets the current time. +//! +//! ### Public functions ([`Module`]) +//! +//! * `get` - Gets the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. +//! +//! * `minimum_period` - Gets the minimum (and advised) period between blocks for the chain. +//! +//! ## Usage +//! +//! The following example shows how to use the timestamp module in your custom module to query the current timestamp. +//! +//! ### Prerequisites +//! +//! Import the `timestamp` module in your custom module and derive the module configuration trait from the `timestamp` trait. +//! +//! ### Get current timestamp +//! +//! ```ignore +//! use support::{decl_module, dispatch::Result}; +//! use system::ensure_signed; +//! +//! pub trait Trait: timestamp::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn get_time(origin) -> Result { +//! let _sender = ensure_signed(origin)?; +//! let _now = >::get(); +//! Ok(()) +//! } +//! } +//! } +//! ``` +//! +//! ### Example from SRML +//! +//! The [`Session` module](https://github.com/paritytech/substrate/blob/master/srml/session/src/lib.rs) uses the `timestamp` module for session management. +//! +//! ## Related Modules +//! +//! * [`System`](https://crates.parity.io/srml_system/index.html) +//! * [`Session`](https://crates.parity.io/srml_session/index.html) //! -//! Note, that there might be a constraint on how much time must pass -//! before setting the new timestamp, specified by the `tim:block_period` -//! storage entry. -//! -//! # Interaction with the system -//! -//! ## Finalization -//! -//! This module should be hooked up to the finalization routine. #![cfg_attr(not(feature = "std"), no_std)] +use parity_codec::Encode; #[cfg(feature = "std")] use parity_codec::Decode; -use parity_codec::Encode; +#[cfg(feature = "std")] +use inherents::ProvideInherentData; use srml_support::{StorageValue, Parameter, decl_storage, decl_module}; use srml_support::for_each_tuple; use runtime_primitives::traits::{As, SimpleArithmetic, Zero}; use system::ensure_inherent; use rstd::{result, ops::{Mul, Div}, cmp}; use inherents::{RuntimeString, InherentIdentifier, ProvideInherent, IsFatalError, InherentData}; -#[cfg(feature = "std")] -use inherents::ProvideInherentData; /// The identifier for the `timestamp` inherent. pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0"; @@ -144,11 +193,13 @@ macro_rules! impl_timestamp_set { for_each_tuple!(impl_timestamp_set); -pub trait Trait: consensus::Trait + system::Trait { +/// The module configuration trait +pub trait Trait: system::Trait { /// Type used for expressing timestamp. type Moment: Parameter + Default + SimpleArithmetic + Mul + Div; + /// Something which can be notified when the timestamp is set. Set this to `()` if not needed. type OnTimestampSet: OnTimestampSet; } @@ -157,18 +208,18 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { /// Set the current time. /// - /// Extrinsic with this call should be placed at the specific position in the each block - /// (specified by the Trait::TIMESTAMP_SET_POSITION) typically at the start of the each block. /// This call should be invoked exactly once per block. It will panic at the finalization phase, /// if this call hasn't been invoked by that time. /// - /// The timestamp should be greater than the previous one by the amount specified by `block_period`. + /// The timestamp should be greater than the previous one by the amount specified by `minimum_period`. + /// + /// The dispatch origin for this call must be `Inherent`. fn set(origin, #[compact] now: T::Moment) { ensure_inherent(origin)?; assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); assert!( - Self::now().is_zero() || now >= Self::now() + Self::block_period(), - "Timestamp must increment by at least between sequential blocks" + Self::now().is_zero() || now >= Self::now() + >::get(), + "Timestamp must increment by at least between sequential blocks" ); ::Now::put(now.clone()); ::DidUpdate::put(true); @@ -176,7 +227,17 @@ decl_module! { >::on_timestamp_set(now); } - fn on_finalise() { + // Manage upgrade. Remove after all networks upgraded. + // TODO: #2133 + fn on_initialize() { + if let Some(period) = >::take() { + if !>::exists() { + >::put(period) + } + } + } + + fn on_finalize() { assert!(::DidUpdate::take(), "Timestamp must be updated once in the block"); } } @@ -186,8 +247,16 @@ decl_storage! { trait Store for Module as Timestamp { /// Current time for the current block. pub Now get(now) build(|_| T::Moment::sa(0)): T::Moment; - /// The minimum (and advised) period between blocks. - pub BlockPeriod get(block_period) config(period): T::Moment = T::Moment::sa(5); + + /// Old storage item provided for compatibility. Remove after all networks upgraded. + // TODO: #2133 + pub BlockPeriod: Option; + + /// The minimum period between blocks. Beware that this is different to the *expected* period + /// that the block production apparatus provides. Your chosen consensus system will generally + /// work with this to determine a sensible block time. e.g. For Aura, it will be double this + /// period on default settings. + pub MinimumPeriod get(minimum_period) config(): T::Moment = T::Moment::sa(3); /// Did the timestamp get updated in this block? DidUpdate: bool; @@ -195,10 +264,9 @@ decl_storage! { } impl Module { - /// Get the current time for the current block. /// - /// NOTE: if this function is called prior the setting the timestamp, + /// NOTE: if this function is called prior to setting the timestamp, /// it will return the timestamp of the previous block. pub fn get() -> T::Moment { Self::now() @@ -225,7 +293,7 @@ impl ProvideInherent for Module { fn create_inherent(data: &InherentData) -> Option { let data = extract_inherent_data(data).expect("Gets and decodes timestamp inherent data"); - let next_time = cmp::max(As::sa(data), Self::now() + Self::block_period()); + let next_time = cmp::max(As::sa(data), Self::now() + >::get()); Some(Call::set(next_time.into())) } @@ -239,7 +307,7 @@ impl ProvideInherent for Module { let data = extract_inherent_data(data).map_err(|e| InherentError::Other(e))?; - let minimum = (Self::now() + Self::block_period()).as_(); + let minimum = (Self::now() + >::get()).as_(); if t > data + MAX_TIMESTAMP_DRIFT { Err(InherentError::Other("Timestamp too far in future to accept".into())) } else if t < minimum { @@ -259,7 +327,7 @@ mod tests { use substrate_primitives::H256; use runtime_primitives::BuildStorage; use runtime_primitives::traits::{BlakeTwo256, IdentityLookup}; - use runtime_primitives::testing::{Digest, DigestItem, Header, UintAuthorityId}; + use runtime_primitives::testing::{Digest, DigestItem, Header}; impl_outer_origin! { pub enum Origin for Test {} @@ -275,16 +343,11 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } - impl consensus::Trait for Test { - type Log = DigestItem; - type SessionKey = UintAuthorityId; - type InherentOfflineReport = (); - } impl Trait for Test { type Moment = u64; type OnTimestampSet = (); @@ -295,7 +358,7 @@ mod tests { fn timestamp_works() { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(GenesisConfig:: { - period: 5, + minimum_period: 5, }.build_storage().unwrap().0); with_externalities(&mut TestExternalities::new(t), || { @@ -310,7 +373,7 @@ mod tests { fn double_timestamp_should_fail() { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(GenesisConfig:: { - period: 5, + minimum_period: 5, }.build_storage().unwrap().0); with_externalities(&mut TestExternalities::new(t), || { @@ -321,11 +384,11 @@ mod tests { } #[test] - #[should_panic(expected = "Timestamp must increment by at least between sequential blocks")] - fn block_period_is_enforced() { + #[should_panic(expected = "Timestamp must increment by at least between sequential blocks")] + fn block_period_minimum_enforced() { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(GenesisConfig:: { - period: 5, + minimum_period: 5, }.build_storage().unwrap().0); with_externalities(&mut TestExternalities::new(t), || { diff --git a/srml/treasury/Cargo.toml b/srml/treasury/Cargo.toml index d417a0e7e2077f648b122548eda39d535e4532c8..825fc73532cbc35fdbf519c8b67bac94bb05f070 100644 --- a/srml/treasury/Cargo.toml +++ b/srml/treasury/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "3.1", default-features = false, features = ["derive"] } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } @@ -22,7 +22,7 @@ substrate-primitives = { path = "../../core/primitives" } [features] default = ["std"] std = [ - "serde/std", + "serde", "serde_derive", "parity-codec/std", "rstd/std", diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index 2087846233a79969a89443c713db131f641c17cd..b96928d7f8a85c38429d95ac00d4d5778008ab04 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,21 +22,18 @@ use serde_derive::{Serialize, Deserialize}; use rstd::prelude::*; use srml_support::{StorageValue, StorageMap, decl_module, decl_storage, decl_event, ensure}; -use srml_support::traits::{Currency, OnDilution, ArithmeticType}; +use srml_support::traits::{Currency, ReservableCurrency, OnDilution, OnUnbalanced, Imbalance}; use runtime_primitives::{Permill, traits::{Zero, EnsureOrigin, StaticLookup}}; use parity_codec::{Encode, Decode}; use system::ensure_signed; -type BalanceOf = <::Currency as ArithmeticType>::Type; +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type PositiveImbalanceOf = <::Currency as Currency<::AccountId>>::PositiveImbalance; +type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; -/// Our module's configuration trait. All our types and consts go in here. If the -/// module is dependent on specific other modules, then their configuration traits -/// should be added to our implied traits list. -/// -/// `system::Trait` should always be included in our implied traits. pub trait Trait: system::Trait { /// The staking balance. - type Currency: ArithmeticType + Currency>; + type Currency: Currency + ReservableCurrency; /// Origin from which approvals must come. type ApproveOrigin: EnsureOrigin; @@ -46,14 +43,17 @@ pub trait Trait: system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; + + /// Handler for the unbalanced increase when minting cash from the "Pot". + type MintedForSpending: OnUnbalanced>; + + /// Handler for the unbalanced decrease when slashing for a rejected proposal. + type ProposalRejection: OnUnbalanced>; } type ProposalIndex = u32; -// The module declaration. This states the entry points that we handle. The -// macro takes care of the marshalling of arguments and dispatch. decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what its working on. pub struct Module for enum Call where origin: T::Origin { fn deposit_event() = default; /// Put forward a suggestion for spending. A deposit proportional to the value @@ -103,7 +103,8 @@ decl_module! { let proposal = >::take(proposal_id).ok_or("No proposal at that index")?; let value = proposal.bond; - let _ = T::Currency::slash_reserved(&proposal.proposer, value); + let imbalance = T::Currency::slash_reserved(&proposal.proposer, value).0; + T::ProposalRejection::on_unbalanced(imbalance); } /// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary @@ -116,7 +117,7 @@ decl_module! { >::mutate(|v| v.push(proposal_id)); } - fn on_finalise(n: T::BlockNumber) { + fn on_finalize(n: T::BlockNumber) { // Check to see if we should spend some funds! if (n % Self::spend_period()).is_zero() { Self::spend_funds(); @@ -168,7 +169,6 @@ decl_storage! { } } -/// An event in this module. decl_event!( pub enum Event where @@ -202,6 +202,7 @@ impl Module { Self::deposit_event(RawEvent::Spending(budget_remaining)); let mut missed_any = false; + let mut imbalance = >::zero(); >::mutate(|v| { v.retain(|&index| { // Should always be true, but shouldn't panic if false or we're screwed. @@ -214,7 +215,7 @@ impl Module { let _ = T::Currency::unreserve(&p.proposer, p.bond); // provide the allocation. - T::Currency::increase_free_balance_creating(&p.beneficiary, p.value); + imbalance.subsume(T::Currency::deposit_creating(&p.beneficiary, p.value)); Self::deposit_event(RawEvent::Awarded(index, p.value, p.beneficiary)); false @@ -228,6 +229,8 @@ impl Module { }); }); + T::MintedForSpending::on_unbalanced(imbalance); + if !missed_any { // burn some proportion of the remaining budget if we run a surplus. let burn = (Self::burn() * budget_remaining).min(budget_remaining); @@ -261,7 +264,7 @@ mod tests { use srml_support::{impl_outer_origin, assert_ok, assert_noop}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_primitives::BuildStorage; - use runtime_primitives::traits::{BlakeTwo256, OnFinalise, IdentityLookup}; + use runtime_primitives::traits::{BlakeTwo256, OnFinalize, IdentityLookup}; use runtime_primitives::testing::{Digest, DigestItem, Header}; impl_outer_origin! { @@ -278,7 +281,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; - type Lookup = IdentityLookup; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; @@ -287,14 +290,18 @@ mod tests { type Balance = u64; type OnNewAccount = (); type OnFreeBalanceZero = (); - type EnsureAccountLiquid = (); type Event = (); + type TransactionPayment = (); + type TransferPayment = (); + type DustRemoval = (); } impl Trait for Test { type Currency = balances::Module; type ApproveOrigin = system::EnsureRoot; type RejectOrigin = system::EnsureRoot; type Event = (); + type MintedForSpending = (); + type ProposalRejection = (); } type Balances = balances::Module; type Treasury = Module; @@ -303,6 +310,8 @@ mod tests { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(balances::GenesisConfig::{ balances: vec![(0, 100), (1, 99), (2, 1)], + transaction_base_fee: 0, + transaction_byte_fee: 0, transfer_fee: 0, creation_fee: 0, existential_deposit: 0, @@ -371,7 +380,7 @@ mod tests { assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); - >::on_finalise(1); + >::on_finalize(1); assert_eq!(Balances::free_balance(&3), 0); assert_eq!(Treasury::pot(), 100); }); @@ -382,7 +391,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_dilution(100, 100); - >::on_finalise(2); + >::on_finalize(2); assert_eq!(Treasury::pot(), 50); }); } @@ -395,7 +404,7 @@ mod tests { assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); - >::on_finalise(2); + >::on_finalize(2); assert_eq!(Balances::free_balance(&3), 0); assert_eq!(Treasury::pot(), 50); }); @@ -445,7 +454,7 @@ mod tests { assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); - >::on_finalise(2); + >::on_finalize(2); assert_eq!(Balances::free_balance(&3), 100); assert_eq!(Treasury::pot(), 0); }); @@ -459,11 +468,11 @@ mod tests { assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); - >::on_finalise(2); + >::on_finalize(2); assert_eq!(Treasury::pot(), 100); Treasury::on_dilution(100, 100); - >::on_finalise(4); + >::on_finalize(4); assert_eq!(Balances::free_balance(&3), 150); assert_eq!(Treasury::pot(), 25); }); diff --git a/srml/upgrade-key/Cargo.toml b/srml/upgrade-key/Cargo.toml deleted file mode 100644 index 14f4bc4de541be94750b89924d30968121c29585..0000000000000000000000000000000000000000 --- a/srml/upgrade-key/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "srml-upgrade-key" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0", default-features = false } -parity-codec = { version = "3.1", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -consensus = { package = "srml-consensus", path = "../consensus", default-features = false } - -[features] -default = ["std"] -std = [ - "serde/std", - "parity-codec/std", - "sr-std/std", - "sr-primitives/std", - "srml-support/std", - "system/std", - "consensus/std", -] diff --git a/srml/upgrade-key/src/lib.rs b/srml/upgrade-key/src/lib.rs deleted file mode 100644 index a55251186b355421e0638fba76d08aba9e8d7538..0000000000000000000000000000000000000000 --- a/srml/upgrade-key/src/lib.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! The Example: A simple example of a runtime module demonstrating -//! concepts, APIs and structures common to most runtime modules. - -#![cfg_attr(not(feature = "std"), no_std)] - -use sr_std::prelude::*; -use sr_primitives::traits::StaticLookup; -use srml_support::{StorageValue, decl_module, decl_event, decl_storage, ensure}; -use system::ensure_signed; - -pub trait Trait: consensus::Trait + system::Trait { - /// The overarching event type. - type Event: From> + Into<::Event>; -} - -decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what its working on. - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - fn upgrade(origin, new: Vec) { - // This is a public call, so we ensure that the origin is some signed account. - let _sender = ensure_signed(origin)?; - ensure!(_sender == Self::key(), "only the current upgrade key can use the upgrade_key module"); - - >::set_code(new)?; - Self::deposit_event(RawEvent::Upgraded); - } - - fn set_key(origin, new: ::Source) { - // This is a public call, so we ensure that the origin is some signed account. - let _sender = ensure_signed(origin)?; - ensure!(_sender == Self::key(), "only the current upgrade key can use the upgrade_key module"); - let new = T::Lookup::lookup(new)?; - - Self::deposit_event(RawEvent::KeyChanged(Self::key())); - >::put(new); - } - } -} - -/// An event in this module. -decl_event!( - pub enum Event where AccountId = ::AccountId { - /// An upgrade just happened. - Upgraded, - /// An upgrade just happened; old key is supplied as an argument. - KeyChanged(AccountId), - } -); - -decl_storage! { - trait Store for Module as UpgradeKey { - Key get(key) config(): T::AccountId; - } -} diff --git a/subkey/Cargo.toml b/subkey/Cargo.toml index 868ab3f74478dcdb9399ec0be30908f4da14e1c6..984820a1238467637dee26bf22322a03f8cb496f 100644 --- a/subkey/Cargo.toml +++ b/subkey/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "subkey" -version = "0.1.0" +version = "0.2.0" authors = ["Parity Technologies "] edition = "2018" @@ -8,6 +8,11 @@ edition = "2018" substrate-primitives = { version = "*", path = "../core/primitives" } rand = "0.6" clap = { version = "~2.32", features = ["yaml"] } +tiny-bip39 = "0.6.0" +rustc-hex = "2.0" +substrate-bip39 = { git = "https://github.com/paritytech/substrate-bip39" } +schnorrkel = "0.1" +hex = "0.3" [features] bench = [] diff --git a/subkey/README.adoc b/subkey/README.adoc index e895ab07adae8ae7c20a8aa43242f43bd7cf6a4c..7fe194eb82b701e0821391eacb465f89454f8add 100644 --- a/subkey/README.adoc +++ b/subkey/README.adoc @@ -1,22 +1,55 @@ = Subkey -A key generation utility with vanity address support. +Subkey is a commandline utility included with Substrate that generates or restores Substrate keys. -Usage: +`subkey` will use the http://wiki.polkadot.network/en/latest/polkadot/learn/cryptography/#keypairs-and-signing[sr25519] cryptography by default. If you need to use the older ed25519 cryptography to generate or restore your key pass the `--ed25519` flag to any of the commands. - subkey +== Usage -Sample use: +=== Generate a random account - $ subkey -or - $ subkey polka -or - $ subkey polka 3 +```bash +subkey generate +``` +Will output a mnemonic phrase and give you the seed, public key, and address of a new account. DO NOT SHARE your mnemonic or seed with ANYONE it will give them access to your funds. If someone is making a transfer to you they will only need your **Address**. -Result: +=== Inspecting a key - 5CxS39ykKsmPetYQjTqW6aJXkSChnuvPdziA8uphuPaCyRZ1: 406ac59ccbb8358f7c95b726d3ccb039afe35e2dd62045189d1abae8d7805b8a (54%) - 5CujMhFmChyq3AMUwMasfbqSpZYpbFfZS5UQ7zUn2d63CGBo: 5b6ac59ccbb8358f7c95b726d3ccb039afe35e2dd62045189d1abae8d7805b8a (69%) - 5EfdN3zChABKsXT9bEg33zqPsBu4YCu1h7yoovvjtsUMqyFU: c46ac59ccbb8358f7c95b726d3ccb039afe35e2dd62045189d1abae8d7805b8a (69%) +You can inspect a given URI (mnemonic, seed, public key, or address) and recover the public key and the address. + +```bash +subkey inspect + +OUTPUT: + Public key (hex): 0x461edcf1ba99e43f50dec4bdeb3d1a2cf521ad7c3cd0eeee5cd3314e50fd424c + Address (SS58): 5DeeNqcAcaHDSed2HYnqMDK7JHcvxZ5QUE9EKmjc5snvU6wF +``` + +=== Signing + +`subkey` expects a message to come in on STDIN, one way to sign a message would look like this: + +```bash +echo | subkey sign + +OUTPUT: +a69da4a6ccbf81dbbbfad235fa12cf8528c18012b991ae89214de8d20d29c1280576ced6eb38b7406d1b7e03231df6dd4a5257546ddad13259356e1c3adfb509 +``` + +=== Verifying a signature + +```bash +echo | subkey verify
+ +OUTPUT: +Signature verifies correctly. +``` + +=== Using the vanity generator + +You can use the included vanity generator to find a seed that provides an address which includes the desired pattern. Be warned, depending on your hardware this may take a while. + +```bash +subkey vanity 1337 +``` diff --git a/subkey/src/cli.yml b/subkey/src/cli.yml index 57cf98bdf2e5024c1364ce1f3e9d3f52a90bcbae..cc131703eb8df23b4d7599b258c5f0971cb71f7a 100644 --- a/subkey/src/cli.yml +++ b/subkey/src/cli.yml @@ -1,20 +1,63 @@ name: subkey author: "Parity Team " -about: A substrate key utility +about: Utility for generating and restoring with Substrate keys +args: + - ed25519: + short: e + long: ed25519 + help: Use Ed25519/BIP39 cryptography + takes_value: false + - sr25519: + short: s + long: sr25519 + help: Use Schnorr/Ristretto x25519/BIP39 cryptography + takes_value: false + - password: + short: p + long: password + takes_value: true + required: false + help: The password for the key subcommands: - generate: about: Generate a random account - - restore: - about: Gets a public key and a SS58 address from the provided seed phrase + - inspect: + about: Gets a public key and a SS58 address from the provided Secret URI args: - - seed: + - uri: index: 1 required: true - help: 32 bytes long seed phrase used to restore the public key. If the provided seed is shorter than that, then - it will be right-padded with 0x20 bytes (ASCII space). If the provided seed is longer than - 32 bytes then seed will be truncated. + help: A Key URI to be inspected. May be a secret seed, secret URI (with derivation paths and password), SS58 or public URI. + - sign: + about: Sign a message, provided on STDIN, with a given (secret) key + args: + - suri: + index: 1 + required: true + help: The secret key URI. + - hex: + short: h + long: hex + help: The message on STDIN is hex-encoded data + takes_value: false + - verify: + about: Verify a signature for a message, provided on STDIN, with a given (public or secret) key + args: + - sig: + index: 1 + required: true + help: Signature, hex-encoded. + - uri: + index: 2 + required: true + help: The public or secret key URI. + - hex: + short: h + long: hex + help: The message on STDIN is hex-encoded data + takes_value: false - vanity: - about: Generate vanity address + about: Generate a seed that provides a vanity address args: - pattern: index: 1 diff --git a/subkey/src/main.rs b/subkey/src/main.rs index 48fb7ad1227028412716f1f634aa11c4a5c5192a..5caf58d45ba14cda8e06f133ce4bd3744e46755c 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,61 +18,203 @@ #[cfg(feature = "bench")] extern crate test; +extern crate substrate_bip39; +extern crate rustc_hex; + +use std::io::{stdin, Read}; use clap::load_yaml; use rand::{RngCore, rngs::OsRng}; -use substrate_primitives::{ed25519::Pair, hexdisplay::HexDisplay}; +use substrate_bip39::mini_secret_from_entropy; +use bip39::{Mnemonic, Language, MnemonicType}; +use substrate_primitives::{ed25519, sr25519, hexdisplay::HexDisplay, Pair, crypto::Ss58Codec}; +use schnorrkel::keys::MiniSecretKey; mod vanity; -fn print_account(seed: &[u8; 32]) { - let pair = Pair::from_seed(seed); - println!("Seed 0x{} is account:\n Public key (hex): 0x{}\n Address (SS58): {}", - HexDisplay::from(seed), - HexDisplay::from(&pair.public().0), - pair.public().to_ss58check() - ); +trait Crypto { + type Seed: AsRef<[u8]> + AsMut<[u8]> + Sized + Default; + type Pair: Pair; + fn generate_phrase() -> String { + Mnemonic::new(MnemonicType::Words12, Language::English).phrase().to_owned() + } + fn generate_seed() -> Self::Seed { + let mut seed: Self::Seed = Default::default(); + OsRng::new().unwrap().fill_bytes(seed.as_mut()); + seed + } + fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed; + fn pair_from_seed(seed: &Self::Seed) -> Self::Pair; + fn pair_from_suri(phrase: &str, password: Option<&str>) -> Self::Pair { + Self::pair_from_seed(&Self::seed_from_phrase(phrase, password)) + } + fn ss58_from_pair(pair: &Self::Pair) -> String; + fn public_from_pair(pair: &Self::Pair) -> Vec; + fn seed_from_pair(_pair: &Self::Pair) -> Option<&Self::Seed> { None } + fn print_from_seed(seed: &Self::Seed) { + let pair = Self::pair_from_seed(seed); + println!("Seed 0x{} is account:\n Public key (hex): 0x{}\n Address (SS58): {}", + HexDisplay::from(&seed.as_ref()), + HexDisplay::from(&Self::public_from_pair(&pair)), + Self::ss58_from_pair(&pair) + ); + } + fn print_from_phrase(phrase: &str, password: Option<&str>) { + let seed = Self::seed_from_phrase(phrase, password); + let pair = Self::pair_from_seed(&seed); + println!("Phrase `{}` is account:\n Seed: 0x{}\n Public key (hex): 0x{}\n Address (SS58): {}", + phrase, + HexDisplay::from(&seed.as_ref()), + HexDisplay::from(&Self::public_from_pair(&pair)), + Self::ss58_from_pair(&pair) + ); + } + fn print_from_uri(uri: &str, password: Option<&str>) where ::Public: Sized + Ss58Codec + AsRef<[u8]> { + if let Ok(pair) = Self::Pair::from_string(uri, password) { + let seed_text = Self::seed_from_pair(&pair) + .map_or_else(Default::default, |s| format!("\n Seed: 0x{}", HexDisplay::from(&s.as_ref()))); + println!("Secret Key URI `{}` is account:{}\n Public key (hex): 0x{}\n Address (SS58): {}", + uri, + seed_text, + HexDisplay::from(&Self::public_from_pair(&pair)), + Self::ss58_from_pair(&pair) + ); + } + if let Ok(public) = ::Public::from_string(uri) { + println!("Public Key URI `{}` is account:\n Public key (hex): 0x{}\n Address (SS58): {}", + uri, + HexDisplay::from(&public.as_ref()), + public.to_ss58check() + ); + } + } } -fn main() { - let yaml = load_yaml!("cli.yml"); - let matches = clap::App::from_yaml(yaml).get_matches(); +struct Ed25519; + +impl Crypto for Ed25519 { + type Seed = [u8; 32]; + type Pair = ed25519::Pair; + + fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed { + Sr25519::seed_from_phrase(phrase, password) + } + fn pair_from_suri(suri: &str, password_override: Option<&str>) -> Self::Pair { + ed25519::Pair::from_legacy_string(suri, password_override) + } + fn pair_from_seed(seed: &Self::Seed) -> Self::Pair { ed25519::Pair::from_seed(seed.clone()) } + fn ss58_from_pair(pair: &Self::Pair) -> String { pair.public().to_ss58check() } + fn public_from_pair(pair: &Self::Pair) -> Vec { (&pair.public().0[..]).to_owned() } + fn seed_from_pair(pair: &Self::Pair) -> Option<&Self::Seed> { Some(pair.seed()) } +} + +struct Sr25519; + +impl Crypto for Sr25519 { + type Seed = [u8; 32]; + type Pair = sr25519::Pair; + + fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed { + mini_secret_from_entropy( + Mnemonic::from_phrase(phrase, Language::English) + .unwrap_or_else(|_| + panic!("Phrase is not a valid BIP-39 phrase: \n {}", phrase) + ) + .entropy(), + password.unwrap_or("") + ) + .expect("32 bytes can always build a key; qed") + .to_bytes() + } + + fn pair_from_suri(suri: &str, password: Option<&str>) -> Self::Pair { + sr25519::Pair::from_string(suri, password).expect("Invalid phrase") + } + fn pair_from_seed(seed: &Self::Seed) -> Self::Pair { + MiniSecretKey::from_bytes(seed) + .expect("32 bytes can always build a key; qed") + .into() + } + fn ss58_from_pair(pair: &Self::Pair) -> String { pair.public().to_ss58check() } + fn public_from_pair(pair: &Self::Pair) -> Vec { (&pair.public().0[..]).to_owned() } +} + +fn execute>(matches: clap::ArgMatches) where + <::Pair as Pair>::Signature: AsRef<[u8]> + AsMut<[u8]> + Default, + <::Pair as Pair>::Public: Sized + AsRef<[u8]> + Ss58Codec + AsRef<<::Pair as Pair>::Public>, +{ + let password = matches.value_of("password"); match matches.subcommand() { ("generate", Some(_matches)) => { - let mut seed = [0u8; 32]; - OsRng::new().unwrap().fill_bytes(&mut seed[..]); - print_account(&seed); - } + // create a new randomly generated mnemonic phrase + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + C::print_from_phrase(mnemonic.phrase(), password); + }, ("vanity", Some(matches)) => { let desired: String = matches.value_of("pattern").map(str::to_string).unwrap_or_default(); - let key = vanity::generate_key(&desired).expect("Key generation failed"); - println!("Found account with score {}%", key.score); - print_account(&key.seed); + let key = vanity::generate_key::(&desired).expect("Key generation failed"); + C::print_from_seed(&key.seed); } - ("restore", Some(matches)) => { - // This subcommand is probably obsolete, see - // https://github.com/paritytech/substrate/issues/1063 - - let mut raw_seed = matches.value_of("seed") - .map(str::as_bytes) - .expect("seed parameter is required; thus it can't be None; qed"); - - if raw_seed.len() > 32 { - raw_seed = &raw_seed[..32]; - println!("seed is too long and will be truncated to: {}", HexDisplay::from(&raw_seed)); - } - - // Copy the raw_seed into a buffer that already contains ' ' 0x20. - // This will effectively get us padding for seeds shorter than 32. - let mut seed = [' ' as u8; 32]; - let len = raw_seed.len().min(32); - seed[..len].copy_from_slice(&raw_seed[..len]); - print_account(&seed); + ("inspect", Some(matches)) => { + // TODO: Accept public key with derivation path. + let uri = matches.value_of("uri") + .expect("URI parameter is required; thus it can't be None; qed"); + C::print_from_uri(uri, password); }, + ("sign", Some(matches)) => { + let suri = matches.value_of("suri") + .expect("secret URI parameter is required; thus it can't be None; qed"); + let pair = C::pair_from_suri(suri, password); + let mut message = vec![]; + stdin().lock().read_to_end(&mut message).expect("Error reading from stdin"); + if matches.is_present("hex") { + message = hex::decode(&message).expect("Invalid hex in message"); + } + let sig = pair.sign(&message); + println!("{}", hex::encode(&sig)); + } + ("verify", Some(matches)) => { + let sig_data = matches.value_of("sig") + .expect("signature parameter is required; thus it can't be None; qed"); + let mut sig = <::Pair as Pair>::Signature::default(); + let sig_data = hex::decode(sig_data).expect("signature is invalid hex"); + if sig_data.len() != sig.as_ref().len() { + panic!("signature is an invalid length. {} bytes is not the expected value of {} bytes", sig_data.len(), sig.as_ref().len()); + } + sig.as_mut().copy_from_slice(&sig_data); + let uri = matches.value_of("uri") + .expect("public uri parameter is required; thus it can't be None; qed"); + let pubkey = <::Pair as Pair>::Public::from_string(uri).ok().or_else(|| + ::Pair::from_string(uri, password).ok().map(|p| p.public()) + ).expect("Invalid URI; expecting either a secret URI or a public URI."); + let mut message = vec![]; + stdin().lock().read_to_end(&mut message).expect("Error reading from stdin"); + if matches.is_present("hex") { + message = hex::decode(&message).expect("Invalid hex in message"); + } + if <::Pair as Pair>::verify(&sig, &message, &pubkey) { + println!("Signature verifies correctly.") + } else { + println!("Signature invalid.") + } + } _ => print_usage(&matches), } } +fn main() { + let yaml = load_yaml!("cli.yml"); + let matches = clap::App::from_yaml(yaml) + .version(env!("CARGO_PKG_VERSION")) + .get_matches(); + + if matches.is_present("ed25519") { + execute::(matches) + } else { + execute::(matches) + } +} + fn print_usage(matches: &clap::ArgMatches) { println!("{}", matches.usage()); } diff --git a/subkey/src/vanity.rs b/subkey/src/vanity.rs index a621ccd0ef0c9c0d45eea5d9e88b01d03e01f94f..785eb95aa5b203ac5c53e62abea30b6c090259ae 100644 --- a/subkey/src/vanity.rs +++ b/subkey/src/vanity.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,7 +15,7 @@ // along with Substrate. If not, see . use rand::{rngs::OsRng, RngCore}; -use substrate_primitives::ed25519::Pair; +use super::Crypto; fn good_waypoint(done: u64) -> u64 { match done { @@ -38,9 +38,9 @@ fn next_seed(mut seed: [u8; 32]) -> [u8; 32] { /// A structure used to carry both Pair and seed. /// This should usually NOT been used. If unsure, use Pair. -pub struct KeyPair { - pub pair: Pair, - pub seed: [u8; 32], +pub(super) struct KeyPair { + pub pair: C::Pair, + pub seed: C::Seed, pub score: usize, } @@ -57,7 +57,7 @@ fn calculate_score(_desired: &str, key: &str) -> usize { 0 } -pub fn generate_key(desired: &str) -> Result { +pub(super) fn generate_key>(desired: &str) -> Result, &str> { if desired.is_empty() { return Err("Pattern must not be empty"); } @@ -77,8 +77,8 @@ pub fn generate_key(desired: &str) -> Result { OsRng::new().unwrap().fill_bytes(&mut seed[..]); } - let p = Pair::from_seed(&seed); - let ss58 = p.public().to_ss58check(); + let p = C::pair_from_seed(&seed); + let ss58 = C::ss58_from_pair(&p); let score = calculate_score(&desired, &ss58); if score > best || desired.len() < 2 { best = score; @@ -104,12 +104,14 @@ pub fn generate_key(desired: &str) -> Result { #[cfg(test)] mod tests { use super::*; + use super::super::Ed25519; + use substrate_primitives::Pair; #[cfg(feature = "bench")] use test::Bencher; #[test] fn test_generation_with_single_char() { - assert!(generate_key("j").unwrap().pair.public().to_ss58check().contains("j")); + assert!(generate_key::("j").unwrap().pair.public().to_ss58check().contains("j")); } #[test] diff --git a/test-utils/chain-spec-builder/Cargo.lock b/test-utils/chain-spec-builder/Cargo.lock index feccfa14ef41cbdf554d413701c37bbe1349cfb1..2d5311d502037e719be355a1c66e4a8b247e7b73 100644 --- a/test-utils/chain-spec-builder/Cargo.lock +++ b/test-utils/chain-spec-builder/Cargo.lock @@ -1781,7 +1781,6 @@ dependencies = [ "srml-system 0.1.0", "srml-timestamp 0.1.0", "srml-treasury 0.1.0", - "srml-upgrade-key 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", "substrate-keyring 0.1.0", @@ -3006,24 +3005,6 @@ dependencies = [ "substrate-primitives 0.1.0", ] -[[package]] -name = "srml-upgrade-key" -version = "0.1.0" -dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", - "sr-primitives 0.1.0", - "sr-std 0.1.0", - "srml-consensus 0.1.0", - "srml-support 0.1.0", - "srml-support-procedural 0.1.0", - "srml-system 0.1.0", - "substrate-primitives 0.1.0", -] - [[package]] name = "stable_deref_trait" version = "1.1.1" diff --git a/test-utils/chain-spec-builder/src/cli.yml b/test-utils/chain-spec-builder/src/cli.yml index 08c0233c31090ae4d6a5091651324b25a8c14fcb..f4b1cb7e2eaaab0e5d2df01a6801d36a3de527b8 100644 --- a/test-utils/chain-spec-builder/src/cli.yml +++ b/test-utils/chain-spec-builder/src/cli.yml @@ -16,9 +16,9 @@ args: takes_value: true multiple: true required: true -- upgrade_key_seed: +- sudo_key_seed: short: u - value_name: UPGRADE_KEY_SEED - help: Upgrade key seed + value_name: SUDO_KEY_SEED + help: Sudo key seed takes_value: true required: true diff --git a/test-utils/chain-spec-builder/src/main.rs b/test-utils/chain-spec-builder/src/main.rs index b899f9c1fcab73f863eeb4b4df799dbc8db723e9..c7b4dd99d8ab28c760f37c543be55b0bc245ce52 100644 --- a/test-utils/chain-spec-builder/src/main.rs +++ b/test-utils/chain-spec-builder/src/main.rs @@ -16,11 +16,11 @@ fn genesis_constructor() -> chain_spec::GenesisConfig { .map(chain_spec::get_authority_id_from_seed) .collect(); - let upgrade_key_seed = matches.value_of("upgrade_key_seed").unwrap(); - let upgrade_key = chain_spec::get_authority_id_from_seed(upgrade_key_seed); + let sudo_key_seed = matches.value_of("sudo_key_seed").unwrap(); + let sudo_key = chain_spec::get_authority_id_from_seed(sudo_key_seed); chain_spec::testnet_genesis( authorities, - upgrade_key.into(), + sudo_key.into(), Some(endowed_accounts), ) }