diff --git a/.gitignore b/.gitignore index 6398c09fe796278130978c2a8598ee9270399388..353d49df28f34b896567b0aa91bb08e056a5832c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ rls*.log .local **/hfuzz_target/ **/hfuzz_workspace/ +.cargo/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ad7900fe1b6a316727e885b3639e5ad9df196783..d047489fd281cce947e5a01d356e603eed0a55df 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -121,7 +121,7 @@ check-signed-tag: image: parity/tools:latest <<: *kubernetes-build only: - - tags + - /^ci-release-.*$/ - /^v[0-9]+\.[0-9]+\.[0-9]+.*$/ script: - ./.maintain/gitlab/check_signed.sh @@ -175,6 +175,8 @@ cargo-check-benches: <<: *docker-env script: - BUILD_DUMMY_WASM_BINARY=1 time cargo +nightly check --benches --all + - cargo run --release -p node-bench -- ::node::import::native::sr25519::transfer_keep_alive::paritydb::small + - cargo run --release -p node-bench -- ::trie::read::small - sccache -s cargo-check-subkey: @@ -193,22 +195,13 @@ test-linux-stable: &test-linux variables: # Enable debug assertions since we are running optimized builds for testing # but still want to have debug assertions. - RUSTFLAGS: -Cdebug-assertions=y + RUSTFLAGS: "-Cdebug-assertions=y -Dwarnings" except: variables: - $DEPLOY_TAG script: - - WASM_BUILD_NO_COLOR=1 time cargo test --all --release --verbose --locked |& - tee output.log + - WASM_BUILD_NO_COLOR=1 time cargo test --all --release --verbose --locked - sccache -s - - echo "____Test job successful, checking for warnings____" - - awk '/^warning:/,/^$/ { print }' output.log > ${CI_COMMIT_SHORT_SHA}_warnings.log - - if [ -s ${CI_COMMIT_SHORT_SHA}_warnings.log ]; then - cat ${CI_COMMIT_SHORT_SHA}_warnings.log; - exit 1; - else - echo "___No warnings___"; - fi test-dependency-rules: stage: test @@ -242,7 +235,7 @@ test-frame-staking: - $DEPLOY_TAG script: - cd frame/staking/ - - WASM_BUILD_NO_COLOR=1 time cargo test --release --verbose --no-default-features --features "std testing-utils" + - WASM_BUILD_NO_COLOR=1 time cargo test --release --verbose --no-default-features --features "std" - sccache -s test-frame-examples-compile-to-wasm: @@ -399,6 +392,7 @@ build-linux-substrate: &build-binary - sha256sum ./artifacts/substrate/substrate | tee ./artifacts/substrate/substrate.sha256 - printf '\n# building node-template\n\n' - ./.maintain/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz + - cp -r .maintain/docker/substrate.Dockerfile ./artifacts/substrate/ - sccache -s @@ -416,6 +410,7 @@ build-linux-subkey: &build-subkey sed -n -E 's/^subkey ([0-9.]+.*)/\1/p' | tee ./artifacts/subkey/VERSION; - sha256sum ./artifacts/subkey/subkey | tee ./artifacts/subkey/subkey.sha256 + - cp -r .maintain/docker/subkey.Dockerfile ./artifacts/subkey/ - sccache -s build-macos-subkey: @@ -587,7 +582,7 @@ publish-draft-release: stage: publish image: parity/tools:latest only: - - tags + - /^ci-release-.*$/ - /^v[0-9]+\.[0-9]+\.[0-9]+.*$/ script: - ./.maintain/gitlab/publish_draft_release.sh @@ -598,8 +593,8 @@ publish-to-crates-io: stage: publish <<: *docker-env only: - - tags - /^ci-release-.*$/ + - /^v[0-9]+\.[0-9]+\.[0-9]+.*$/ script: - cargo install cargo-unleash ${CARGO_UNLEASH_INSTALL_PARAMS} - cargo unleash em-dragons --no-check ${CARGO_UNLEASH_PKG_DEF} diff --git a/.maintain/gitlab/check_line_width.sh b/.maintain/gitlab/check_line_width.sh index f382d630b183c6396115cc1e76e77dfab4c20047..85092260b6a649187de6d03c0936cb0d54fc751e 100755 --- a/.maintain/gitlab/check_line_width.sh +++ b/.maintain/gitlab/check_line_width.sh @@ -2,47 +2,49 @@ # # check if line width of rust source files is not beyond x characters # +set -e +set -o pipefail +BASE_ORIGIN="origin" +BASE_BRANCH_NAME="master" +LINE_WIDTH="120" +GOOD_LINE_WIDTH="100" +BASE_BRANCH="${BASE_ORIGIN}/${BASE_BRANCH_NAME}" -BASE_BRANCH="origin/master" -LINE_WIDTH="121" -GOOD_LINE_WIDTH="101" - - -git diff --name-only ${BASE_BRANCH}...${CI_COMMIT_SHA} \*.rs | ( while read file +git fetch ${BASE_ORIGIN} ${BASE_BRANCH_NAME} --depth 1 +git diff --name-only ${BASE_BRANCH} -- \*.rs | ( while read file do if [ ! -f ${file} ]; then echo "Skipping removed file." - elif git diff ${BASE_BRANCH}...${CI_COMMIT_SHA} ${file} | grep -q "^+.\{${LINE_WIDTH}\}" + elif git diff ${BASE_BRANCH} -- ${file} | grep -q "^+.\{$(( $LINE_WIDTH + 1 ))\}" then if [ -z "${FAIL}" ] then - echo "| warning!" - echo "| Lines should not be longer than 120 characters." + echo "| error!" + echo "| Lines must not be longer than ${LINE_WIDTH} characters." echo "| " echo "| see more https://wiki.parity.io/Substrate-Style-Guide" echo "|" FAIL="true" fi echo "| file: ${file}" - git diff ${BASE_BRANCH}...${CI_COMMIT_SHA} ${file} \ - | grep -n "^+.\{${LINE_WIDTH}\}" + git diff ${BASE_BRANCH} -- ${file} \ + | grep -n "^+.\{$(( $LINE_WIDTH + 1))\}" echo "|" else - if git diff ${BASE_BRANCH}...${CI_COMMIT_SHA} ${file} | grep -q "^+.\{${GOOD_LINE_WIDTH}\}" + if git diff ${BASE_BRANCH} -- ${file} | grep -q "^+.\{$(( $GOOD_LINE_WIDTH + 1 ))\}" then if [ -z "${FAIL}" ] then echo "| warning!" - echo "| Lines should be longer than 100 characters only in exceptional circumstances!" + echo "| Lines should be longer than ${GOOD_LINE_WIDTH} characters only in exceptional circumstances!" echo "| " echo "| see more https://wiki.parity.io/Substrate-Style-Guide" echo "|" fi echo "| file: ${file}" - git diff ${BASE_BRANCH}...${CI_COMMIT_SHA} ${file} \ - | grep -n "^+.\{${LINE_WIDTH}\}" + git diff ${BASE_BRANCH} -- ${file} | grep -n "^+.\{$(( $GOOD_LINE_WIDTH + 1 ))\}" echo "|" fi fi diff --git a/.maintain/gitlab/check_polkadot_companion_build.sh b/.maintain/gitlab/check_polkadot_companion_build.sh index c2ecf8cb6a071b116af4591097251efdba254746..281fa8e1e8d4621a253fb4bdf0815a1859564dcb 100755 --- a/.maintain/gitlab/check_polkadot_companion_build.sh +++ b/.maintain/gitlab/check_polkadot_companion_build.sh @@ -12,7 +12,7 @@ github_api_substrate_pull_url="https://api.github.com/repos/paritytech/substrate/pulls" # use github api v3 in order to access the data without authentication -github_header="Accept: application/vnd.github.v3+json" +github_header="Authorization: token ${GITHUB_PR_TOKEN}" boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; } boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; } @@ -83,12 +83,12 @@ then if [ "${pr_companion}" ] then boldprint "companion pr specified/detected: #${pr_companion}" - git fetch --depth 1 origin refs/pull/${pr_companion}/head:pr/${pr_companion} + git fetch origin refs/pull/${pr_companion}/head:pr/${pr_companion} git checkout pr/${pr_companion} git merge origin/master else pr_ref="$(grep -Po '"ref"\s*:\s*"\K(?!master)[^"]*' "${pr_data_file}")" - if git fetch --depth 1 origin "$pr_ref":branch/"$pr_ref" 2>/dev/null + if git fetch origin "$pr_ref":branch/"$pr_ref" 2>/dev/null then boldprint "companion branch detected: $pr_ref" git checkout branch/"$pr_ref" diff --git a/.maintain/gitlab/check_polkadot_companion_status.sh b/.maintain/gitlab/check_polkadot_companion_status.sh index 5387e68f25cbba284433b8946f20f6eacfc76b9f..b781831055b6d500d133425fe7c0860a807938cb 100755 --- a/.maintain/gitlab/check_polkadot_companion_status.sh +++ b/.maintain/gitlab/check_polkadot_companion_status.sh @@ -7,7 +7,7 @@ github_api_substrate_pull_url="https://api.github.com/repos/paritytech/substrate/pulls" github_api_polkadot_pull_url="https://api.github.com/repos/paritytech/polkadot/pulls" # use github api v3 in order to access the data without authentication -github_header="Accept: application/vnd.github.v3+json" +github_header="Authorization: token ${GITHUB_PR_TOKEN}" boldprint () { printf "|\n| \033[1m${@}\033[0m\n|\n" ; } boldcat () { printf "|\n"; while read l; do printf "| \033[1m${l}\033[0m\n"; done; printf "|\n" ; } diff --git a/.maintain/gitlab/skip_if_draft.sh b/.maintain/gitlab/skip_if_draft.sh index a234a6c18e21c8e415c840f6bba1cf988d2a744c..cf6ea6a5b31155da9d6ac0c09079f4dffcec2dfa 100755 --- a/.maintain/gitlab/skip_if_draft.sh +++ b/.maintain/gitlab/skip_if_draft.sh @@ -2,7 +2,7 @@ url="https://api.github.com/repos/paritytech/substrate/pulls/${CI_COMMIT_REF_NAME}" echo "[+] API URL: $url" -draft_state=$(curl "$url" | jq -r .draft) +draft_state=$(curl -H "Authorization: token ${GITHUB_PR_TOKEN}" "$url" | jq -r .draft) echo "[+] Draft state: $draft_state" if [ "$draft_state" = 'true' ]; then diff --git a/.maintain/monitoring/alerting-rules/alerting-rules.yaml b/.maintain/monitoring/alerting-rules/alerting-rules.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cb5b3c271dd14e1fb8222ab9e3b7da54bc0d8b1f --- /dev/null +++ b/.maintain/monitoring/alerting-rules/alerting-rules.yaml @@ -0,0 +1,113 @@ +groups: +- name: polkadot.rules + rules: + + ############################################################################## + # Resource usage + ############################################################################## + + - alert: HighCPUUsage + expr: polkadot_cpu_usage_percentage >= 100 + for: 5m + labels: + severity: warning + annotations: + message: 'The node {{ $labels.instance }} has a CPU usage higher than 100% for more than 5 minutes' + + ############################################################################## + # Block production + ############################################################################## + + - alert: LowNumberOfNewBlocks + annotations: + message: 'Less than one new block per minute on instance {{ $labels.instance }}.' + expr: increase(polkadot_block_height{status="best"}[1m]) < 1 + for: 3m + labels: + severity: warning + - alert: LowNumberOfNewBlocks + annotations: + message: 'Less than one new block per minute on instance {{ $labels.instance }}.' + expr: increase(polkadot_block_height{status="best"}[1m]) < 1 + for: 10m + labels: + severity: critical + + ############################################################################## + # Block finalization + ############################################################################## + + - alert: BlockFinalizationSlow + expr: increase(polkadot_block_height{status="finalized"}[1m]) < 1 + for: 3m + labels: + severity: warning + annotations: + message: 'Finalized block on instance {{ $labels.instance }} increases by less than 1 per minute.' + - alert: BlockFinalizationSlow + expr: increase(polkadot_block_height{status="finalized"}[1m]) < 1 + for: 10m + labels: + severity: critical + annotations: + message: 'Finalized block on instance {{ $labels.instance }} increases by less than 1 per minute.' + - alert: BlockFinalizationLaggingBehind + # Under the assumption of an average block production of 6 seconds, + # "best" and "finalized" being more than 10 blocks apart would imply + # more than a 1 minute delay between block production and finalization. + expr: (polkadot_block_height_number{status="best"} - ignoring(status) polkadot_block_height_number{status="finalized"}) > 10 + for: 8m + labels: + severity: critical + annotations: + message: "Block finalization on instance {{ $labels.instance }} is behind block production by {{ $value }} for more than 8m" + + ############################################################################## + # Transaction queue + ############################################################################## + + - alert: TransactionQueueSize + expr: polkadot_sub_txpool_validations_scheduled - polkadot_sub_txpool_validations_finished > 10 + for: 10m + labels: + severity: warning + annotations: + message: 'The node {{ $labels.instance }} has more than 10 transactions in the queue for more than 10 minutes' + - alert: TransactionQueueSize + expr: polkadot_sub_txpool_validations_scheduled - polkadot_sub_txpool_validations_finished > 10 + for: 30m + labels: + severity: critical + annotations: + message: 'The node {{ $labels.instance }} has more than 10 transactions in the queue for more than 30 minutes' + + ############################################################################## + # Networking + ############################################################################## + + - alert: LowNumberOfPeers + expr: polkadot_sub_libp2p_peers_count < 3 + for: 3m + labels: + severity: warning + annotations: + message: 'The node {{ $labels.instance }} has less than 3 peers for more than 3 minutes' + - alert: LowNumberOfPeers + expr: polkadot_sub_libp2p_peers_count < 3 + for: 15m + labels: + severity: critical + annotations: + message: 'The node {{ $labels.instance }} has less than 3 peers for more than 15 minutes' + + ############################################################################## + # Others + ############################################################################## + + - alert: AuthorityDiscoveryHighDiscoveryFailure + expr: polkadot_authority_discovery_handle_value_found_event_failure / ignoring(name) polkadot_authority_discovery_dht_event_received{name="value_found"} > 0.5 + for: 2h + labels: + severity: warning + annotations: + message: "Authority discovery on node {{ $labels.instance }} fails to process more than 50 % of the values found on the DHT." diff --git a/.maintain/monitoring/grafana-dashboards/substrate-networking.json b/.maintain/monitoring/grafana-dashboards/substrate-networking.json new file mode 100644 index 0000000000000000000000000000000000000000..f18ca66c13a0774eca86ceef42795cf4b36a35d3 --- /dev/null +++ b/.maintain/monitoring/grafana-dashboards/substrate-networking.json @@ -0,0 +1,2722 @@ +{ + "__inputs": [ + { + "name": "VAR_METRIC_NAMESPACE", + "type": "constant", + "label": "Prefix of the metrics", + "value": "polkadot", + "description": "" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "6.7.3" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "panel", + "id": "heatmap", + "name": "Heatmap", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:821", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "type": "dashboard" + }, + { + "$$hashKey": "object:822", + "datasource": "$data_source", + "enable": true, + "expr": "count(count(${metric_namespace}_sub_libp2p_connections / max_over_time(${metric_namespace}_sub_libp2p_connections[1h]) < 0.1) >= count(${metric_namespace}_sub_libp2p_connections) / 10)", + "hide": false, + "iconColor": "#C4162A", + "limit": 100, + "name": "Connection losses events", + "showIn": 0, + "step": "5m", + "tags": [], + "titleFormat": "Network-wide connectivity loss", + "type": "tags" + } + ] + }, + "description": "Information related to the networking layer of Substrate", + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1590742405831, + "links": [], + "panels": [ + { + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 167, + "title": "Sync", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 101, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "1 - (${metric_namespace}_sub_libp2p_peerset_num_requested{instance=~\"${nodename}\"} - ${metric_namespace}_sub_libp2p_peers_count{instance=~\"${nodename}\"}) / ${metric_namespace}_sub_libp2p_peerset_num_requested{instance=~\"${nodename}\"}", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of peer slots filled", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1044", + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1.0", + "min": null, + "show": true + }, + { + "$$hashKey": "object:1045", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 29, + "panels": [], + "repeat": "request_protocol", + "title": "Requests (${request_protocol})", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 148, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(${metric_namespace}_sub_libp2p_requests_out_started_total{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests emitted per second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 7 + }, + "hiddenSeries": false, + "id": 151, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(${metric_namespace}_sub_libp2p_requests_in_total_count{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Requests served per second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 11 + }, + "hiddenSeries": false, + "id": 146, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(${metric_namespace}_sub_libp2p_requests_out_finished_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le)) > 0", + "instant": false, + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Median request answer time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1230", + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1231", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 11 + }, + "hiddenSeries": false, + "id": 145, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.5, sum(rate(${metric_namespace}_sub_libp2p_requests_in_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le))", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Median request serving time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 15 + }, + "hiddenSeries": false, + "id": 150, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_requests_out_finished_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le)) > 0", + "instant": false, + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "99th percentile request answer time", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 15 + }, + "hiddenSeries": false, + "id": 149, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_requests_in_total_bucket{instance=~\"${nodename}\", protocol=\"${request_protocol}\"}[5m])) by (instance, le))", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "99th percentile request serving time", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 185 + }, + "id": 23, + "panels": [], + "repeat": "notif_protocol", + "title": "Notifications (${notif_protocol})", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 186 + }, + "hiddenSeries": false, + "id": 31, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [ + { + "$$hashKey": "object:850", + "alias": "/(in)/", + "color": "#73BF69" + }, + { + "$$hashKey": "object:851", + "alias": "/(out)/", + "color": "#F2495C" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg by (direction) (irate(${metric_namespace}_sub_libp2p_notifications_sizes_count{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[$__interval]))", + "interval": "", + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average network notifications per second", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:874", + "format": "cps", + "label": "Notifs/sec", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:875", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 186 + }, + "hiddenSeries": false, + "id": 37, + "interval": "1m", + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [ + { + "$$hashKey": "object:942", + "alias": "/(in)/", + "color": "#73BF69" + }, + { + "$$hashKey": "object:943", + "alias": "/(out)/", + "color": "#F2495C" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(irate(${metric_namespace}_sub_libp2p_notifications_sizes_sum{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[$__interval])) by (direction)", + "instant": false, + "interval": "", + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average bandwidth used by notifications", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:966", + "format": "Bps", + "label": "Bandwidth", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:967", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 193 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(${metric_namespace}_sub_libp2p_out_events_notifications_sizes{instance=~\"${nodename}\", protocol=\"${notif_protocol}\", action=\"sent\"} - ignoring(action) ${metric_namespace}_sub_libp2p_out_events_notifications_sizes{instance=~\"${nodename}\", protocol=\"${notif_protocol}\", action=\"received\"}) by (instance) > 0", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Total sizes of notifications waiting to be delivered to the rest of Substrate", + "tooltip": { + "shared": false, + "sort": 1, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 193 + }, + "hiddenSeries": false, + "id": 21, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pluginVersion": "6.4.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(${metric_namespace}_sub_libp2p_notifications_sizes_sum{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[5m])) by (direction, protocol) / sum(rate(${metric_namespace}_sub_libp2p_notifications_sizes_count{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[5m])) by (direction, protocol)", + "format": "time_series", + "interval": "", + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average size of sent and received notifications in the past 5 minutes", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2050", + "format": "bytes", + "label": "Max. notification size", + "logBase": 10, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:2051", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "description": "99.9% of the time, the output queue size for this protocol is below the given value", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 201 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "hideEmpty": false, + "hideZero": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fill": 1, + "linewidth": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_notifications_queues_size_bucket{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[2m])) by (le, instance))", + "hide": false, + "interval": "", + "legendFormat": "{{protocol}}", + "refId": "A" + }, + { + "expr": "max(histogram_quantile(0.99, sum(rate(${metric_namespace}_sub_libp2p_notifications_queues_size_bucket{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[2m])) by (le, instance)))", + "interval": "", + "legendFormat": "max", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "99th percentile of queues sizes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": "300", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 201 + }, + "hiddenSeries": false, + "id": 134, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pluginVersion": "6.4.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(1.0, sum(rate(${metric_namespace}_sub_libp2p_notifications_sizes_bucket{instance=~\"${nodename}\", protocol=\"${notif_protocol}\"}[5m])) by (direction, le))", + "format": "time_series", + "interval": "", + "legendFormat": "{{direction}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Maximum size of sent and received notifications in the past 5 minutes", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1524", + "format": "bytes", + "label": "Max. notification size", + "logBase": 10, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1525", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1853 + }, + "id": 27, + "panels": [], + "title": "Transport", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 1854 + }, + "hiddenSeries": false, + "id": 19, + "interval": "1m", + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "established (in)", + "color": "#37872D" + }, + { + "alias": "established (out)", + "color": "#C4162A" + }, + { + "alias": "pending (out)", + "color": "#FF7383" + }, + { + "alias": "closed-recently", + "color": "#FADE2A", + "steppedLine": true + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(sum(${metric_namespace}_sub_libp2p_connections_opened_total{direction=\"in\", instance=~\"${nodename}\"}) by (instance) - sum(${metric_namespace}_sub_libp2p_connections_closed_total{direction=\"in\", instance=~\"${nodename}\"}) by (instance))", + "format": "time_series", + "hide": false, + "interval": "", + "legendFormat": "established (in)", + "refId": "A" + }, + { + "expr": "avg(sum(${metric_namespace}_sub_libp2p_connections_opened_total{direction=\"out\", instance=~\"${nodename}\"}) by (instance) - sum(${metric_namespace}_sub_libp2p_connections_closed_total{direction=\"out\", instance=~\"${nodename}\"}) by (instance))", + "hide": false, + "instant": false, + "interval": "", + "legendFormat": "established (out)", + "refId": "C" + }, + { + "expr": "avg(sum by (instance) (${metric_namespace}_sub_libp2p_pending_connections{instance=~\"${nodename}\"}))", + "hide": false, + "interval": "", + "legendFormat": "pending (out)", + "refId": "B" + }, + { + "expr": "avg(sum by(instance) (increase(${metric_namespace}_sub_libp2p_connections_closed_total{instance=~\"${nodename}\"}[$__interval])))", + "hide": false, + "interval": "", + "legendFormat": "closed-recently", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Average transport-level (TCP, QUIC, ...) connections per node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Connections", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 1860 + }, + "hiddenSeries": false, + "id": 39, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*/", + "color": "#FF780A" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(increase(${metric_namespace}_sub_libp2p_incoming_connections_handshake_errors_total{instance=~\"${nodename}\"}[$__interval])) by (reason)", + "interval": "", + "legendFormat": "{{reason}}", + "refId": "A" + }, + { + "expr": "avg(increase(${metric_namespace}_sub_libp2p_listeners_errors_total{instance=~\"${nodename}\"}[$__interval]))", + "interval": "", + "legendFormat": "pre-handshake", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of incoming connection errors, averaged by node", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Errors", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "max": 100, + "min": 0, + "mode": "spectrum" + }, + "dataFormat": "timeseries", + "datasource": "$data_source", + "description": "Each bucket represent a certain number of nodes using a certain bandwidth range.", + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 1860 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 4, + "legend": { + "show": false + }, + "reverseYBuckets": false, + "targets": [ + { + "expr": "${metric_namespace}_network_per_sec_bytes{instance=~\"${nodename}\"}", + "format": "time_series", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Heatmap of network bandwidth", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": "2.5m", + "yAxis": { + "decimals": null, + "format": "Bps", + "logBase": 1, + "max": null, + "min": null, + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 1866 + }, + "hiddenSeries": false, + "id": 81, + "interval": "1m", + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(increase(${metric_namespace}_sub_libp2p_pending_connections_errors_total{instance=~\"${nodename}\"}[$__interval])) by (reason)", + "interval": "", + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Dialing attempt errors, averaged per node", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 1866 + }, + "hiddenSeries": false, + "id": 46, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(increase(${metric_namespace}_sub_libp2p_connections_closed_total{instance=~\"${nodename}\"}[$__interval])) by (reason)", + "interval": "", + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disconnects, averaged per node", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "Disconnects", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1873 + }, + "id": 52, + "panels": [], + "title": "GrandPa", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 1874 + }, + "hiddenSeries": false, + "id": 54, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": true, + "values": true + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [ + { + "alias": "/discard/", + "color": "#FA6400", + "zindex": -2 + }, + { + "alias": "/keep/", + "color": "#73BF69", + "zindex": 2 + }, + { + "alias": "/process_and_discard/", + "color": "#5794F2" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(increase(${metric_namespace}_finality_grandpa_communication_gossip_validator_messages{instance=~\"${nodename}\"}[$__interval])) by (action, message)", + "interval": "", + "legendFormat": "{{message}} => {{action}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "GrandPa messages received from the network, and action", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1880 + }, + "id": 25, + "panels": [], + "repeat": null, + "title": "Kademlia", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "description": "", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 1881 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*/", + "color": "#B877D9" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "${metric_namespace}_sub_libp2p_kbuckets_num_nodes{instance=~\"${nodename}\"}", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "Number nodes in all kbuckets", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Distribution over number of entries in k-buckets", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "max": 0, + "min": null, + "mode": "histogram", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 7, + "fillGradient": 7, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 1881 + }, + "hiddenSeries": false, + "id": 35, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "60 * sum(irate(${metric_namespace}_sub_libp2p_random_kademalia_queries_total{instance=~\"${nodename}\"}[$__interval]))", + "interval": "", + "legendFormat": "Number of Kademlia random queries started per minute on all nodes", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of Kademlia discovery queries per minute on all nodes combined", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "cpm", + "label": "Queries per minute", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 1887 + }, + "hiddenSeries": false, + "id": 111, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(${metric_namespace}_sub_libp2p_kademlia_records_count{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "avg", + "refId": "A" + }, + { + "expr": "min(${metric_namespace}_sub_libp2p_kademlia_records_count{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "min", + "refId": "B" + }, + { + "expr": "max(${metric_namespace}_sub_libp2p_kademlia_records_count{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of Kademlia records (average/min/max per node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 1887 + }, + "hiddenSeries": false, + "id": 112, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "min", + "lines": false + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(${metric_namespace}_sub_libp2p_kademlia_records_sizes_total{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "avg", + "refId": "A" + }, + { + "expr": "min(${metric_namespace}_sub_libp2p_kademlia_records_sizes_total{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "min", + "refId": "B" + }, + { + "expr": "max(${metric_namespace}_sub_libp2p_kademlia_records_sizes_total{instance=~\"${nodename}\"})", + "interval": "", + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Total size of Kademlia records (average/min/max per node)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 1891 + }, + "hiddenSeries": false, + "id": 68, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(\n # The amount of inflight Kademlia queries per node.\r\n sum by (instance) (\r\n # The total amount of Kademlia GET_VALUE queries started.\r\n ${metric_namespace}_authority_discovery_authority_addresses_requested_total{instance=~\"${nodename}\"}\r\n \r\n # The total amount of Kademlia PUT_VALUE queries started.\r\n + ${metric_namespace}_authority_discovery_times_published_total{instance=~\"${nodename}\"}\r\n )\r\n - sum by (instance) (\r\n # The total amount of Kademlia queries (both GET_VALUE and PUT_VALUE) finished.\r\n ${metric_namespace}_authority_discovery_dht_event_received{instance=~\"${nodename}\"}\r\n )\n)", + "interval": "", + "legendFormat": "in-progress", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Authority discovery Kademlia queries in progress, averaged per node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$data_source", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 1896 + }, + "hiddenSeries": false, + "id": 72, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(sum without(instance) (delta(${metric_namespace}_authority_discovery_times_published_total{instance=~\"${nodename}\"}[$__interval])))", + "interval": "", + "legendFormat": "publications", + "refId": "A" + }, + { + "expr": "avg(sum without(instance) (delta(${metric_namespace}_authority_discovery_dht_event_received{instance=~\"${nodename}\", name=\"value_put\"}[$__interval])))", + "interval": "", + "legendFormat": "successes", + "refId": "B" + }, + { + "expr": "avg(sum without(instance) (delta(${metric_namespace}_authority_discovery_dht_event_received{instance=~\"${nodename}\", name=\"value_put_failed\"}[$__interval])))", + "interval": "", + "legendFormat": "failures", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Authority discovery publications, averaged per node", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "1m", + "schemaVersion": 22, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "$data_source", + "definition": "${metric_namespace}_cpu_usage_percentage", + "hide": 0, + "includeAll": true, + "index": -1, + "label": "Instance name filter", + "multi": true, + "name": "nodename", + "options": [], + "query": "${metric_namespace}_cpu_usage_percentage", + "refresh": 1, + "regex": "/instance=\"(.*?)\"/", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$data_source", + "definition": "${metric_namespace}_sub_libp2p_notifications_sizes_count", + "hide": 2, + "includeAll": true, + "index": -1, + "label": null, + "multi": false, + "name": "notif_protocol", + "options": [], + "query": "${metric_namespace}_sub_libp2p_notifications_sizes_count", + "refresh": 1, + "regex": "/protocol=\"(.*?)\"/", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "$data_source", + "definition": "${metric_namespace}_sub_libp2p_requests_out_started_total", + "hide": 2, + "includeAll": true, + "index": -1, + "label": null, + "multi": false, + "name": "request_protocol", + "options": [], + "query": "${metric_namespace}_sub_libp2p_requests_out_started_total", + "refresh": 1, + "regex": "/protocol=\"(.*?)\"/", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "tags": [], + "text": "prometheus.parity-mgmt", + "value": "prometheus.parity-mgmt" + }, + "hide": 0, + "includeAll": false, + "label": "Source of data", + "multi": false, + "name": "data_source", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "value": "${VAR_METRIC_NAMESPACE}", + "text": "${VAR_METRIC_NAMESPACE}" + }, + "hide": 2, + "label": "Prefix of the metrics", + "name": "metric_namespace", + "options": [ + { + "value": "${VAR_METRIC_NAMESPACE}", + "text": "${VAR_METRIC_NAMESPACE}" + } + ], + "query": "${VAR_METRIC_NAMESPACE}", + "skipUrlSync": false, + "type": "constant" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Substrate Networking", + "uid": "vKVuiD9Zk", + "variables": { + "list": [] + }, + "version": 103 +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 6c7b9a9a4bd76e53f84ba2b6fecd6b900f37fd13..06b1b42b10453c492c28159d6ef710f7a7d6a39d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,18 +103,6 @@ version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff" -[[package]] -name = "app_dirs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" -dependencies = [ - "ole32-sys", - "shell32-sys", - "winapi 0.2.8", - "xdg", -] - [[package]] name = "approx" version = "0.3.2" @@ -300,6 +288,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +[[package]] +name = "base64" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3" + [[package]] name = "bincode" version = "1.2.1" @@ -446,9 +440,9 @@ dependencies = [ [[package]] name = "bs58" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "bstr" @@ -526,9 +520,9 @@ checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" [[package]] name = "cargo_metadata" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" +checksum = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf" dependencies = [ "semver 0.9.0", "serde", @@ -580,7 +574,7 @@ dependencies = [ [[package]] name = "chain-spec-builder" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "ansi_term 0.12.1", "node-cli", @@ -721,18 +715,18 @@ checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "cranelift-bforest" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a9c21f8042b9857bda93f6c1910b9f9f24100187a3d3d52f214a34e3dc5818" +checksum = "d4425bb6c3f3d2f581c650f1a1fdd3196a975490149cf59bea9d34c3bea79eda" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7853f77a6e4a33c67a69c40f5e1bb982bd2dc5c4a22e17e67b65bbccf9b33b2e" +checksum = "d166b289fd30062ee6de86284750fc3fe5d037c6b864b3326ce153239b0626e1" dependencies = [ "byteorder 1.3.4", "cranelift-bforest", @@ -741,17 +735,18 @@ dependencies = [ "cranelift-entity", "gimli", "log", + "regalloc", "serde", - "smallvec 1.3.0", + "smallvec 1.4.0", "target-lexicon", "thiserror", ] [[package]] name = "cranelift-codegen-meta" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084cd6d5fb0d1da28acd72c199471bfb09acc703ec8f3bf07b1699584272a3b9" +checksum = "02c9fb2306a36d41c5facd4bf3400bc6c157185c43a96eaaa503471c34c5144b" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -759,36 +754,36 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "701b599783305a58c25027a4d73f2d6b599b2d8ef3f26677275f480b4d51e05d" +checksum = "44e0cfe9b1f97d9f836bca551618106c7d53b93b579029ecd38e73daa7eb689e" [[package]] name = "cranelift-entity" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88e792b28e1ebbc0187b72ba5ba880dad083abe9231a99d19604d10c9e73f38" +checksum = "926a73c432e5ba9c891171ff50b75e7d992cd76cd271f0a0a0ba199138077472" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518344698fa6c976d853319218415fdfb4f1bc6b42d0b2e2df652e55dff1f778" +checksum = "e45f82e3446dd1ebb8c2c2f6a6b0e6cd6cd52965c7e5f7b1b35e9a9ace31ccde" dependencies = [ "cranelift-codegen", "log", - "smallvec 1.3.0", + "smallvec 1.4.0", "target-lexicon", ] [[package]] name = "cranelift-native" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32daf082da21c0c05d93394ff4842c2ab7c4991b1f3186a1d952f8ac660edd0b" +checksum = "488b5d481bb0996a143e55a9d1739ef425efa20d4a5e5e98c859a8573c9ead9a" dependencies = [ "cranelift-codegen", "raw-cpuid", @@ -797,9 +792,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.59.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2aa816f554a3ef739a5d17ca3081a1f8983f04c944ea8ff60fb8d9dd8cd2d7b" +checksum = "00aa8dde71fd9fdb1958e7b0ef8f524c1560e2c6165e4ea54bc302b40551c161" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -807,7 +802,7 @@ dependencies = [ "log", "serde", "thiserror", - "wasmparser", + "wasmparser 0.51.4", ] [[package]] @@ -1277,11 +1272,10 @@ dependencies = [ [[package]] name = "faerie" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b9ed6159e4a6212c61d9c6a86bee01876b192a64accecf58d5b5ae3b667b52" +checksum = "dfef65b0e94693295c5d2fe2506f0ee6f43465342d4b5331659936aee8b16084" dependencies = [ - "anyhow", "goblin", "indexmap", "log", @@ -1346,9 +1340,9 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4682570188cd105606e621b9992e580f717c15f8cd1b7d106b59f1c6e54680" +checksum = "8feb87a63249689640ac9c011742c33139204e3c134293d3054022276869133b" dependencies = [ "either", "futures 0.3.4", @@ -1399,14 +1393,14 @@ checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" [[package]] name = "fork-tree" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", ] [[package]] name = "frame-benchmarking" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -1422,7 +1416,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "parity-scale-codec", @@ -1439,7 +1433,7 @@ dependencies = [ [[package]] name = "frame-executive" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -1459,7 +1453,7 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "11.0.0-dev" +version = "11.0.0-rc2" dependencies = [ "parity-scale-codec", "serde", @@ -1469,7 +1463,7 @@ dependencies = [ [[package]] name = "frame-support" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "bitmask", "frame-metadata", @@ -1482,6 +1476,7 @@ dependencies = [ "paste", "pretty_assertions", "serde", + "smallvec 1.4.0", "sp-arithmetic", "sp-core", "sp-inherents", @@ -1494,7 +1489,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support-procedural-tools", "proc-macro2", @@ -1504,7 +1499,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", @@ -1515,7 +1510,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "proc-macro2", "quote 1.0.3", @@ -1524,7 +1519,7 @@ dependencies = [ [[package]] name = "frame-support-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "parity-scale-codec", @@ -1541,7 +1536,7 @@ dependencies = [ [[package]] name = "frame-system" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "criterion 0.2.11", "frame-support", @@ -1559,7 +1554,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -1574,7 +1569,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "sp-api", @@ -1869,7 +1864,7 @@ dependencies = [ "byteorder 1.3.4", "fallible-iterator", "indexmap", - "smallvec 1.3.0", + "smallvec 1.4.0", "stable_deref_trait", ] @@ -2050,9 +2045,9 @@ dependencies = [ [[package]] name = "honggfuzz" -version = "0.5.47" +version = "0.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3de2c3273ef7735df1c5a72128ca85b1d20105b9aac643cdfd7a6e581311150" +checksum = "832bac18a82ec7d6c21887daa8616b238fe90d5d5e762d0d4b9372cdaa9e097f" dependencies = [ "arbitrary", "lazy_static", @@ -2274,12 +2269,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f65877bf7d44897a473350b1046277941cee20b263397e90869c50b6e766088b" -[[package]] -name = "interleaved-ordered" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" - [[package]] name = "intervalier" version = "0.4.0" @@ -2490,19 +2479,19 @@ dependencies = [ [[package]] name = "kvdb" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad096c6849b2ef027fabe35c4aed356d0e3d3f586d0a8361e5e17f1e50a7ce5" +checksum = "e763b2a9b500ba47948061d1e8bc3b5f03a8a1f067dbcf822a4d2c84d2b54a3a" dependencies = [ "parity-util-mem", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] name = "kvdb-memorydb" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa954d12cfac958822dfd77aab34f3eec71f103b918c4ab79ab59a36ee594ea" +checksum = "73027d5e228de6f503b5b7335d530404fc26230a6ae3e09b33ec6e45408509a4" dependencies = [ "kvdb", "parity-util-mem", @@ -2511,12 +2500,11 @@ dependencies = [ [[package]] name = "kvdb-rocksdb" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3f14c3a10c8894d26175e57e9e26032e6d6c49c30cbe2468c5bf5f6b64bb0be" +checksum = "84384eca250c7ff67877eda5336f28a86586aaee24acb945643590671f6bfce1" dependencies = [ "fs-swap", - "interleaved-ordered", "kvdb", "log", "num_cpus", @@ -2525,14 +2513,14 @@ dependencies = [ "parking_lot 0.10.2", "regex", "rocksdb", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] name = "kvdb-web" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f96eec962af83cdf7c83036b3dbb0ae6a1249ddab746820618e2567ca8ebcd" +checksum = "6c7f36acb1841d4c701d30ae1f2cfd242e805991443f75f6935479ed3de64903" dependencies = [ "futures 0.3.4", "js-sys", @@ -2599,9 +2587,9 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "libp2p" -version = "0.18.1" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ea742c86405b659c358223a8f0f9f5a9eb27bb6083894c6340959b05269662" +checksum = "057eba5432d3e740e313c6e13c9153d0cb76b4f71bfc2e5242ae5bdb7d41af67" dependencies = [ "bytes 0.5.4", "futures 0.3.4", @@ -2628,18 +2616,18 @@ dependencies = [ "libp2p-websocket", "libp2p-yamux", "multihash", - "parity-multiaddr 0.8.0", + "parity-multiaddr 0.9.0", "parking_lot 0.10.2", "pin-project", - "smallvec 1.3.0", + "smallvec 1.4.0", "wasm-timer", ] [[package]] name = "libp2p-core" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d2c17158c4dca984a77a5927aac6f0862d7f50c013470a415f93be498b5739" +checksum = "80a6000296bdbff540b6c00ef82108ef23aa68d195b9333823ea491562c338d7" dependencies = [ "asn1_der", "bs58", @@ -2653,7 +2641,7 @@ dependencies = [ "log", "multihash", "multistream-select", - "parity-multiaddr 0.8.0", + "parity-multiaddr 0.9.0", "parking_lot 0.10.2", "pin-project", "prost", @@ -2662,7 +2650,7 @@ dependencies = [ "ring", "rw-stream-sink", "sha2", - "smallvec 1.3.0", + "smallvec 1.4.0", "thiserror", "unsigned-varint", "void", @@ -2671,9 +2659,9 @@ dependencies = [ [[package]] name = "libp2p-core-derive" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329127858e4728db5ab60c33d5ae352a999325fdf190ed022ec7d3a4685ae2e6" +checksum = "f09548626b737ed64080fde595e06ce1117795b8b9fc4d2629fa36561c583171" dependencies = [ "quote 1.0.3", "syn 1.0.17", @@ -2681,9 +2669,9 @@ dependencies = [ [[package]] name = "libp2p-deflate" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad32b006ea922da8cc66e537cf2df4b0fad8ebaa467d2a8c63d7784ac252ec6" +checksum = "5c4acff33f5bfe154bafe14c6c08655d4b1e1736afaca78014111bc1742a2016" dependencies = [ "flate2", "futures 0.3.4", @@ -2692,9 +2680,9 @@ dependencies = [ [[package]] name = "libp2p-dns" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d0993481203d68e5ce2f787d033fb0cac6b850659ed6c784612db678977c71" +checksum = "3cc186d9a941fd0207cf8f08ef225a735e2d7296258f570155e525f6ee732f87" dependencies = [ "futures 0.3.4", "libp2p-core", @@ -2703,9 +2691,9 @@ dependencies = [ [[package]] name = "libp2p-floodsub" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3673153ca967c179d745fadf047d069355d6669ecf7f261b450fbaebf1bffd3d" +checksum = "c6dd8cc558e0edde2d4a423d017efd6b36c1b6bf97f4304c83076895c5edaed8" dependencies = [ "cuckoofilter", "fnv", @@ -2715,16 +2703,16 @@ dependencies = [ "prost", "prost-build", "rand 0.7.3", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] name = "libp2p-gossipsub" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f7f3f79f060864db0317cc47641b7d35276dee52a0ffa91553fbd0c153863a3" +checksum = "1675c23765e37ddbf6bf05fb520be8f7df3f5f4981d68f185bb95f9b047c576a" dependencies = [ - "base64", + "base64 0.11.0", "byteorder 1.3.4", "bytes 0.5.4", "fnv", @@ -2738,16 +2726,16 @@ dependencies = [ "prost-build", "rand 0.7.3", "sha2", - "smallvec 1.3.0", + "smallvec 1.4.0", "unsigned-varint", "wasm-timer", ] [[package]] name = "libp2p-identify" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38ca3eb807789e26f41c82ca7cd2b3843c66c5587b8b5f709a2f421f3061414" +checksum = "6438ed8ca240c7635c9caa3be6c5258bc0058553ae97ba81737f04e5d33804f5" dependencies = [ "futures 0.3.4", "libp2p-core", @@ -2755,15 +2743,15 @@ dependencies = [ "log", "prost", "prost-build", - "smallvec 1.3.0", + "smallvec 1.4.0", "wasm-timer", ] [[package]] name = "libp2p-kad" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92cda1fb8149ea64d092a2b99d2bd7a2c309eee38ea322d02e4480bd6ee1759" +checksum = "41d6c1d5100973527ae70d82687465b17049c1b717a7964de38b8e65000878ff" dependencies = [ "arrayvec 0.5.1", "bytes 0.5.4", @@ -2779,7 +2767,7 @@ dependencies = [ "prost-build", "rand 0.7.3", "sha2", - "smallvec 1.3.0", + "smallvec 1.4.0", "uint", "unsigned-varint", "void", @@ -2788,9 +2776,9 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41e908d2aaf8ff0ec6ad1f02fe1844fd777fb0b03a68a226423630750ab99471" +checksum = "51b00163d13f705aae67c427bea0575f8aaf63da6524f9bd4a5a093b8bda0b38" dependencies = [ "async-std", "data-encoding", @@ -2803,16 +2791,16 @@ dependencies = [ "log", "net2", "rand 0.7.3", - "smallvec 1.3.0", + "smallvec 1.4.0", "void", "wasm-timer", ] [[package]] name = "libp2p-mplex" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0832882b06619b2e81d74e71447753ea3c068164a0bca67847d272e856a04a02" +checksum = "34ce63313ad4bce2d76e54c292a1293ea47a0ebbe16708f1513fa62184992f53" dependencies = [ "bytes 0.5.4", "fnv", @@ -2826,9 +2814,9 @@ dependencies = [ [[package]] name = "libp2p-noise" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918e94a649e1139c24ee9f1f8c1f2adaba6d157b9471af787f2d9beac8c29c77" +checksum = "84fd504e27b0eadd451e06b67694ef714bd8374044e7db339bb0cdb83755ddf4" dependencies = [ "curve25519-dalek", "futures 0.3.4", @@ -2847,9 +2835,9 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9bfbf87eebb492d040f9899c5c81c9738730465ac5e78d9b7a7d086d0f07230" +checksum = "c189cf1dfe4b3f01e2c0fe5e97a6f5df8aeb6f3569e26981015eb7c08015ce5f" dependencies = [ "futures 0.3.4", "libp2p-core", @@ -2862,9 +2850,9 @@ dependencies = [ [[package]] name = "libp2p-plaintext" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabb00553a49bf6d4a8ce362f6eefac410227a14d03c3acffbb8cc3f022ea019" +checksum = "ad28fe7beaa3e516ee8ba2af8c4f6820f269afa60d661831e879f2afea64f4a0" dependencies = [ "bytes 0.5.4", "futures 0.3.4", @@ -2880,9 +2868,9 @@ dependencies = [ [[package]] name = "libp2p-pnet" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f81b8b37ff529e1f51c20c396dac657def2108da174c1d27e57e72c9fe2d411" +checksum = "dabaa2194e1ce3c51cd78d734dd4c81dc5c7b150b309cbf9029df044034ac261" dependencies = [ "futures 0.3.4", "log", @@ -2894,9 +2882,9 @@ dependencies = [ [[package]] name = "libp2p-secio" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a0509a7e47245259954fef58b85b81bf4d29ae33a4365e38d718a866698774" +checksum = "7b73f0cc119c83a5b619d6d11074a319fdb4aa4daf8088ade00d511418566e28" dependencies = [ "aes-ctr", "ctr", @@ -2924,24 +2912,24 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44ab289ae44cc691da0a6fe96aefa43f26c86c6c7813998e203f6d80f1860f18" +checksum = "b4a8101a0e0d5f04562137a476bf5f5423cd5bdab2f7e43a75909668e63cb102" dependencies = [ "futures 0.3.4", "libp2p-core", "log", "rand 0.7.3", - "smallvec 1.3.0", + "smallvec 1.4.0", "void", "wasm-timer", ] [[package]] name = "libp2p-tcp" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b37ea44823d3ed223e4605da94b50177bc520f05ae2452286700549a32d81669" +checksum = "309f95fce9bec755eff5406f8b822fd3969990830c2b54f752e1fc181d5ace3e" dependencies = [ "async-std", "futures 0.3.4", @@ -2950,13 +2938,14 @@ dependencies = [ "ipnet", "libp2p-core", "log", + "socket2", ] [[package]] name = "libp2p-uds" -version = "0.18.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "281c18ea2faacb9c8a6ff76c4405df5918d9a263770e3847bf03f099abadc010" +checksum = "78d51726e063e8d73b103331576bb7e8fad187a3f0c227933a10b3542e2ad3f4" dependencies = [ "async-std", "futures 0.3.4", @@ -2966,9 +2955,9 @@ dependencies = [ [[package]] name = "libp2p-wasm-ext" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ac7dbde0f88cad191dcdfd073b8bae28d01823e8ca313f117b6ecb914160c3" +checksum = "f59fdbb5706f2723ca108c088b1c7a37f735a8c328021f0508007162627e9885" dependencies = [ "futures 0.3.4", "js-sys", @@ -2980,9 +2969,9 @@ dependencies = [ [[package]] name = "libp2p-websocket" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6874c9069ce93d899df9dc7b29f129c706b2a0fdc048f11d878935352b580190" +checksum = "085fbe4c05c4116c2164ab4d5a521eb6e00516c444f61b3ee9f68c7b1e53580b" dependencies = [ "async-tls", "bytes 0.5.4", @@ -3001,9 +2990,9 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f91aea50f6571e0bc6c058dc0e9b270afd41ec28dd94e9e4bf607e78b9ab87" +checksum = "0b305d3a8981e68f11c0e17f2d11d5c52fae95e0d7c283f9e462b5b2dab413b2" dependencies = [ "futures 0.3.4", "libp2p-core", @@ -3014,9 +3003,9 @@ dependencies = [ [[package]] name = "librocksdb-sys" -version = "6.6.4" +version = "6.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3b727e2dd20ec2fb7ed93f23d9fd5328a0871185485ebdaff007b47d3e27e4" +checksum = "883213ae3d09bfc3d104aefe94b25ebb183b6f4d3a515b23b14817e1f4854005" dependencies = [ "bindgen", "cc", @@ -3270,9 +3259,9 @@ checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "multihash" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47fbc227f7e2b1cb701f95404579ecb2668abbdd3c7ef7a6cbb3cc0d3b236869" +checksum = "ae32179a9904ccc6e063de8beee7f5dd55fae85ecb851ca923d55722bc28cf5d" dependencies = [ "blake2b_simd", "blake2s_simd", @@ -3299,7 +3288,7 @@ dependencies = [ "futures 0.3.4", "log", "pin-project", - "smallvec 1.3.0", + "smallvec 1.4.0", "unsigned-varint", ] @@ -3369,7 +3358,7 @@ dependencies = [ [[package]] name = "node-bench" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "fs_extra", @@ -3380,6 +3369,7 @@ dependencies = [ "lazy_static", "log", "node-primitives", + "node-runtime", "node-testing", "parity-db", "parity-util-mem", @@ -3398,7 +3388,7 @@ dependencies = [ [[package]] name = "node-browser-testing" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "futures 0.3.4", "futures-timer 3.0.2", @@ -3415,7 +3405,7 @@ dependencies = [ [[package]] name = "node-cli" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "assert_cmd", "frame-benchmarking-cli", @@ -3489,7 +3479,7 @@ dependencies = [ [[package]] name = "node-executor" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "criterion 0.3.1", "frame-benchmarking", @@ -3523,7 +3513,7 @@ dependencies = [ [[package]] name = "node-inspect" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "log", @@ -3539,7 +3529,7 @@ dependencies = [ [[package]] name = "node-primitives" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-system", "parity-scale-codec", @@ -3552,7 +3542,7 @@ dependencies = [ [[package]] name = "node-rpc" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "jsonrpc-core", "node-primitives", @@ -3566,6 +3556,7 @@ dependencies = [ "sc-finality-grandpa", "sc-finality-grandpa-rpc", "sc-keystore", + "sc-rpc-api", "sp-api", "sp-blockchain", "sp-consensus", @@ -3577,7 +3568,7 @@ dependencies = [ [[package]] name = "node-rpc-client" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "env_logger 0.7.1", "futures 0.1.29", @@ -3590,7 +3581,7 @@ dependencies = [ [[package]] name = "node-runtime" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-executive", @@ -3650,12 +3641,13 @@ dependencies = [ "sp-std", "sp-transaction-pool", "sp-version", + "static_assertions", "substrate-wasm-builder-runner", ] [[package]] name = "node-template" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "futures 0.3.4", "log", @@ -3684,7 +3676,7 @@ dependencies = [ [[package]] name = "node-template-runtime" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-executive", "frame-support", @@ -3716,7 +3708,7 @@ dependencies = [ [[package]] name = "node-testing" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "criterion 0.3.1", "frame-support", @@ -3865,26 +3857,11 @@ dependencies = [ [[package]] name = "object" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea44a4fd660ab0f38434934ca0212e90fbeaaee54126ef20a3451c30c95bafae" +checksum = "e5666bbb90bc4d1e5bdcb26c0afda1822d25928341e9384ab187a9b37ab69e36" dependencies = [ - "flate2", - "goblin", - "parity-wasm 0.41.0", - "scroll", "target-lexicon", - "uuid", -] - -[[package]] -name = "ole32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -dependencies = [ - "winapi 0.2.8", - "winapi-build", ] [[package]] @@ -3934,7 +3911,7 @@ dependencies = [ [[package]] name = "pallet-assets" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -3948,7 +3925,7 @@ dependencies = [ [[package]] name = "pallet-aura" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -3970,7 +3947,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -3988,7 +3965,7 @@ dependencies = [ [[package]] name = "pallet-authorship" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4004,7 +3981,7 @@ dependencies = [ [[package]] name = "pallet-babe" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4026,7 +4003,7 @@ dependencies = [ [[package]] name = "pallet-balances" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4042,7 +4019,7 @@ dependencies = [ [[package]] name = "pallet-benchmark" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4056,7 +4033,7 @@ dependencies = [ [[package]] name = "pallet-collective" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4073,7 +4050,7 @@ dependencies = [ [[package]] name = "pallet-contracts" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "assert_matches", "frame-support", @@ -4099,7 +4076,7 @@ dependencies = [ [[package]] name = "pallet-contracts-primitives" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "sp-runtime", @@ -4108,7 +4085,7 @@ dependencies = [ [[package]] name = "pallet-contracts-rpc" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -4127,7 +4104,7 @@ dependencies = [ [[package]] name = "pallet-contracts-rpc-runtime-api" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "pallet-contracts-primitives", "parity-scale-codec", @@ -4138,7 +4115,7 @@ dependencies = [ [[package]] name = "pallet-democracy" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4153,11 +4130,12 @@ dependencies = [ "sp-runtime", "sp-std", "sp-storage", + "substrate-test-utils", ] [[package]] name = "pallet-elections" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4173,13 +4151,13 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "hex-literal", "pallet-balances", - "pallet-scheduler", "parity-scale-codec", "serde", "sp-core", @@ -4192,7 +4170,7 @@ dependencies = [ [[package]] name = "pallet-evm" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "evm", "frame-support", @@ -4212,7 +4190,7 @@ dependencies = [ [[package]] name = "pallet-example" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4228,7 +4206,7 @@ dependencies = [ [[package]] name = "pallet-example-offchain-worker" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4243,7 +4221,7 @@ dependencies = [ [[package]] name = "pallet-finality-tracker" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4260,7 +4238,7 @@ dependencies = [ [[package]] name = "pallet-generic-asset" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4274,7 +4252,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "finality-grandpa", "frame-support", @@ -4301,7 +4279,7 @@ dependencies = [ [[package]] name = "pallet-identity" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "enumflags2", "frame-benchmarking", @@ -4318,7 +4296,7 @@ dependencies = [ [[package]] name = "pallet-im-online" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4337,7 +4315,7 @@ dependencies = [ [[package]] name = "pallet-indices" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4353,7 +4331,7 @@ dependencies = [ [[package]] name = "pallet-membership" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4367,7 +4345,7 @@ dependencies = [ [[package]] name = "pallet-nicks" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4382,7 +4360,7 @@ dependencies = [ [[package]] name = "pallet-offences" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4398,7 +4376,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4423,7 +4401,7 @@ dependencies = [ [[package]] name = "pallet-randomness-collective-flip" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4437,7 +4415,7 @@ dependencies = [ [[package]] name = "pallet-recovery" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "enumflags2", "frame-support", @@ -4453,7 +4431,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4468,7 +4446,7 @@ dependencies = [ [[package]] name = "pallet-scored-pool" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4483,7 +4461,7 @@ dependencies = [ [[package]] name = "pallet-session" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4504,7 +4482,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4524,7 +4502,7 @@ dependencies = [ [[package]] name = "pallet-society" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4540,7 +4518,7 @@ dependencies = [ [[package]] name = "pallet-staking" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "env_logger 0.7.1", "frame-benchmarking", @@ -4549,13 +4527,11 @@ dependencies = [ "hex", "pallet-authorship", "pallet-balances", - "pallet-indices", "pallet-session", "pallet-staking-reward-curve", "pallet-timestamp", "parity-scale-codec", "parking_lot 0.10.2", - "rand 0.7.3", "rand_chacha 0.2.2", "serde", "sp-application-crypto", @@ -4593,7 +4569,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -4604,7 +4580,7 @@ dependencies = [ [[package]] name = "pallet-sudo" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4618,7 +4594,7 @@ dependencies = [ [[package]] name = "pallet-template" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -4630,7 +4606,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4648,13 +4624,14 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", "pallet-balances", "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", + "smallvec 1.4.0", "sp-core", "sp-io", "sp-runtime", @@ -4664,7 +4641,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -4681,7 +4658,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "parity-scale-codec", @@ -4694,7 +4671,7 @@ dependencies = [ [[package]] name = "pallet-treasury" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4710,7 +4687,7 @@ dependencies = [ [[package]] name = "pallet-utility" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-benchmarking", "frame-support", @@ -4726,7 +4703,7 @@ dependencies = [ [[package]] name = "pallet-vesting" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "enumflags2", "frame-benchmarking", @@ -4777,9 +4754,9 @@ dependencies = [ [[package]] name = "parity-multiaddr" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4db35e222f783ef4e6661873f6c165c4eb7b65e0c408349818517d5705c2d7d3" +checksum = "12ca96399f4a01aa89c59220c4f52ac371940eb4e53e3ce990da796f364bdf69" dependencies = [ "arrayref", "bs58", @@ -4850,7 +4827,7 @@ dependencies = [ "parity-util-mem-derive", "parking_lot 0.10.2", "primitive-types", - "smallvec 1.3.0", + "smallvec 1.4.0", "winapi 0.3.8", ] @@ -4926,7 +4903,7 @@ dependencies = [ "cloudabi", "libc", "redox_syscall", - "smallvec 1.3.0", + "smallvec 1.4.0", "winapi 0.3.8", ] @@ -5609,6 +5586,17 @@ dependencies = [ "syn 1.0.17", ] +[[package]] +name = "regalloc" +version = "0.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b27b256b41986ac5141b37b8bbba85d314fbf546c182eb255af6720e07e4f804" +dependencies = [ + "log", + "rustc-hash", + "smallvec 1.4.0", +] + [[package]] name = "regex" version = "1.3.6" @@ -5689,9 +5677,9 @@ dependencies = [ [[package]] name = "rocksdb" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12069b106981c6103d3eab7dd1c86751482d0779a520b7c14954c8b586c1e643" +checksum = "61aa17a99a2413cd71c1106691bf59dad7de0cd5099127f90e9d99c429c40d4a" dependencies = [ "libc", "librocksdb-sys", @@ -5713,7 +5701,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" dependencies = [ - "base64", + "base64 0.11.0", "blake2b_simd", "constant_time_eq", "crossbeam-utils", @@ -5752,7 +5740,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" dependencies = [ - "base64", + "base64 0.11.0", "log", "ring", "sct", @@ -5839,7 +5827,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "bytes 0.5.4", "derive_more", @@ -5869,7 +5857,7 @@ dependencies = [ [[package]] name = "sc-basic-authorship" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "futures 0.3.4", "futures-timer 3.0.2", @@ -5878,6 +5866,7 @@ dependencies = [ "parking_lot 0.10.2", "sc-block-builder", "sc-client-api", + "sc-proposer-metrics", "sc-telemetry", "sc-transaction-pool", "sp-api", @@ -5887,13 +5876,14 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-transaction-pool", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tokio-executor 0.2.0-alpha.6", ] [[package]] name = "sc-block-builder" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -5910,7 +5900,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "impl-trait-for-tuples", "sc-chain-spec-derive", @@ -5925,7 +5915,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5935,14 +5925,13 @@ dependencies = [ [[package]] name = "sc-cli" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "ansi_term 0.12.1", - "app_dirs", "atty", "chrono", - "clap", "derive_more", + "directories", "env_logger 0.7.1", "fdlimit", "futures 0.3.4", @@ -5977,7 +5966,7 @@ dependencies = [ [[package]] name = "sc-client-api" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "derive_more", "fnv", @@ -6015,7 +6004,7 @@ dependencies = [ [[package]] name = "sc-client-db" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "blake2-rfc", "env_logger 0.7.1", @@ -6048,7 +6037,7 @@ dependencies = [ [[package]] name = "sc-consensus" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "sc-client-api", "sp-blockchain", @@ -6058,7 +6047,7 @@ dependencies = [ [[package]] name = "sc-consensus-aura" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "env_logger 0.7.1", @@ -6089,13 +6078,14 @@ dependencies = [ "sp-runtime", "sp-timestamp", "sp-version", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", ] [[package]] name = "sc-consensus-babe" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "env_logger 0.7.1", @@ -6138,23 +6128,27 @@ dependencies = [ "sp-runtime", "sp-timestamp", "sp-version", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "tempfile", ] [[package]] name = "sc-consensus-babe-rpc" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "futures 0.3.4", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", + "sc-consensus", "sc-consensus-babe", "sc-consensus-epochs", "sc-keystore", + "sc-rpc-api", "serde", + "serde_json", "sp-api", "sp-application-crypto", "sp-blockchain", @@ -6169,7 +6163,7 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "fork-tree", "parity-scale-codec", @@ -6181,7 +6175,7 @@ dependencies = [ [[package]] name = "sc-consensus-manual-seal" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "assert_matches", "derive_more", @@ -6202,6 +6196,7 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-transaction-pool", + "substrate-prometheus-endpoint", "substrate-test-runtime-client", "substrate-test-runtime-transaction-pool", "tempfile", @@ -6210,7 +6205,7 @@ dependencies = [ [[package]] name = "sc-consensus-pow" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "futures 0.3.4", @@ -6226,11 +6221,12 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-timestamp", + "substrate-prometheus-endpoint", ] [[package]] name = "sc-consensus-slots" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "futures 0.3.4", "futures-timer 3.0.2", @@ -6240,6 +6236,7 @@ dependencies = [ "sc-client-api", "sc-telemetry", "sp-api", + "sp-application-crypto", "sp-blockchain", "sp-consensus", "sp-core", @@ -6251,7 +6248,7 @@ dependencies = [ [[package]] name = "sc-consensus-uncles" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "log", "sc-client-api", @@ -6264,7 +6261,7 @@ dependencies = [ [[package]] name = "sc-executor" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "assert_matches", "derive_more", @@ -6299,7 +6296,7 @@ dependencies = [ [[package]] name = "sc-executor-common" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "log", @@ -6315,7 +6312,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "log", "parity-scale-codec", @@ -6329,7 +6326,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "assert_matches", "cranelift-codegen", @@ -6350,7 +6347,7 @@ dependencies = [ [[package]] name = "sc-finality-grandpa" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "assert_matches", "derive_more", @@ -6394,7 +6391,7 @@ dependencies = [ [[package]] name = "sc-finality-grandpa-rpc" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "finality-grandpa", @@ -6411,7 +6408,7 @@ dependencies = [ [[package]] name = "sc-informant" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "ansi_term 0.12.1", "futures 0.3.4", @@ -6427,7 +6424,7 @@ dependencies = [ [[package]] name = "sc-keystore" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "derive_more", "hex", @@ -6442,11 +6439,12 @@ dependencies = [ [[package]] name = "sc-network" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "assert_matches", "async-std", "bitflags", + "bs58", "bytes 0.5.4", "derive_more", "either", @@ -6501,7 +6499,7 @@ dependencies = [ [[package]] name = "sc-network-gossip" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "async-std", "futures 0.3.4", @@ -6519,7 +6517,7 @@ dependencies = [ [[package]] name = "sc-network-test" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "env_logger 0.7.1", "futures 0.3.4", @@ -6545,7 +6543,7 @@ dependencies = [ [[package]] name = "sc-offchain" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "bytes 0.5.4", "env_logger 0.7.1", @@ -6578,7 +6576,7 @@ dependencies = [ [[package]] name = "sc-peerset" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "futures 0.3.4", "libp2p", @@ -6589,9 +6587,17 @@ dependencies = [ "wasm-timer", ] +[[package]] +name = "sc-proposer-metrics" +version = "0.8.0-rc2" +dependencies = [ + "log", + "substrate-prometheus-endpoint", +] + [[package]] name = "sc-rpc" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "assert_matches", "futures 0.1.29", @@ -6599,6 +6605,7 @@ dependencies = [ "hash-db", "jsonrpc-core", "jsonrpc-pubsub", + "lazy_static", "log", "parity-scale-codec", "parking_lot 0.10.2", @@ -6629,7 +6636,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "futures 0.3.4", @@ -6652,7 +6659,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "jsonrpc-core", "jsonrpc-http-server", @@ -6666,7 +6673,7 @@ dependencies = [ [[package]] name = "sc-runtime-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "sp-allocator", "sp-core", @@ -6679,7 +6686,7 @@ dependencies = [ [[package]] name = "sc-service" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "exit-future", @@ -6740,7 +6747,7 @@ dependencies = [ [[package]] name = "sc-service-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "env_logger 0.7.1", "fdlimit", @@ -6775,7 +6782,7 @@ dependencies = [ [[package]] name = "sc-state-db" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "env_logger 0.7.1", "log", @@ -6789,7 +6796,7 @@ dependencies = [ [[package]] name = "sc-telemetry" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "bytes 0.5.4", "futures 0.3.4", @@ -6810,7 +6817,7 @@ dependencies = [ [[package]] name = "sc-tracing" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "erased-serde", "log", @@ -6825,7 +6832,7 @@ dependencies = [ [[package]] name = "sc-transaction-graph" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "assert_matches", "criterion 0.3.1", @@ -6848,7 +6855,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "assert_matches", "derive_more", @@ -7014,18 +7021,18 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.106" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" +checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.106" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" +checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" dependencies = [ "proc-macro2", "quote 1.0.3", @@ -7086,16 +7093,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "shell32-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "shlex" version = "0.1.1" @@ -7173,9 +7170,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" [[package]] name = "snow" @@ -7195,13 +7192,25 @@ dependencies = [ "x25519-dalek", ] +[[package]] +name = "socket2" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] + [[package]] name = "soketto" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c9dab3f95c9ebdf3a88268c19af668f637a3c5039c2c56ff2d40b1b2d64a25b" dependencies = [ - "base64", + "base64 0.11.0", "bytes 0.5.4", "flate2", "futures 0.3.4", @@ -7210,14 +7219,14 @@ dependencies = [ "log", "rand 0.7.3", "sha1", - "smallvec 1.3.0", + "smallvec 1.4.0", "static_assertions", "thiserror", ] [[package]] name = "sp-allocator" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "derive_more", "log", @@ -7228,7 +7237,7 @@ dependencies = [ [[package]] name = "sp-api" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "hash-db", "parity-scale-codec", @@ -7243,7 +7252,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "blake2-rfc", "proc-macro-crate", @@ -7254,7 +7263,7 @@ dependencies = [ [[package]] name = "sp-api-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "criterion 0.3.1", "parity-scale-codec", @@ -7273,7 +7282,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "serde", @@ -7284,7 +7293,7 @@ dependencies = [ [[package]] name = "sp-application-crypto-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "sp-api", "sp-application-crypto", @@ -7295,7 +7304,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "criterion 0.3.1", "integer-sqrt", @@ -7311,7 +7320,7 @@ dependencies = [ [[package]] name = "sp-arithmetic-fuzzer" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "honggfuzz", "num-bigint", @@ -7322,7 +7331,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "sp-api", @@ -7333,7 +7342,7 @@ dependencies = [ [[package]] name = "sp-authorship" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "sp-inherents", @@ -7343,7 +7352,7 @@ dependencies = [ [[package]] name = "sp-block-builder" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "sp-api", @@ -7354,7 +7363,7 @@ dependencies = [ [[package]] name = "sp-blockchain" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "derive_more", "log", @@ -7369,7 +7378,7 @@ dependencies = [ [[package]] name = "sp-chain-spec" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "serde", "serde_json", @@ -7377,7 +7386,7 @@ dependencies = [ [[package]] name = "sp-consensus" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "derive_more", "futures 0.3.4", @@ -7395,11 +7404,12 @@ dependencies = [ "sp-test-primitives", "sp-utils", "sp-version", + "substrate-prometheus-endpoint", ] [[package]] name = "sp-consensus-aura" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "parity-scale-codec", "sp-api", @@ -7412,7 +7422,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "merlin", "parity-scale-codec", @@ -7428,7 +7438,7 @@ dependencies = [ [[package]] name = "sp-consensus-pow" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "parity-scale-codec", "sp-api", @@ -7439,7 +7449,7 @@ dependencies = [ [[package]] name = "sp-consensus-vrf" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "parity-scale-codec", "schnorrkel", @@ -7450,12 +7460,13 @@ dependencies = [ [[package]] name = "sp-core" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "base58", "blake2-rfc", "byteorder 1.3.4", "criterion 0.2.11", + "derive_more", "ed25519-dalek", "futures 0.3.4", "hash-db", @@ -7495,7 +7506,7 @@ dependencies = [ [[package]] name = "sp-database" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "kvdb", "parking_lot 0.10.2", @@ -7503,7 +7514,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "proc-macro2", "quote 1.0.3", @@ -7512,7 +7523,7 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "environmental", "parity-scale-codec", @@ -7522,7 +7533,7 @@ dependencies = [ [[package]] name = "sp-finality-grandpa" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "finality-grandpa", "log", @@ -7537,7 +7548,7 @@ dependencies = [ [[package]] name = "sp-finality-tracker" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "sp-inherents", @@ -7546,7 +7557,7 @@ dependencies = [ [[package]] name = "sp-inherents" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "derive_more", "parity-scale-codec", @@ -7557,7 +7568,7 @@ dependencies = [ [[package]] name = "sp-io" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "futures 0.3.4", "hash-db", @@ -7576,7 +7587,7 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "lazy_static", "sp-core", @@ -7586,7 +7597,7 @@ dependencies = [ [[package]] name = "sp-offchain" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "sp-api", "sp-core", @@ -7596,7 +7607,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "backtrace", "log", @@ -7604,7 +7615,7 @@ dependencies = [ [[package]] name = "sp-phragmen" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "rand 0.7.3", @@ -7619,7 +7630,7 @@ dependencies = [ [[package]] name = "sp-phragmen-compact" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -7640,7 +7651,7 @@ dependencies = [ [[package]] name = "sp-rpc" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "serde", "serde_json", @@ -7649,7 +7660,7 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "hash256-std-hasher", "impl-trait-for-tuples", @@ -7671,7 +7682,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "primitive-types", @@ -7691,7 +7702,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "Inflector", "proc-macro-crate", @@ -7702,7 +7713,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "sc-executor", "sp-core", @@ -7717,7 +7728,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-test-wasm" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "sp-core", "sp-io", @@ -7728,7 +7739,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-test-wasm-deprecated" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "sp-core", "sp-io", @@ -7739,7 +7750,7 @@ dependencies = [ [[package]] name = "sp-sandbox" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "assert_matches", "parity-scale-codec", @@ -7753,7 +7764,7 @@ dependencies = [ [[package]] name = "sp-serializer" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "serde", "serde_json", @@ -7761,7 +7772,7 @@ dependencies = [ [[package]] name = "sp-session" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "sp-api", @@ -7773,7 +7784,7 @@ dependencies = [ [[package]] name = "sp-staking" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "sp-runtime", @@ -7782,7 +7793,7 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "hash-db", "hex-literal", @@ -7802,11 +7813,11 @@ dependencies = [ [[package]] name = "sp-std" -version = "2.0.0-dev" +version = "2.0.0-rc2" [[package]] name = "sp-storage" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "impl-serde 0.2.3", "ref-cast", @@ -7817,7 +7828,7 @@ dependencies = [ [[package]] name = "sp-test-primitives" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "parity-scale-codec", "parity-util-mem", @@ -7829,7 +7840,7 @@ dependencies = [ [[package]] name = "sp-timestamp" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -7842,14 +7853,14 @@ dependencies = [ [[package]] name = "sp-tracing" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "tracing", ] [[package]] name = "sp-transaction-pool" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "derive_more", "futures 0.3.4", @@ -7863,7 +7874,7 @@ dependencies = [ [[package]] name = "sp-trie" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "criterion 0.2.11", "hash-db", @@ -7881,7 +7892,7 @@ dependencies = [ [[package]] name = "sp-utils" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "futures 0.3.4", "futures-core", @@ -7891,7 +7902,7 @@ dependencies = [ [[package]] name = "sp-version" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "impl-serde 0.2.3", "parity-scale-codec", @@ -7902,7 +7913,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -8017,7 +8028,7 @@ dependencies = [ [[package]] name = "subkey" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "clap", "derive_more", @@ -8059,7 +8070,7 @@ dependencies = [ [[package]] name = "substrate-browser-utils" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "chrono", "clear_on_drop", @@ -8085,14 +8096,14 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "platforms", ] [[package]] name = "substrate-frame-rpc-support" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "frame-support", "frame-system", @@ -8108,7 +8119,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "env_logger 0.7.1", "frame-system-rpc-runtime-api", @@ -8131,7 +8142,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" -version = "0.8.0-dev" +version = "0.8.0-rc2" dependencies = [ "async-std", "derive_more", @@ -8144,7 +8155,7 @@ dependencies = [ [[package]] name = "substrate-test-client" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "futures 0.3.4", "hash-db", @@ -8164,7 +8175,7 @@ dependencies = [ [[package]] name = "substrate-test-runtime" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "cfg-if", "frame-executive", @@ -8207,7 +8218,7 @@ dependencies = [ [[package]] name = "substrate-test-runtime-client" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "futures 0.3.4", "parity-scale-codec", @@ -8226,7 +8237,7 @@ dependencies = [ [[package]] name = "substrate-test-runtime-transaction-pool" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "derive_more", "futures 0.3.4", @@ -8241,11 +8252,11 @@ dependencies = [ [[package]] name = "substrate-test-utils" -version = "2.0.0-dev" +version = "2.0.0-rc2" [[package]] name = "substrate-wasm-builder" -version = "1.0.10" +version = "1.0.11" dependencies = [ "atty", "build-helper", @@ -8264,9 +8275,9 @@ version = "1.0.6" [[package]] name = "substrate-wasmtime" -version = "0.13.0-threadsafe.1" +version = "0.16.0-threadsafe.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e512629525ecfe43bffe1f3d9e6bb0f08bf01155288ef27fcaae4ea086e4a9d" +checksum = "6bd62264edc1a5f3ef44d86fb0c11c9fb142894b9a2da034f34afae482080d7a" dependencies = [ "anyhow", "backtrace", @@ -8276,20 +8287,20 @@ dependencies = [ "region", "rustc-demangle", "substrate-wasmtime-jit", + "substrate-wasmtime-profiling", "substrate-wasmtime-runtime", "target-lexicon", - "wasmparser", + "wasmparser 0.52.2", "wasmtime-environ", - "wasmtime-profiling", "wat", "winapi 0.3.8", ] [[package]] name = "substrate-wasmtime-jit" -version = "0.13.0-threadsafe.1" +version = "0.16.0-threadsafe.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20de5564886d2bcffdd351c9cd114ceb50758aa58eac3cedb14faabf7f93b91" +checksum = "4ce43c159d4f3ef6b19641e1ae045847fd202d8e2cc74df7ccb2b6475e069d4a" dependencies = [ "anyhow", "cfg-if", @@ -8298,23 +8309,44 @@ dependencies = [ "cranelift-frontend", "cranelift-native", "cranelift-wasm", + "gimli", + "log", "more-asserts", "region", + "substrate-wasmtime-profiling", "substrate-wasmtime-runtime", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.52.2", "wasmtime-debug", "wasmtime-environ", - "wasmtime-profiling", "winapi 0.3.8", ] +[[package]] +name = "substrate-wasmtime-profiling" +version = "0.16.0-threadsafe.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77f0ce539b5a09a54dc80a1cf0c7cd7e694df11029354fe50a2d5fe889bdb97" +dependencies = [ + "anyhow", + "cfg-if", + "gimli", + "lazy_static", + "libc", + "object", + "scroll", + "serde", + "substrate-wasmtime-runtime", + "target-lexicon", + "wasmtime-environ", +] + [[package]] name = "substrate-wasmtime-runtime" -version = "0.13.0-threadsafe.1" +version = "0.16.0-threadsafe.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d08846f04293a7fc27eeb30f06262ca2e1b4ee20f5192cec1f3ce201e08ceb8" +checksum = "46516af0a64a7d9b652c5aa7436b6ce13edfa54435a66ef177fc02d2283e2dc2" dependencies = [ "backtrace", "cc", @@ -8327,7 +8359,6 @@ dependencies = [ "region", "thiserror", "wasmtime-environ", - "wasmtime-profiling", "winapi 0.3.8", ] @@ -8914,7 +8945,7 @@ dependencies = [ "hashbrown", "log", "rustc-hex", - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] @@ -9018,7 +9049,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.3.0", + "smallvec 1.4.0", ] [[package]] @@ -9085,12 +9116,6 @@ dependencies = [ "percent-encoding 2.1.0", ] -[[package]] -name = "uuid" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" - [[package]] name = "vcpkg" version = "0.2.8" @@ -9187,9 +9212,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" +checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551" dependencies = [ "cfg-if", "serde", @@ -9199,9 +9224,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" +checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94" dependencies = [ "bumpalo", "lazy_static", @@ -9226,9 +9251,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776" dependencies = [ "quote 1.0.3", "wasm-bindgen-macro-support", @@ -9236,9 +9261,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a" dependencies = [ "proc-macro2", "quote 1.0.3", @@ -9249,9 +9274,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" +checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad" [[package]] name = "wasm-bindgen-test" @@ -9334,11 +9359,17 @@ version = "0.51.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aeb1956b19469d1c5e63e459d29e7b5aa0f558d9f16fcef09736f8a265e6c10a" +[[package]] +name = "wasmparser" +version = "0.52.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733954023c0b39602439e60a65126fd31b003196d3a1e8e4531b055165a79b31" + [[package]] name = "wasmtime-debug" -version = "0.12.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d3d007436043bf55ec252d2f4dc1d35834157b5e2f148da839ca502e611cfe1" +checksum = "d39ba645aee700b29ff0093028b4123556dd142a74973f04ed6225eedb40e77d" dependencies = [ "anyhow", "faerie", @@ -9346,18 +9377,18 @@ dependencies = [ "more-asserts", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.51.4", "wasmtime-environ", ] [[package]] name = "wasmtime-environ" -version = "0.12.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f3dea0e60c076dd0da27fa10c821323903c9554c617ed32eaab8e7a7e36c89" +checksum = "ed54fd9d64dfeeee7c285fd126174a6b5e6d4efc7e5a1566fdb635e60ff6a74e" dependencies = [ "anyhow", - "base64", + "base64 0.12.0", "bincode", "cranelift-codegen", "cranelift-entity", @@ -9374,27 +9405,11 @@ dependencies = [ "sha2", "thiserror", "toml", - "wasmparser", + "wasmparser 0.51.4", "winapi 0.3.8", "zstd", ] -[[package]] -name = "wasmtime-profiling" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "984d29c8add3381e60d649f4e3e2a501da900fc2d2586e139502eec32fe0ebc8" -dependencies = [ - "gimli", - "goblin", - "lazy_static", - "libc", - "object", - "scroll", - "serde", - "target-lexicon", -] - [[package]] name = "wast" version = "13.0.0" @@ -9542,12 +9557,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "xdg" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" - [[package]] name = "yamux" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index d9ee8709d1334f7ffbab48f02028a94f79b5e295..8fbe1cf0d8d84f66769b92115ca1e26532a73fa5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ members = [ "client/network-gossip", "client/offchain", "client/peerset", + "client/proposer-metrics", "client/rpc-servers", "client/rpc", "client/rpc-api", diff --git a/LICENSE-APACHE2 b/LICENSE-APACHE2 new file mode 100644 index 0000000000000000000000000000000000000000..fbb0616d18b261c461b5a004f6bba6dda702ec09 --- /dev/null +++ b/LICENSE-APACHE2 @@ -0,0 +1,211 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + NOTE + +Individual files contain the following tag instead of the full license +text. + + SPDX-License-Identifier: Apache-2.0 + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ \ No newline at end of file diff --git a/LICENSE b/LICENSE-GPL3 similarity index 96% rename from LICENSE rename to LICENSE-GPL3 index 9cecc1d4669ee8af2ca727a5d8cde10cd8b2d7cc..2ba7526ee695722852efd2c162ea57f87e4fd54c 100644 --- a/LICENSE +++ b/LICENSE-GPL3 @@ -672,3 +672,29 @@ may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . + + "CLASSPATH" EXCEPTION TO THE GPL + + Linking this library statically or dynamically with other modules is making +a combined work based on this library. Thus, the terms and conditions of the +GNU General Public License cover the whole combination. + + As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent modules, +and to copy and distribute the resulting executable under terms of your +choice, provided that you also meet, for each linked independent module, +the terms and conditions of the license of that module. An independent +module is a module which is not derived from or based on this library. +If you modify this library, you may extend this exception to your version +of the library, but you are not obligated to do so. If you do not wish to +do so, delete this exception statement from your version. + + NOTE + + Individual files contain the following tag instead of the full license text. + + SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + + This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ \ No newline at end of file diff --git a/README.md b/README.md index cd00013d1ae8ad4fb86dee4044061f9b7b5e732b..5bb7ebb775c2eeefbfcfbeaefc87e7679557493f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ -# Substrate · [![GitHub license](https://img.shields.io/github/license/paritytech/substrate)](LICENSE) [![GitLab Status](https://gitlab.parity.io/parity/substrate/badges/master/pipeline.svg)](https://gitlab.parity.io/parity/substrate/pipelines) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/CONTRIBUTING.adoc) +# Substrate · [![GitHub license](https://img.shields.io/badge/license-GPL3%2FApache2-blue)](LICENSE) [![GitLab Status](https://gitlab.parity.io/parity/substrate/badges/master/pipeline.svg)](https://gitlab.parity.io/parity/substrate/pipelines) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/CONTRIBUTING.adoc) -Substrate is a next-generation framework for blockchain innovation. +

+ +

+ + +Substrate is a next-generation framework for blockchain innovation 🚀. ## Trying it out @@ -16,4 +21,4 @@ The security policy and procedures can be found in [`docs/SECURITY.md`](docs/SEC ## License -Substrate is [GPL 3.0 licensed](LICENSE). +Substrate Client (`/client/*` / `sc-*`) is licensed under [GPL v3.0 with a classpath linking exception](LICENSE-GPL3), primitives (`sp-*`), FRAME (`frame-*`) and pallets (`pallets-*`), binaries (`/bin`) and all other utilities are licensed under [Apache 2.0](LICENSE-APACHE2). diff --git a/bin/node-template/node/Cargo.toml b/bin/node-template/node/Cargo.toml index 030672ee6ff1accbe00aa9cb67a1eef37e85c44e..79f63f211a5c463a60d6f98fbebf0d096cb415f7 100644 --- a/bin/node-template/node/Cargo.toml +++ b/bin/node-template/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "node-template" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Anonymous"] description = "Substrate Node template" edition = "2018" @@ -21,25 +21,25 @@ log = "0.4.8" structopt = "0.3.8" parking_lot = "0.10.0" -sc-cli = { version = "0.8.0-dev", path = "../../../client/cli" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sc-executor = { version = "0.8.0-dev", path = "../../../client/executor" } -sc-service = { version = "0.8.0-dev", path = "../../../client/service" } -sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" } -sc-transaction-pool = { version = "2.0.0-dev", path = "../../../client/transaction-pool" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../../primitives/transaction-pool" } -sc-network = { version = "0.8.0-dev", path = "../../../client/network" } -sc-consensus-aura = { version = "0.8.0-dev", path = "../../../client/consensus/aura" } -sp-consensus-aura = { version = "0.8.0-dev", path = "../../../primitives/consensus/aura" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" } -sc-finality-grandpa = { version = "0.8.0-dev", path = "../../../client/finality-grandpa" } -sp-finality-grandpa = { version = "2.0.0-dev", path = "../../../primitives/finality-grandpa" } -sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sc-basic-authorship = { path = "../../../client/basic-authorship", version = "0.8.0-dev"} +sc-cli = { version = "0.8.0-rc2", path = "../../../client/cli" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sc-executor = { version = "0.8.0-rc2", path = "../../../client/executor" } +sc-service = { version = "0.8.0-rc2", path = "../../../client/service" } +sp-inherents = { version = "2.0.0-rc2", path = "../../../primitives/inherents" } +sc-transaction-pool = { version = "2.0.0-rc2", path = "../../../client/transaction-pool" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../../primitives/transaction-pool" } +sc-network = { version = "0.8.0-rc2", path = "../../../client/network" } +sc-consensus-aura = { version = "0.8.0-rc2", path = "../../../client/consensus/aura" } +sp-consensus-aura = { version = "0.8.0-rc2", path = "../../../primitives/consensus/aura" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sc-consensus = { version = "0.8.0-rc2", path = "../../../client/consensus/common" } +sc-finality-grandpa = { version = "0.8.0-rc2", path = "../../../client/finality-grandpa" } +sp-finality-grandpa = { version = "2.0.0-rc2", path = "../../../primitives/finality-grandpa" } +sc-client-api = { version = "2.0.0-rc2", path = "../../../client/api" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sc-basic-authorship = { path = "../../../client/basic-authorship", version = "0.8.0-rc2"} -node-template-runtime = { version = "2.0.0-dev", path = "../runtime" } +node-template-runtime = { version = "2.0.0-rc2", path = "../runtime" } [build-dependencies] -substrate-build-script-utils = { version = "2.0.0-dev", path = "../../../utils/build-script-utils" } +substrate-build-script-utils = { version = "2.0.0-rc2", path = "../../../utils/build-script-utils" } diff --git a/bin/node-template/node/src/command.rs b/bin/node-template/node/src/command.rs index baac33e9aca83311fe76a378afe04966a0337c6c..18e1b22a53f8ef1eac2f441d00b356fae6fe3e69 100644 --- a/bin/node-template/node/src/command.rs +++ b/bin/node-template/node/src/command.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::chain_spec; use crate::cli::Cli; diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 36555b5a223b56f9aa79952259a7366798e96228..8e57a041373a91b1a6bb7b5873980b612e6ef18b 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -43,7 +43,14 @@ macro_rules! new_full_start { let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); Ok(sc_transaction_pool::BasicPool::new(config, std::sync::Arc::new(pool_api), prometheus_registry)) })? - .with_import_queue(|_config, client, mut select_chain, _transaction_pool, spawn_task_handle| { + .with_import_queue(| + _config, + client, + mut select_chain, + _transaction_pool, + spawn_task_handle, + registry, + | { let select_chain = select_chain.take() .ok_or_else(|| sc_service::Error::SelectChainRequired)?; @@ -65,6 +72,7 @@ macro_rules! new_full_start { client, inherent_data_providers.clone(), spawn_task_handle, + registry, )?; import_setup = Some((grandpa_block_import, grandpa_link)); @@ -98,8 +106,11 @@ pub fn new_full(config: Configuration) -> Result Result Result NativeVersion { } parameter_types! { - pub const BlockHashCount: BlockNumber = 250; + pub const BlockHashCount: BlockNumber = 2400; /// We allow for 2 seconds of compute with a 6 second average block time. pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + /// Assume 10% of weight for average on_initialize calls. + pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() + .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; } @@ -164,6 +167,10 @@ impl system::Trait for Runtime { /// The base weight of any extrinsic processed by the runtime, independent of the /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, + /// idependent of the logic of that extrinsics. (Roughly max block weight - average on + /// initialize cost). + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. type MaximumBlockLength = MaximumBlockLength; /// Portion of the block weight that is available to all normal transactions. @@ -236,7 +243,7 @@ impl transaction_payment::Trait for Runtime { type Currency = balances::Module; type OnTransactionPayment = (); type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } @@ -281,7 +288,8 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( - system::CheckVersion, + system::CheckSpecVersion, + system::CheckTxVersion, system::CheckGenesis, system::CheckEra, system::CheckNonce, diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml index 809600b99f46722cadd1bf2d0c7c1d4c05007cc8..0cb8e006d0665053b780aa97df9cd3a786a2a23b 100644 --- a/bin/node/bench/Cargo.toml +++ b/bin/node/bench/Cargo.toml @@ -1,29 +1,30 @@ [package] name = "node-bench" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Substrate node integration benchmarks." edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] log = "0.4.8" -node-primitives = { version = "2.0.0-dev", path = "../primitives" } -node-testing = { version = "2.0.0-dev", path = "../testing" } -sc-cli = { version = "0.8.0-dev", path = "../../../client/cli" } -sc-client-api = { version = "2.0.0-dev", path = "../../../client/api/" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.8.0-dev", path = "../../../primitives/state-machine" } +node-primitives = { version = "2.0.0-rc2", path = "../primitives" } +node-testing = { version = "2.0.0-rc2", path = "../testing" } +node-runtime = { version = "2.0.0-rc2", path = "../runtime" } +sc-cli = { version = "0.8.0-rc2", path = "../../../client/cli" } +sc-client-api = { version = "2.0.0-rc2", path = "../../../client/api/" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../../primitives/state-machine" } serde = "1.0.101" serde_json = "1.0.41" structopt = "0.3" derive_more = "0.99.2" -kvdb = "0.5" -kvdb-rocksdb = "0.7" -sp-trie = { version = "2.0.0-dev", path = "../../../primitives/trie" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } +kvdb = "0.6" +kvdb-rocksdb = "0.8" +sp-trie = { version = "2.0.0-rc2", path = "../../../primitives/trie" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } hash-db = "0.15.2" tempfile = "3.1.0" fs_extra = "1" diff --git a/bin/node/bench/src/core.rs b/bin/node/bench/src/core.rs index db0b1180f4f20af35bddda8f9d7794de96887712..c1b1711549be17daf43024caae16ee356d0c889c 100644 --- a/bin/node/bench/src/core.rs +++ b/bin/node/bench/src/core.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{fmt, borrow::{Cow, ToOwned}}; use serde::Serialize; @@ -73,14 +75,14 @@ impl fmt::Display for NsFormatter { } if self.0 < 1_000_000 { - return write!(f, "{:.2} ms", v as f64 / 1_000_000.0) + return write!(f, "{:.4} ms", v as f64 / 1_000_000.0) } if self.0 < 100_000_000 { - return write!(f, "{} ms", v as f64 / 1_000_000.0) + return write!(f, "{:.1} ms", v as f64 / 1_000_000.0) } - write!(f, "{:.2} s", v as f64 / 1_000_000_000.0) + write!(f, "{:.4} s", v as f64 / 1_000_000_000.0) } } diff --git a/bin/node/bench/src/generator.rs b/bin/node/bench/src/generator.rs index 895f523497036d26dcd517da7700b9c10ef19f59..759a4299c72758f540e92349de6a25591c506d39 100644 --- a/bin/node/bench/src/generator.rs +++ b/bin/node/bench/src/generator.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{collections::HashMap, sync::Arc}; diff --git a/bin/node/bench/src/import.rs b/bin/node/bench/src/import.rs index 1fd2bbdecccb1280357798234b73619f25bf9f7b..c1b324c03cf2be3dd4a6b544ac7fcec7d116a8b2 100644 --- a/bin/node/bench/src/import.rs +++ b/bin/node/bench/src/import.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Block import benchmark. //! @@ -30,10 +32,11 @@ use std::borrow::Cow; -use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes}; +use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes, DatabaseType}; use node_primitives::Block; use sc_client_api::backend::Backend; use sp_runtime::generic::BlockId; +use sp_state_machine::InspectState; use crate::core::{self, Path, Mode}; @@ -50,19 +53,19 @@ pub enum SizeType { #[display(fmt = "full")] Full, #[display(fmt = "custom")] - Custom, + Custom(usize), } impl SizeType { - pub fn transactions(&self) -> usize { + pub fn transactions(&self) -> Option { match self { - SizeType::Empty => 0, - SizeType::Small => 10, - SizeType::Medium => 100, - SizeType::Large => 500, - SizeType::Full => 4000, + SizeType::Empty => Some(0), + SizeType::Small => Some(10), + SizeType::Medium => Some(100), + SizeType::Large => Some(500), + SizeType::Full => None, // Custom SizeType will use the `--transactions` input parameter - SizeType::Custom => 0, + SizeType::Custom(val) => Some(*val), } } } @@ -72,12 +75,14 @@ pub struct ImportBenchmarkDescription { pub key_types: KeyTypes, pub block_type: BlockType, pub size: SizeType, + pub database_type: DatabaseType, } pub struct ImportBenchmark { profile: Profile, database: BenchDb, block: Block, + block_type: BlockType, } impl core::BenchmarkDescription for ImportBenchmarkDescription { @@ -96,9 +101,14 @@ impl core::BenchmarkDescription for ImportBenchmarkDescription { } match self.block_type { - BlockType::RandomTransfersKeepAlive(_) => path.push("transfer_keep_alive"), - BlockType::RandomTransfersReaping(_) => path.push("transfer_reaping"), - BlockType::Noop(_) => path.push("noop"), + BlockType::RandomTransfersKeepAlive => path.push("transfer_keep_alive"), + BlockType::RandomTransfersReaping => path.push("transfer_reaping"), + BlockType::Noop => path.push("noop"), + } + + match self.database_type { + DatabaseType::RocksDb => path.push("rocksdb"), + DatabaseType::ParityDb => path.push("paritydb"), } path.push(&format!("{}", self.size)); @@ -109,12 +119,14 @@ impl core::BenchmarkDescription for ImportBenchmarkDescription { fn setup(self: Box) -> Box { let profile = self.profile; let mut bench_db = BenchDb::with_key_types( + self.database_type, 50_000, self.key_types ); - let block = bench_db.generate_block(self.block_type); + let block = bench_db.generate_block(self.block_type.to_content(self.size.transactions())); Box::new(ImportBenchmark { database: bench_db, + block_type: self.block_type, block, profile, }) @@ -122,9 +134,10 @@ impl core::BenchmarkDescription for ImportBenchmarkDescription { fn name(&self) -> Cow<'static, str> { format!( - "Import benchmark ({:?}, {:?})", + "Import benchmark ({:?}, {:?}, {:?} backend)", self.block_type, self.profile, + self.database_type, ).into() } } @@ -145,6 +158,41 @@ impl core::Benchmark for ImportBenchmark { context.import_block(self.block.clone()); let elapsed = start.elapsed(); + // Sanity checks. + context.client.state_at(&BlockId::number(1)).expect("state_at failed for block#1") + .inspect_with(|| { + match self.block_type { + BlockType::RandomTransfersKeepAlive => { + // should be 5 per signed extrinsic + 1 per unsigned + // we have 1 unsigned and the rest are signed in the block + // those 5 events per signed are: + // - new account (RawEvent::NewAccount) as we always transfer fund to non-existant account + // - endowed (RawEvent::Endowed) for this new account + // - successful transfer (RawEvent::Transfer) for this transfer operation + // - deposit event for charging transaction fee + // - extrinsic success + assert_eq!( + node_runtime::System::events().len(), + (self.block.extrinsics.len() - 1) * 5 + 1, + ); + }, + BlockType::Noop => { + assert_eq!( + node_runtime::System::events().len(), + + // should be 2 per signed extrinsic + 1 per unsigned + // we have 1 unsigned and the rest are signed in the block + // those 2 events per signed are: + // - deposit event for charging transaction fee + // - extrinsic success + (self.block.extrinsics.len() - 1) * 2 + 1, + ); + }, + _ => {}, + } + } + ); + if mode == Mode::Profile { std::thread::park_timeout(std::time::Duration::from_secs(1)); } diff --git a/bin/node/bench/src/main.rs b/bin/node/bench/src/main.rs index e627f07c3d44070dfaa9db10b7eef024acc7c49f..5c5af3703857ae9aa01110252dd70fa60417459e 100644 --- a/bin/node/bench/src/main.rs +++ b/bin/node/bench/src/main.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . #[macro_use] mod core; mod import; @@ -26,7 +28,7 @@ use crate::core::{run_benchmark, Mode as BenchmarkMode}; use crate::tempdb::DatabaseType; use import::{ImportBenchmarkDescription, SizeType}; use trie::{TrieReadBenchmarkDescription, TrieWriteBenchmarkDescription, DatabaseSize}; -use node_testing::bench::{Profile, KeyTypes, BlockType}; +use node_testing::bench::{Profile, KeyTypes, BlockType, DatabaseType as BenchDataBaseType}; use structopt::StructOpt; #[derive(Debug, StructOpt)] @@ -79,29 +81,28 @@ fn main() { SizeType::Medium, SizeType::Large, SizeType::Full, - SizeType::Custom, + SizeType::Custom(opt.transactions.unwrap_or(0)), ].iter() { - let txs = match size { - SizeType::Custom => opt.transactions.unwrap_or(0), - _ => size.transactions() - }; for block_type in [ - BlockType::RandomTransfersKeepAlive(txs), - BlockType::RandomTransfersReaping(txs), - BlockType::Noop(txs), + BlockType::RandomTransfersKeepAlive, + BlockType::RandomTransfersReaping, + BlockType::Noop, ].iter() { - import_benchmarks.push((profile.clone(), size.clone(), block_type.clone())); + for database_type in [BenchDataBaseType::RocksDb, BenchDataBaseType::ParityDb].iter() { + import_benchmarks.push((profile, size.clone(), block_type.clone(), database_type)); + } } } } let benchmarks = matrix!( - (profile, size, block_type) in import_benchmarks.iter() => + (profile, size, block_type, database_type) in import_benchmarks.into_iter() => ImportBenchmarkDescription { profile: *profile, key_types: KeyTypes::Sr25519, - size: *size, - block_type: *block_type, + size: size, + block_type: block_type, + database_type: *database_type, }, (size, db_type) in [ @@ -128,8 +129,14 @@ fn main() { ); if opt.list { + println!("Available benchmarks:"); + if let Some(filter) = opt.filter.as_ref() { + println!("\t(filtered by \"{}\")", filter); + } for benchmark in benchmarks.iter() { - log::info!("{}: {}", benchmark.name(), benchmark.path().full()) + if opt.filter.as_ref().map(|f| benchmark.path().has(f)).unwrap_or(true) { + println!("{}: {}", benchmark.name(), benchmark.path().full()) + } } return; } @@ -145,6 +152,11 @@ fn main() { } } + if results.is_empty() { + eprintln!("No benchmark was found for query"); + std::process::exit(1); + } + if opt.json { let json_result: String = serde_json::to_string(&results).expect("Failed to construct json"); println!("{}", json_result); diff --git a/bin/node/bench/src/simple_trie.rs b/bin/node/bench/src/simple_trie.rs index 50078a11df6b5290157bdbdfbc02389f1711261b..3cfd7ddb300a9101b22d55a2d460526a283fa0e2 100644 --- a/bin/node/bench/src/simple_trie.rs +++ b/bin/node/bench/src/simple_trie.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{collections::HashMap, sync::Arc}; diff --git a/bin/node/bench/src/tempdb.rs b/bin/node/bench/src/tempdb.rs index 4a0a793a22ccb4fdc561a1eed2942eb3a2a850e6..770bafec6f38dc092ac3a905152e2c0861f54e5f 100644 --- a/bin/node/bench/src/tempdb.rs +++ b/bin/node/bench/src/tempdb.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{io, sync::Arc}; use kvdb::{KeyValueDB, DBTransaction}; @@ -41,17 +43,14 @@ impl KeyValueDB for ParityDbWrapper { } /// Write a transaction of changes to the buffer. - fn write_buffered(&self, transaction: DBTransaction) { + fn write(&self, transaction: DBTransaction) -> io::Result<()> { self.0.commit( transaction.ops.iter().map(|op| match op { kvdb::DBOp::Insert { col, key, value } => (*col as u8, &key[key.len() - 32..], Some(value.to_vec())), kvdb::DBOp::Delete { col, key } => (*col as u8, &key[key.len() - 32..], None), + kvdb::DBOp::DeletePrefix { col: _, prefix: _ } => unimplemented!() }) ).expect("db error"); - } - - /// Flush all buffered data. - fn flush(&self) -> io::Result<()> { Ok(()) } @@ -61,7 +60,7 @@ impl KeyValueDB for ParityDbWrapper { } /// Iterate over flushed data for a given column, starting from a given prefix. - fn iter_from_prefix<'a>( + fn iter_with_prefix<'a>( &'a self, _col: u32, _prefix: &'a [u8], diff --git a/bin/node/bench/src/trie.rs b/bin/node/bench/src/trie.rs index 9a52e3c301617dfe8e6524389974b827c5115e6a..886dc6011492f4564aa679f6f5f483025c057b58 100644 --- a/bin/node/bench/src/trie.rs +++ b/bin/node/bench/src/trie.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Trie benchmark (integrated). diff --git a/bin/node/browser-testing/Cargo.toml b/bin/node/browser-testing/Cargo.toml index 391f2fa2267d596c040ed43d55c668b38d017205..7628582fbb0471bcb402feae204c041e22250d5a 100644 --- a/bin/node/browser-testing/Cargo.toml +++ b/bin/node/browser-testing/Cargo.toml @@ -1,21 +1,21 @@ [package] name = "node-browser-testing" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] description = "Tests for the in-browser light client." edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" [dependencies] futures-timer = "3.0.2" -libp2p = { version = "0.18.0", default-features = false } +libp2p = { version = "0.19.1", default-features = false } jsonrpc-core = "14.0.5" serde = "1.0.106" serde_json = "1.0.48" -wasm-bindgen = { version = "0.2.60", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.62", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.10" wasm-bindgen-test = "0.3.10" futures = "0.3.4" -node-cli = { path = "../cli", default-features = false, features = ["browser"] , version = "2.0.0-dev"} -sc-rpc-api = { path = "../../../client/rpc-api" , version = "0.8.0-dev"} +node-cli = { path = "../cli", default-features = false, features = ["browser"] , version = "2.0.0-rc2"} +sc-rpc-api = { path = "../../../client/rpc-api" , version = "0.8.0-rc2"} diff --git a/bin/node/browser-testing/src/lib.rs b/bin/node/browser-testing/src/lib.rs index 65f1e4620ba9c8aa59164e8776f051d513f7489d..c943a383aefadf78fdf3af67458a0c488d55497b 100644 --- a/bin/node/browser-testing/src/lib.rs +++ b/bin/node/browser-testing/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Running //! Running this test can be done with diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index de38ac66e548906b89d95ed934a6907e92692a89..f2b25068edfd8fde0510ed7023e8587b0b48ffd1 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "node-cli" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] description = "Generic Substrate node implementation in Rust." build = "build.rs" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" default-run = "substrate" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -46,76 +46,76 @@ tracing = "0.1.10" parking_lot = "0.10.0" # primitives -sp-authority-discovery = { version = "2.0.0-dev", path = "../../../primitives/authority-discovery" } -sp-consensus-babe = { version = "0.8.0-dev", path = "../../../primitives/consensus/babe" } -grandpa-primitives = { version = "2.0.0-dev", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/timestamp" } -sp-finality-tracker = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/finality-tracker" } -sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" } -sp-keyring = { version = "2.0.0-dev", path = "../../../primitives/keyring" } -sp-io = { version = "2.0.0-dev", path = "../../../primitives/io" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../../primitives/transaction-pool" } +sp-authority-discovery = { version = "2.0.0-rc2", path = "../../../primitives/authority-discovery" } +sp-consensus-babe = { version = "0.8.0-rc2", path = "../../../primitives/consensus/babe" } +grandpa-primitives = { version = "2.0.0-rc2", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/timestamp" } +sp-finality-tracker = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/finality-tracker" } +sp-inherents = { version = "2.0.0-rc2", path = "../../../primitives/inherents" } +sp-keyring = { version = "2.0.0-rc2", path = "../../../primitives/keyring" } +sp-io = { version = "2.0.0-rc2", path = "../../../primitives/io" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../../primitives/transaction-pool" } # client dependencies -sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" } -sc-chain-spec = { version = "2.0.0-dev", path = "../../../client/chain-spec" } -sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" } -sc-transaction-pool = { version = "2.0.0-dev", path = "../../../client/transaction-pool" } -sc-network = { version = "0.8.0-dev", path = "../../../client/network" } -sc-consensus-babe = { version = "0.8.0-dev", path = "../../../client/consensus/babe" } -grandpa = { version = "0.8.0-dev", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } -sc-client-db = { version = "0.8.0-dev", default-features = false, path = "../../../client/db" } -sc-offchain = { version = "2.0.0-dev", path = "../../../client/offchain" } -sc-rpc = { version = "2.0.0-dev", path = "../../../client/rpc" } -sc-basic-authorship = { version = "0.8.0-dev", path = "../../../client/basic-authorship" } -sc-service = { version = "0.8.0-dev", default-features = false, path = "../../../client/service" } -sc-tracing = { version = "2.0.0-dev", path = "../../../client/tracing" } -sc-telemetry = { version = "2.0.0-dev", path = "../../../client/telemetry" } -sc-authority-discovery = { version = "0.8.0-dev", path = "../../../client/authority-discovery" } +sc-client-api = { version = "2.0.0-rc2", path = "../../../client/api" } +sc-chain-spec = { version = "2.0.0-rc2", path = "../../../client/chain-spec" } +sc-consensus = { version = "0.8.0-rc2", path = "../../../client/consensus/common" } +sc-transaction-pool = { version = "2.0.0-rc2", path = "../../../client/transaction-pool" } +sc-network = { version = "0.8.0-rc2", path = "../../../client/network" } +sc-consensus-babe = { version = "0.8.0-rc2", path = "../../../client/consensus/babe" } +grandpa = { version = "0.8.0-rc2", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } +sc-client-db = { version = "0.8.0-rc2", default-features = false, path = "../../../client/db" } +sc-offchain = { version = "2.0.0-rc2", path = "../../../client/offchain" } +sc-rpc = { version = "2.0.0-rc2", path = "../../../client/rpc" } +sc-basic-authorship = { version = "0.8.0-rc2", path = "../../../client/basic-authorship" } +sc-service = { version = "0.8.0-rc2", default-features = false, path = "../../../client/service" } +sc-tracing = { version = "2.0.0-rc2", path = "../../../client/tracing" } +sc-telemetry = { version = "2.0.0-rc2", path = "../../../client/telemetry" } +sc-authority-discovery = { version = "0.8.0-rc2", path = "../../../client/authority-discovery" } # frame dependencies -pallet-indices = { version = "2.0.0-dev", path = "../../../frame/indices" } -pallet-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../../frame/timestamp" } -pallet-contracts = { version = "2.0.0-dev", path = "../../../frame/contracts" } -frame-system = { version = "2.0.0-dev", path = "../../../frame/system" } -pallet-balances = { version = "2.0.0-dev", path = "../../../frame/balances" } -pallet-transaction-payment = { version = "2.0.0-dev", path = "../../../frame/transaction-payment" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../../../frame/support" } -pallet-im-online = { version = "2.0.0-dev", default-features = false, path = "../../../frame/im-online" } -pallet-authority-discovery = { version = "2.0.0-dev", path = "../../../frame/authority-discovery" } -pallet-staking = { version = "2.0.0-dev", path = "../../../frame/staking" } -pallet-grandpa = { version = "2.0.0-dev", path = "../../../frame/grandpa" } +pallet-indices = { version = "2.0.0-rc2", path = "../../../frame/indices" } +pallet-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/timestamp" } +pallet-contracts = { version = "2.0.0-rc2", path = "../../../frame/contracts" } +frame-system = { version = "2.0.0-rc2", path = "../../../frame/system" } +pallet-balances = { version = "2.0.0-rc2", path = "../../../frame/balances" } +pallet-transaction-payment = { version = "2.0.0-rc2", path = "../../../frame/transaction-payment" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/support" } +pallet-im-online = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/im-online" } +pallet-authority-discovery = { version = "2.0.0-rc2", path = "../../../frame/authority-discovery" } +pallet-staking = { version = "2.0.0-rc2", path = "../../../frame/staking" } +pallet-grandpa = { version = "2.0.0-rc2", path = "../../../frame/grandpa" } # node-specific dependencies -node-runtime = { version = "2.0.0-dev", path = "../runtime" } -node-rpc = { version = "2.0.0-dev", path = "../rpc" } -node-primitives = { version = "2.0.0-dev", path = "../primitives" } -node-executor = { version = "2.0.0-dev", path = "../executor" } +node-runtime = { version = "2.0.0-rc2", path = "../runtime" } +node-rpc = { version = "2.0.0-rc2", path = "../rpc" } +node-primitives = { version = "2.0.0-rc2", path = "../primitives" } +node-executor = { version = "2.0.0-rc2", path = "../executor" } # CLI-specific dependencies -sc-cli = { version = "0.8.0-dev", optional = true, path = "../../../client/cli" } -frame-benchmarking-cli = { version = "2.0.0-dev", optional = true, path = "../../../utils/frame/benchmarking-cli" } -node-inspect = { version = "0.8.0-dev", optional = true, path = "../inspect" } +sc-cli = { version = "0.8.0-rc2", optional = true, path = "../../../client/cli" } +frame-benchmarking-cli = { version = "2.0.0-rc2", optional = true, path = "../../../utils/frame/benchmarking-cli" } +node-inspect = { version = "0.8.0-rc2", optional = true, path = "../inspect" } # WASM-specific dependencies wasm-bindgen = { version = "0.2.57", optional = true } wasm-bindgen-futures = { version = "0.4.7", optional = true } -browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.8.0-dev"} +browser-utils = { package = "substrate-browser-utils", path = "../../../utils/browser", optional = true, version = "0.8.0-rc2"} [target.'cfg(target_arch="x86_64")'.dependencies] -node-executor = { version = "2.0.0-dev", path = "../executor", features = [ "wasmtime" ] } -sc-cli = { version = "0.8.0-dev", optional = true, path = "../../../client/cli", features = [ "wasmtime" ] } -sc-service = { version = "0.8.0-dev", default-features = false, path = "../../../client/service", features = [ "wasmtime" ] } +node-executor = { version = "2.0.0-rc2", path = "../executor", features = [ "wasmtime" ] } +sc-cli = { version = "0.8.0-rc2", optional = true, path = "../../../client/cli", features = [ "wasmtime" ] } +sc-service = { version = "0.8.0-rc2", default-features = false, path = "../../../client/service", features = [ "wasmtime" ] } [dev-dependencies] -sc-keystore = { version = "2.0.0-dev", path = "../../../client/keystore" } -sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" } -sc-consensus-babe = { version = "0.8.0-dev", features = ["test-helpers"], path = "../../../client/consensus/babe" } -sc-consensus-epochs = { version = "0.8.0-dev", path = "../../../client/consensus/epochs" } -sc-service-test = { version = "2.0.0-dev", path = "../../../client/service/test" } +sc-keystore = { version = "2.0.0-rc2", path = "../../../client/keystore" } +sc-consensus = { version = "0.8.0-rc2", path = "../../../client/consensus/common" } +sc-consensus-babe = { version = "0.8.0-rc2", features = ["test-helpers"], path = "../../../client/consensus/babe" } +sc-consensus-epochs = { version = "0.8.0-rc2", path = "../../../client/consensus/epochs" } +sc-service-test = { version = "2.0.0-rc2", path = "../../../client/service/test" } futures = "0.3.4" tempfile = "3.1.0" assert_cmd = "1.0" @@ -126,12 +126,12 @@ platforms = "0.2.1" [build-dependencies] structopt = { version = "0.3.8", optional = true } -node-inspect = { version = "0.8.0-dev", optional = true, path = "../inspect" } -frame-benchmarking-cli = { version = "2.0.0-dev", optional = true, path = "../../../utils/frame/benchmarking-cli" } -substrate-build-script-utils = { version = "2.0.0-dev", optional = true, path = "../../../utils/build-script-utils" } +node-inspect = { version = "0.8.0-rc2", optional = true, path = "../inspect" } +frame-benchmarking-cli = { version = "2.0.0-rc2", optional = true, path = "../../../utils/frame/benchmarking-cli" } +substrate-build-script-utils = { version = "2.0.0-rc2", optional = true, path = "../../../utils/build-script-utils" } [build-dependencies.sc-cli] -version = "0.8.0-dev" +version = "0.8.0-rc2" package = "sc-cli" path = "../../../client/cli" optional = true diff --git a/bin/node/cli/bin/main.rs b/bin/node/cli/bin/main.rs index cfad84a4cb5520f2542dc18da771d4cfa4a0a9ed..299b760c82e36b2b6540f6ae4efd8111cf430640 100644 --- a/bin/node/cli/bin/main.rs +++ b/bin/node/cli/bin/main.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate Node CLI diff --git a/bin/node/cli/build.rs b/bin/node/cli/build.rs index 12e0cab58ada5797c069e9a24970be6daa06de4f..a36f0d01a0a034a10686d3565e6abf538e6a5886 100644 --- a/bin/node/cli/build.rs +++ b/bin/node/cli/build.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . fn main() { #[cfg(feature = "cli")] diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs index 861d37c6058e1aff0640da97a6ad2fdce622abd2..8d74e3cbf3f0966bb938aecae73a541adc40ca49 100644 --- a/bin/node/cli/src/browser.rs +++ b/bin/node/cli/src/browser.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::chain_spec::ChainSpec; use log::info; diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index ea3999fa377187958f7e28bf87376a7eaf83a93b..c1eadc2f937c0ad62ddd499df26474029b479979 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate chain configurations. diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index fa9a43ee6841ca88302810ecb81b6d1bed5f77c0..0156faf47ee4ade0593d2b89752a0b37cd1a13dc 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use sc_cli::RunCmd; use structopt::StructOpt; diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index 91c6298c9fd5c5751dab747d23d0d46d3e1a15d0..bd5483f2cd31e21d5bcd6c274c0fbe24f53156da 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::{chain_spec, service, Cli, Subcommand}; use node_executor::Executor; @@ -63,8 +65,6 @@ impl SubstrateCli for Cli { /// Parse command line arguments into service configuration. pub fn run() -> Result<()> { - sc_cli::reset_signal_pipe_handler()?; - let cli = Cli::from_args(); match &cli.subcommand { diff --git a/bin/node/cli/src/lib.rs b/bin/node/cli/src/lib.rs index 3c49f9176f15b96df4bd4ae87ea407b713f340e1..bd2298514a7a2f1ed57fa008615b11ac0947d20b 100644 --- a/bin/node/cli/src/lib.rs +++ b/bin/node/cli/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate CLI library. //! diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 7e27d57063ecfef242c010c05b9b08ab5f2e71f1..05f168bd8bad9cf6bea3726426aaae1fc6a5b216 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . #![warn(unused_extern_crates)] @@ -41,7 +43,6 @@ macro_rules! new_full_start { ($config:expr) => {{ use std::sync::Arc; - type RpcExtension = jsonrpc_core::IoHandler; let mut import_setup = None; let mut rpc_setup = None; let inherent_data_providers = sp_inherents::InherentDataProviders::new(); @@ -60,7 +61,14 @@ macro_rules! new_full_start { prometheus_registry, )) })? - .with_import_queue(|_config, client, mut select_chain, _transaction_pool, spawn_task_handle| { + .with_import_queue(| + _config, + client, + mut select_chain, + _transaction_pool, + spawn_task_handle, + prometheus_registry, + | { let select_chain = select_chain.take() .ok_or_else(|| sc_service::Error::SelectChainRequired)?; let (grandpa_block_import, grandpa_link) = grandpa::block_import( @@ -84,35 +92,52 @@ macro_rules! new_full_start { client, inherent_data_providers.clone(), spawn_task_handle, + prometheus_registry, )?; import_setup = Some((block_import, grandpa_link, babe_link)); Ok(import_queue) })? - .with_rpc_extensions(|builder| -> std::result::Result { - let babe_link = import_setup.as_ref().map(|s| &s.2) - .expect("BabeLink is present for full services or set up failed; qed."); + .with_rpc_extensions_builder(|builder| { let grandpa_link = import_setup.as_ref().map(|s| &s.1) .expect("GRANDPA LinkHalf is present for full services or set up failed; qed."); - let shared_authority_set = grandpa_link.shared_authority_set(); + + let shared_authority_set = grandpa_link.shared_authority_set().clone(); let shared_voter_state = grandpa::SharedVoterState::empty(); - let deps = node_rpc::FullDeps { - client: builder.client().clone(), - pool: builder.pool(), - select_chain: builder.select_chain().cloned() - .expect("SelectChain is present for full services or set up failed; qed."), - babe: node_rpc::BabeDeps { - keystore: builder.keystore(), - babe_config: sc_consensus_babe::BabeLink::config(babe_link).clone(), - shared_epoch_changes: sc_consensus_babe::BabeLink::epoch_changes(babe_link).clone() - }, - grandpa: node_rpc::GrandpaDeps { - shared_voter_state: shared_voter_state.clone(), - shared_authority_set: shared_authority_set.clone(), - }, - }; - rpc_setup = Some((shared_voter_state)); - Ok(node_rpc::create_full(deps)) + + rpc_setup = Some((shared_voter_state.clone())); + + let babe_link = import_setup.as_ref().map(|s| &s.2) + .expect("BabeLink is present for full services or set up failed; qed."); + + let babe_config = babe_link.config().clone(); + let shared_epoch_changes = babe_link.epoch_changes().clone(); + + let client = builder.client().clone(); + let pool = builder.pool().clone(); + let select_chain = builder.select_chain().cloned() + .expect("SelectChain is present for full services or set up failed; qed."); + let keystore = builder.keystore().clone(); + + Ok(move |deny_unsafe| { + let deps = node_rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + select_chain: select_chain.clone(), + deny_unsafe, + babe: node_rpc::BabeDeps { + babe_config: babe_config.clone(), + shared_epoch_changes: shared_epoch_changes.clone(), + keystore: keystore.clone(), + }, + grandpa: node_rpc::GrandpaDeps { + shared_voter_state: shared_voter_state.clone(), + shared_authority_set: shared_authority_set.clone(), + }, + }; + + node_rpc::create_full(deps) + }) })?; (builder, import_setup, inherent_data_providers, rpc_setup) @@ -163,7 +188,8 @@ macro_rules! new_full { if let sc_service::config::Role::Authority { .. } = &role { let proposer = sc_basic_authorship::ProposerFactory::new( service.client(), - service.transaction_pool() + service.transaction_pool(), + service.prometheus_registry().as_ref(), ); let client = service.client(); @@ -291,7 +317,6 @@ pub fn new_full(config: Configuration) /// Builds a new service for a light client. pub fn new_light(config: Configuration) -> Result { - type RpcExtension = jsonrpc_core::IoHandler; let inherent_data_providers = InherentDataProviders::new(); let service = ServiceBuilder::new_light::(config)? @@ -307,7 +332,16 @@ pub fn new_light(config: Configuration) ); Ok(pool) })? - .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool, spawn_task_handle| { + .with_import_queue_and_fprb(| + _config, + client, + backend, + fetcher, + _select_chain, + _tx_pool, + spawn_task_handle, + registry, + | { let fetch_checker = fetcher .map(|fetcher| fetcher.checker().clone()) .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; @@ -336,6 +370,7 @@ pub fn new_light(config: Configuration) client.clone(), inherent_data_providers.clone(), spawn_task_handle, + registry, )?; Ok((import_queue, finality_proof_request_builder)) @@ -345,9 +380,7 @@ pub fn new_light(config: Configuration) let provider = client as Arc>; Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) })? - .with_rpc_extensions(|builder,| -> - Result - { + .with_rpc_extensions(|builder| { let fetcher = builder.fetcher() .ok_or_else(|| "Trying to start node RPC without active fetcher")?; let remote_blockchain = builder.remote_backend() @@ -359,6 +392,7 @@ pub fn new_light(config: Configuration) client: builder.client().clone(), pool: builder.pool(), }; + Ok(node_rpc::create_light(light_deps)) })? .build()?; @@ -398,83 +432,6 @@ mod tests { type AccountPublic = ::Signer; - #[cfg(feature = "rhd")] - fn test_sync() { - use sp_core::ed25519::Pair; - - use {service_test, Factory}; - use sp_consensus::{BlockImportParams, BlockOrigin}; - - let alice: Arc = Arc::new(Keyring::Alice.into()); - let bob: Arc = Arc::new(Keyring::Bob.into()); - let validators = vec![alice.public().0.into(), bob.public().0.into()]; - let keys: Vec<&ed25519::Pair> = vec![&*alice, &*bob]; - let dummy_runtime = ::tokio::runtime::Runtime::new().unwrap(); - let block_factory = |service: &::FullService| { - let block_id = BlockId::number(service.client().chain_info().best_number); - let parent_header = service.client().best_header(&block_id) - .expect("db error") - .expect("best block should exist"); - - futures::executor::block_on( - service.transaction_pool().maintain( - ChainEvent::NewBlock { - is_new_best: true, - id: block_id.clone(), - retracted: vec![], - header: parent_header, - }, - ) - ); - - let consensus_net = ConsensusNetwork::new(service.network(), service.client().clone()); - let proposer_factory = consensus::ProposerFactory { - client: service.client().clone(), - transaction_pool: service.transaction_pool().clone(), - network: consensus_net, - force_delay: 0, - handle: dummy_runtime.executor(), - }; - let (proposer, _, _) = proposer_factory.init(&parent_header, &validators, alice.clone()).unwrap(); - let block = proposer.propose().expect("Error making test block"); - BlockImportParams { - origin: BlockOrigin::File, - justification: Vec::new(), - internal_justification: Vec::new(), - finalized: false, - body: Some(block.extrinsics), - storage_changes: None, - header: block.header, - auxiliary: Vec::new(), - } - }; - let extrinsic_factory = - |service: &SyncService<::FullService>| - { - let payload = ( - 0, - Call::Balances(BalancesCall::transfer(RawAddress::Id(bob.public().0.into()), 69.into())), - Era::immortal(), - service.client().genesis_hash() - ); - let signature = alice.sign(&payload.encode()).into(); - let id = alice.public().0.into(); - let xt = UncheckedExtrinsic { - signature: Some((RawAddress::Id(id), signature, payload.0, Era::immortal())), - function: payload.1, - }.encode(); - let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); - OpaqueExtrinsic(v) - }; - sc_service_test::sync( - sc_chain_spec::integration_test_config(), - |config| new_full(config), - |mut config| new_light(config), - block_factory, - extrinsic_factory, - ); - } - #[test] // It is "ignored", but the node-cli ignored tests are running on the CI. // This can be run locally with `cargo test --release -p node-cli test_sync -- --ignored`. @@ -532,7 +489,8 @@ mod tests { let mut proposer_factory = sc_basic_authorship::ProposerFactory::new( service.client(), - service.transaction_pool() + service.transaction_pool(), + None, ); let epoch_descriptor = babe_link.epoch_changes().lock().epoch_descriptor_for_child_of( @@ -602,12 +560,16 @@ mod tests { let from: Address = AccountPublic::from(charlie.public()).into_account().into(); let genesis_hash = service.client().block_hash(0).unwrap().unwrap(); let best_block_id = BlockId::number(service.client().chain_info().best_number); - let version = service.client().runtime_version_at(&best_block_id).unwrap().spec_version; + let (spec_version, transaction_version) = { + let version = service.client().runtime_version_at(&best_block_id).unwrap(); + (version.spec_version, version.transaction_version) + }; let signer = charlie.clone(); let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); - let check_version = frame_system::CheckVersion::new(); + let check_spec_version = frame_system::CheckSpecVersion::new(); + let check_tx_version = frame_system::CheckTxVersion::new(); let check_genesis = frame_system::CheckGenesis::new(); let check_era = frame_system::CheckEra::from(Era::Immortal); let check_nonce = frame_system::CheckNonce::from(index); @@ -615,7 +577,8 @@ mod tests { let payment = pallet_transaction_payment::ChargeTransactionPayment::from(0); let validate_grandpa_equivocation = pallet_grandpa::ValidateEquivocationReport::new(); let extra = ( - check_version, + check_spec_version, + check_tx_version, check_genesis, check_era, check_nonce, @@ -626,7 +589,7 @@ mod tests { let raw_payload = SignedPayload::from_raw( function, extra, - (version, genesis_hash, genesis_hash, (), (), (), ()) + (spec_version, transaction_version, genesis_hash, genesis_hash, (), (), (), ()) ); let signature = raw_payload.using_encoded(|payload| { signer.sign(payload) diff --git a/bin/node/cli/tests/build_spec_works.rs b/bin/node/cli/tests/build_spec_works.rs index 2eca71a5b5978de1e1de20873b6584a7d5c703b0..800a4a8c51e6175e2eb8fbfb1e5ddf375d30c264 100644 --- a/bin/node/cli/tests/build_spec_works.rs +++ b/bin/node/cli/tests/build_spec_works.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use assert_cmd::cargo::cargo_bin; use std::process::Command; diff --git a/bin/node/cli/tests/check_block_works.rs b/bin/node/cli/tests/check_block_works.rs index 6bfb82a8bfafb84c1b041b87dc093e2481193ec5..34078b08cf074f218865df548ee20b3b94f19d74 100644 --- a/bin/node/cli/tests/check_block_works.rs +++ b/bin/node/cli/tests/check_block_works.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . #![cfg(unix)] @@ -20,7 +22,7 @@ use assert_cmd::cargo::cargo_bin; use std::process::Command; use tempfile::tempdir; -mod common; +pub mod common; #[test] fn check_block_works() { diff --git a/bin/node/cli/tests/common.rs b/bin/node/cli/tests/common.rs index 34e371195c16b20e216a9426f238ce6b78bcd257..61a07dd1ca877c8814169f2babdfccd3a506ec76 100644 --- a/bin/node/cli/tests/common.rs +++ b/bin/node/cli/tests/common.rs @@ -1,21 +1,22 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . #![cfg(unix)] -#![allow(dead_code)] use std::{process::{Child, ExitStatus}, thread, time::Duration, path::Path}; use assert_cmd::cargo::cargo_bin; diff --git a/bin/node/cli/tests/export_import_flow.rs b/bin/node/cli/tests/export_import_flow.rs new file mode 100644 index 0000000000000000000000000000000000000000..557e722ddb7b505a13fa8daa8361838dcfd93c45 --- /dev/null +++ b/bin/node/cli/tests/export_import_flow.rs @@ -0,0 +1,212 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +#![cfg(unix)] + +use assert_cmd::cargo::cargo_bin; +use std::{process::Command, fs, path::PathBuf}; +use tempfile::{tempdir, TempDir}; +use regex::Regex; + +pub mod common; + +fn contains_error(logged_output: &str) -> bool { + logged_output.contains("Error") +} + +/// Helper struct to execute the export/import/revert tests. +/// The fields are paths to a temporary directory +struct ExportImportRevertExecutor<'a> { + base_path: &'a TempDir, + exported_blocks_file: &'a PathBuf, + db_path: &'a PathBuf, + num_exported_blocks: Option, +} + +/// Format options for export / import commands. +enum FormatOpt { + Json, + Binary, +} + +/// Command corresponding to the different commands we would like to run. +enum SubCommand { + ExportBlocks, + ImportBlocks, +} + +impl ToString for SubCommand { + fn to_string(&self) -> String { + match self { + SubCommand::ExportBlocks => String::from("export-blocks"), + SubCommand::ImportBlocks => String::from("import-blocks"), + } + } +} + +impl<'a> ExportImportRevertExecutor<'a> { + fn new( + base_path: &'a TempDir, + exported_blocks_file: &'a PathBuf, + db_path: &'a PathBuf + ) -> Self { + Self { + base_path, + exported_blocks_file, + db_path, + num_exported_blocks: None, + } + } + + /// Helper method to run a command. Returns a string corresponding to what has been logged. + fn run_block_command(&self, + sub_command: SubCommand, + format_opt: FormatOpt, + expected_to_fail: bool + ) -> String { + let sub_command_str = sub_command.to_string(); + // Adding "--binary" if need be. + let arguments: Vec<&str> = match format_opt { + FormatOpt::Binary => vec![&sub_command_str, "--dev", "--pruning", "archive", "--binary", "-d"], + FormatOpt::Json => vec![&sub_command_str, "--dev", "--pruning", "archive", "-d"], + }; + + let tmp: TempDir; + // Setting base_path to be a temporary folder if we are importing blocks. + // This allows us to make sure we are importing from scratch. + let base_path = match sub_command { + SubCommand::ExportBlocks => &self.base_path.path(), + SubCommand::ImportBlocks => { + tmp = tempdir().unwrap(); + tmp.path() + } + }; + + // Running the command and capturing the output. + let output = Command::new(cargo_bin("substrate")) + .args(&arguments) + .arg(&base_path) + .arg(&self.exported_blocks_file) + .output() + .unwrap(); + + let logged_output = String::from_utf8_lossy(&output.stderr).to_string(); + + if expected_to_fail { + // Checking that we did indeed find an error. + assert!(contains_error(&logged_output), "expected to error but did not error!"); + assert!(!output.status.success()); + } else { + // Making sure no error were logged. + assert!(!contains_error(&logged_output), "expected not to error but error'd!"); + assert!(output.status.success()); + } + + logged_output + } + + /// Runs the `export-blocks` command. + fn run_export(&mut self, fmt_opt: FormatOpt) { + let log = self.run_block_command(SubCommand::ExportBlocks, fmt_opt, false); + + // Using regex to find out how many block we exported. + let re = Regex::new(r"Exporting blocks from #\d* to #(?P\d*)").unwrap(); + let caps = re.captures(&log).unwrap(); + // Saving the number of blocks we've exported for further use. + self.num_exported_blocks = Some(caps["exported_blocks"].parse::().unwrap()); + + let metadata = fs::metadata(&self.exported_blocks_file).unwrap(); + assert!(metadata.len() > 0, "file exported_blocks should not be empty"); + + let _ = fs::remove_dir_all(&self.db_path); + } + + /// Runs the `import-blocks` command, asserting that an error was found or + /// not depending on `expected_to_fail`. + fn run_import(&mut self, fmt_opt: FormatOpt, expected_to_fail: bool) { + let log = self.run_block_command(SubCommand::ImportBlocks, fmt_opt, expected_to_fail); + + if !expected_to_fail { + // Using regex to find out how much block we imported, + // and what's the best current block. + let re = Regex::new(r"Imported (?P\d*) blocks. Best: #(?P\d*)").unwrap(); + let caps = re.captures(&log).expect("capture should have succeeded"); + let imported = caps["imported"].parse::().unwrap(); + let best = caps["best"].parse::().unwrap(); + + assert_eq!( + imported, + best, + "numbers of blocks imported and best number differs" + ); + assert_eq!( + best, + self.num_exported_blocks.expect("number of exported blocks cannot be None; qed"), + "best block number and number of expected blocks should not differ" + ); + } + self.num_exported_blocks = None; + } + + /// Runs the `revert` command. + fn run_revert(&self) { + let output = Command::new(cargo_bin("substrate")) + .args(&["revert", "--dev", "--pruning", "archive", "-d"]) + .arg(&self.base_path.path()) + .output() + .unwrap(); + + let logged_output = String::from_utf8_lossy(&output.stderr).to_string(); + + // Reverting should not log any error. + assert!(!contains_error(&logged_output)); + // Command should never fail. + assert!(output.status.success()); + } + + /// Helper function that runs the whole export / import / revert flow and checks for errors. + fn run(&mut self, export_fmt: FormatOpt, import_fmt: FormatOpt, expected_to_fail: bool) { + self.run_export(export_fmt); + self.run_import(import_fmt, expected_to_fail); + self.run_revert(); + } +} + +#[test] +fn export_import_revert() { + let base_path = tempdir().expect("could not create a temp dir"); + let exported_blocks_file = base_path.path().join("exported_blocks"); + let db_path = base_path.path().join("db"); + + common::run_dev_node_for_a_while(base_path.path()); + + let mut executor = ExportImportRevertExecutor::new( + &base_path, + &exported_blocks_file, + &db_path, + ); + + // Binary and binary should work. + executor.run(FormatOpt::Binary, FormatOpt::Binary, false); + // Binary and JSON should fail. + executor.run(FormatOpt::Binary, FormatOpt::Json, true); + // JSON and JSON should work. + executor.run(FormatOpt::Json, FormatOpt::Json, false); + // JSON and binary should fail. + executor.run(FormatOpt::Json, FormatOpt::Binary, true); +} diff --git a/bin/node/cli/tests/import_export_and_revert_work.rs b/bin/node/cli/tests/import_export_and_revert_work.rs deleted file mode 100644 index 131265e3b4ab9bd868b9728bca6cda558d2982f2..0000000000000000000000000000000000000000 --- a/bin/node/cli/tests/import_export_and_revert_work.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020 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(unix)] - -use assert_cmd::cargo::cargo_bin; -use std::{process::Command, fs}; -use tempfile::tempdir; - -mod common; - -#[test] -fn import_export_and_revert_work() { - let base_path = tempdir().expect("could not create a temp dir"); - let exported_blocks = base_path.path().join("exported_blocks"); - - common::run_dev_node_for_a_while(base_path.path()); - - let status = Command::new(cargo_bin("substrate")) - .args(&["export-blocks", "--dev", "--pruning", "archive", "-d"]) - .arg(base_path.path()) - .arg(&exported_blocks) - .status() - .unwrap(); - assert!(status.success()); - - let metadata = fs::metadata(&exported_blocks).unwrap(); - assert!(metadata.len() > 0, "file exported_blocks should not be empty"); - - let _ = fs::remove_dir_all(base_path.path().join("db")); - - let status = Command::new(cargo_bin("substrate")) - .args(&["import-blocks", "--dev", "--pruning", "archive", "-d"]) - .arg(base_path.path()) - .arg(&exported_blocks) - .status() - .unwrap(); - assert!(status.success()); - - let status = Command::new(cargo_bin("substrate")) - .args(&["revert", "--dev", "--pruning", "archive", "-d"]) - .arg(base_path.path()) - .status() - .unwrap(); - assert!(status.success()); -} diff --git a/bin/node/cli/tests/inspect_works.rs b/bin/node/cli/tests/inspect_works.rs index 441b08ccf46da1b1ef70ec49a7a46015d94f3c4c..aa9653acadba5a1db8ccd295da9d802967604a77 100644 --- a/bin/node/cli/tests/inspect_works.rs +++ b/bin/node/cli/tests/inspect_works.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . #![cfg(unix)] @@ -20,7 +22,7 @@ use assert_cmd::cargo::cargo_bin; use std::process::Command; use tempfile::tempdir; -mod common; +pub mod common; #[test] fn inspect_works() { diff --git a/bin/node/cli/tests/purge_chain_works.rs b/bin/node/cli/tests/purge_chain_works.rs index 020259d0c595a57a01b8a9b113522d826e1de912..001bed8b136f5d2349f83fe86c557466f0b7a7ca 100644 --- a/bin/node/cli/tests/purge_chain_works.rs +++ b/bin/node/cli/tests/purge_chain_works.rs @@ -1,24 +1,26 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use assert_cmd::cargo::cargo_bin; use std::process::Command; use tempfile::tempdir; -mod common; +pub mod common; #[test] #[cfg(unix)] diff --git a/bin/node/cli/tests/running_the_node_and_interrupt.rs b/bin/node/cli/tests/running_the_node_and_interrupt.rs index 67efedccbe771a65e892b5dbe94bac702d3c01ce..bd79dcd77a49a9e6a81b28ae360ef90b3174b565 100644 --- a/bin/node/cli/tests/running_the_node_and_interrupt.rs +++ b/bin/node/cli/tests/running_the_node_and_interrupt.rs @@ -1,24 +1,26 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use assert_cmd::cargo::cargo_bin; use std::{convert::TryInto, process::Command, thread, time::Duration}; use tempfile::tempdir; -mod common; +pub mod common; #[test] #[cfg(unix)] diff --git a/bin/node/cli/tests/version.rs b/bin/node/cli/tests/version.rs index 6f99d7c24ae1434ff84e81ba84ee406ec6248ac4..c5240257f16dea779fa78f75fafd77df75cce08e 100644 --- a/bin/node/cli/tests/version.rs +++ b/bin/node/cli/tests/version.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use assert_cmd::cargo::cargo_bin; use platforms::*; diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 99bd83bb4a2bf0c4e8f3181dcd739eccaa685690..83a16a023f3ea13b4d73b37360c3256478b406b7 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "node-executor" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] description = "Substrate node implementation in Rust." edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -13,34 +13,34 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0" } -node-primitives = { version = "2.0.0-dev", path = "../primitives" } -node-runtime = { version = "2.0.0-dev", path = "../runtime" } -sc-executor = { version = "0.8.0-dev", path = "../../../client/executor" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-io = { version = "2.0.0-dev", path = "../../../primitives/io" } -sp-state-machine = { version = "0.8.0-dev", path = "../../../primitives/state-machine" } -sp-trie = { version = "2.0.0-dev", path = "../../../primitives/trie" } +node-primitives = { version = "2.0.0-rc2", path = "../primitives" } +node-runtime = { version = "2.0.0-rc2", path = "../runtime" } +sc-executor = { version = "0.8.0-rc2", path = "../../../client/executor" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-io = { version = "2.0.0-rc2", path = "../../../primitives/io" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../../primitives/state-machine" } +sp-trie = { version = "2.0.0-rc2", path = "../../../primitives/trie" } trie-root = "0.16.0" -frame-benchmarking = { version = "2.0.0-dev", path = "../../../frame/benchmarking" } +frame-benchmarking = { version = "2.0.0-rc2", path = "../../../frame/benchmarking" } [dev-dependencies] criterion = "0.3.0" -frame-support = { version = "2.0.0-dev", path = "../../../frame/support" } -frame-system = { version = "2.0.0-dev", path = "../../../frame/system" } -node-testing = { version = "2.0.0-dev", path = "../testing" } -pallet-balances = { version = "2.0.0-dev", path = "../../../frame/balances" } -pallet-contracts = { version = "2.0.0-dev", path = "../../../frame/contracts" } -pallet-grandpa = { version = "2.0.0-dev", path = "../../../frame/grandpa" } -pallet-im-online = { version = "2.0.0-dev", path = "../../../frame/im-online" } -pallet-indices = { version = "2.0.0-dev", path = "../../../frame/indices" } -pallet-session = { version = "2.0.0-dev", path = "../../../frame/session" } -pallet-timestamp = { version = "2.0.0-dev", path = "../../../frame/timestamp" } -pallet-transaction-payment = { version = "2.0.0-dev", path = "../../../frame/transaction-payment" } -pallet-treasury = { version = "2.0.0-dev", path = "../../../frame/treasury" } -sp-application-crypto = { version = "2.0.0-dev", path = "../../../primitives/application-crypto" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-externalities = { version = "0.8.0-dev", path = "../../../primitives/externalities" } -substrate-test-client = { version = "2.0.0-dev", path = "../../../test-utils/client" } +frame-support = { version = "2.0.0-rc2", path = "../../../frame/support" } +frame-system = { version = "2.0.0-rc2", path = "../../../frame/system" } +node-testing = { version = "2.0.0-rc2", path = "../testing" } +pallet-balances = { version = "2.0.0-rc2", path = "../../../frame/balances" } +pallet-contracts = { version = "2.0.0-rc2", path = "../../../frame/contracts" } +pallet-grandpa = { version = "2.0.0-rc2", path = "../../../frame/grandpa" } +pallet-im-online = { version = "2.0.0-rc2", path = "../../../frame/im-online" } +pallet-indices = { version = "2.0.0-rc2", path = "../../../frame/indices" } +pallet-session = { version = "2.0.0-rc2", path = "../../../frame/session" } +pallet-timestamp = { version = "2.0.0-rc2", path = "../../../frame/timestamp" } +pallet-transaction-payment = { version = "2.0.0-rc2", path = "../../../frame/transaction-payment" } +pallet-treasury = { version = "2.0.0-rc2", path = "../../../frame/treasury" } +sp-application-crypto = { version = "2.0.0-rc2", path = "../../../primitives/application-crypto" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-externalities = { version = "0.8.0-rc2", path = "../../../primitives/externalities" } +substrate-test-client = { version = "2.0.0-rc2", path = "../../../test-utils/client" } wabt = "0.9.2" [features] diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs index 4f335df90d1ba3b1eba376601c899ec77b0909b6..ad735c87661ca2aeb33a1ec889e983537ef30f63 100644 --- a/bin/node/executor/benches/bench.rs +++ b/bin/node/executor/benches/bench.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{Decode, Encode}; use criterion::{BatchSize, Criterion, criterion_group, criterion_main}; @@ -39,7 +40,9 @@ const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; const GENESIS_HASH: [u8; 32] = [69u8; 32]; -const VERSION: u32 = node_runtime::VERSION.spec_version; +const TRANSACTION_VERSION: u32 = node_runtime::VERSION.transaction_version; + +const SPEC_VERSION: u32 = node_runtime::VERSION.spec_version; const HEAP_PAGES: u64 = 20; @@ -52,7 +55,7 @@ enum ExecutionMethod { } fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { - node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) + node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH) } fn new_test_ext(genesis_config: &GenesisConfig) -> TestExternalities { diff --git a/bin/node/executor/src/lib.rs b/bin/node/executor/src/lib.rs index bcc7f48507398cd0ea15319460f8d13e6058f2ec..4c3b82bc7d3b538234d470a5560ca61db28976b7 100644 --- a/bin/node/executor/src/lib.rs +++ b/bin/node/executor/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A `CodeExecutor` specialization which uses natively compiled runtime when the wasm to be //! executed is equivalent to the natively compiled code. diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index caf3b7c0c7de54a228e197017e96d14e9cebbc13..7799f0913a8294c98b7b740a275aa65a712e27c4 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -1,31 +1,33 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{Encode, Decode, Joiner}; use frame_support::{ StorageValue, StorageMap, traits::Currency, - weights::{GetDispatchInfo, DispatchInfo, DispatchClass, constants::ExtrinsicBaseWeight}, -}; -use sp_core::{ - NeverNativeValue, map, traits::Externalities, storage::{well_known_keys, Storage}, + weights::{ + GetDispatchInfo, DispatchInfo, DispatchClass, constants::ExtrinsicBaseWeight, + WeightToFeePolynomial, + }, }; +use sp_core::{NeverNativeValue, traits::Externalities, storage::well_known_keys}; use sp_runtime::{ - ApplyExtrinsicResult, Fixed128, - traits::{Hash as HashT, Convert, BlakeTwo256}, + ApplyExtrinsicResult, Fixed128, FixedPointNumber, + traits::Hash as HashT, transaction_validity::InvalidTransaction, }; use pallet_contracts::ContractAddressFor; @@ -55,11 +57,11 @@ fn transfer_fee(extrinsic: &E, fee_multiplier: Fixed128) -> Balance { let length_fee = TransactionByteFee::get() * (extrinsic.encode().len() as Balance); let base_weight = ExtrinsicBaseWeight::get(); - let base_fee = ::WeightToFee::convert(base_weight); + let base_fee = ::WeightToFee::calc(&base_weight); let weight = default_transfer_call().get_dispatch_info().weight; - let weight_fee = ::WeightToFee::convert(weight); + let weight_fee = ::WeightToFee::calc(&weight); - base_fee + fee_multiplier.saturated_multiply_accumulate(length_fee + weight_fee) + base_fee + fee_multiplier.saturating_mul_acc_int(length_fee + weight_fee) } fn xt() -> UncheckedExtrinsic { @@ -158,20 +160,13 @@ fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec, Hash) { #[test] fn panic_execution_with_foreign_code_gives_error() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (69u128, 0u8, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - 69_u128.encode() - }, - >::hashed_key_for(0) => { - vec![0u8; 32] - } - ], - children_default: map![], - }); + let mut t = new_test_ext(BLOATY_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (69u128, 0u8, 0u128, 0u128, 0u128).encode() + ); + t.insert(>::hashed_key().to_vec(), 69_u128.encode()); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -194,20 +189,13 @@ fn panic_execution_with_foreign_code_gives_error() { #[test] fn bad_extrinsic_with_native_equivalent_code_gives_error() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 69u128, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - 69_u128.encode() - }, - >::hashed_key_for(0) => { - vec![0u8; 32] - } - ], - children_default: map![], - }); + let mut t = new_test_ext(COMPACT_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 69u128, 0u128, 0u128, 0u128).encode() + ); + t.insert(>::hashed_key().to_vec(), 69_u128.encode()); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -230,18 +218,20 @@ fn bad_extrinsic_with_native_equivalent_code_gives_error() { #[test] fn successful_execution_with_native_equivalent_code_gives_ok() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children_default: map![], - }); + let mut t = new_test_ext(COMPACT_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key_for(bob()), + (0u32, 0u8, 0 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key().to_vec(), + (111 * DOLLARS).encode() + ); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -272,18 +262,20 @@ fn successful_execution_with_native_equivalent_code_gives_ok() { #[test] fn successful_execution_with_foreign_code_gives_ok() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children_default: map![], - }); + let mut t = new_test_ext(BLOATY_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key_for(bob()), + (0u32, 0u8, 0 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key().to_vec(), + (111 * DOLLARS).encode() + ); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -337,9 +329,9 @@ fn full_native_block_import_works() { let events = vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - // timestamp set call with weight 9_000_000 + 2 read + 1 write + // timestamp set call with weight 8_000_000 + 2 read + 1 write event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess( - DispatchInfo { weight: 9_000_000 + 2 * 25_000_000 + 1 * 100_000_000, class: DispatchClass::Mandatory, ..Default::default() } + DispatchInfo { weight: 8_000_000 + 2 * 25_000_000 + 1 * 100_000_000, class: DispatchClass::Mandatory, ..Default::default() } )), topics: vec![], }, @@ -392,9 +384,9 @@ fn full_native_block_import_works() { let events = vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - // timestamp set call with weight 9_000_000 + 2 read + 1 write + // timestamp set call with weight 8_000_000 + 2 read + 1 write event: Event::frame_system(frame_system::RawEvent::ExtrinsicSuccess( - DispatchInfo { weight: 9_000_000 + 2 * 25_000_000 + 1 * 100_000_000, class: DispatchClass::Mandatory, ..Default::default() } + DispatchInfo { weight: 8_000_000 + 2 * 25_000_000 + 1 * 100_000_000, class: DispatchClass::Mandatory, ..Default::default() } )), topics: vec![], }, @@ -707,15 +699,13 @@ fn native_big_block_import_fails_on_fallback() { #[test] fn panic_execution_gives_error() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { - top: map![ - >::hashed_key().to_vec() => { - 0_u128.encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children_default: map![], - }); + let mut t = new_test_ext(BLOATY_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 0 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert(>::hashed_key().to_vec(), 0_u128.encode()); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -738,18 +728,20 @@ fn panic_execution_gives_error() { #[test] fn successful_execution_gives_ok() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children_default: map![], - }); + let mut t = new_test_ext(COMPACT_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 111 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key_for(bob()), + (0u32, 0u8, 0 * DOLLARS, 0u128, 0u128, 0u128).encode() + ); + t.insert( + >::hashed_key().to_vec(), + (111 * DOLLARS).encode() + ); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let r = executor_call:: _>( &mut t, @@ -759,7 +751,12 @@ fn successful_execution_gives_ok() { None, ).0; assert!(r.is_ok()); + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 111 * DOLLARS); + }); + let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + let r = executor_call:: _>( &mut t, "BlockBuilder_apply_extrinsic", diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index 5a51e4312c5e80315c3b05fc5a82bc72a6842fb2..9f4d9f71e72dd657fc328da40f48a267b9cde303 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{Encode, Decode}; use frame_system::offchain::AppCrypto; @@ -71,12 +72,14 @@ pub const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; pub const GENESIS_HASH: [u8; 32] = [69u8; 32]; -pub const VERSION: u32 = node_runtime::VERSION.spec_version; +pub const SPEC_VERSION: u32 = node_runtime::VERSION.spec_version; + +pub const TRANSACTION_VERSION: u32 = node_runtime::VERSION.transaction_version; pub type TestExternalities = CoreTestExternalities; pub fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { - node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) + node_testing::keyring::sign(xt, SPEC_VERSION, TRANSACTION_VERSION, GENESIS_HASH) } pub fn default_transfer_call() -> pallet_balances::Call { diff --git a/bin/node/executor/tests/fees.rs b/bin/node/executor/tests/fees.rs index c7d6bb34cd5d93dfea6727735879af834433ccab..a4fc3930da28c367215cc72385f53efaf7ac346f 100644 --- a/bin/node/executor/tests/fees.rs +++ b/bin/node/executor/tests/fees.rs @@ -1,33 +1,33 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{Encode, Joiner}; use frame_support::{ StorageValue, StorageMap, traits::Currency, - weights::{GetDispatchInfo, constants::ExtrinsicBaseWeight}, + weights::{GetDispatchInfo, constants::ExtrinsicBaseWeight, IdentityFee, WeightToFeePolynomial}, }; -use sp_core::{NeverNativeValue, map, storage::Storage}; -use sp_runtime::{Fixed128, Perbill, traits::{Convert, BlakeTwo256}}; +use sp_core::NeverNativeValue; +use sp_runtime::{FixedPointNumber, Fixed128, Perbill}; use node_runtime::{ CheckedExtrinsic, Call, Runtime, Balances, TransactionPayment, - TransactionByteFee, WeightFeeCoefficient, + TransactionByteFee, constants::currency::*, }; -use node_runtime::impls::LinearWeightToFee; use node_primitives::Balance; use node_testing::keyring::*; @@ -39,7 +39,7 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() { let mut t = new_test_ext(COMPACT_CODE, false); // initial fee multiplier must be zero - let mut prev_multiplier = Fixed128::from_parts(0); + let mut prev_multiplier = Fixed128::from_inner(0); t.execute_with(|| { assert_eq!(TransactionPayment::next_fee_multiplier(), prev_multiplier); @@ -130,21 +130,20 @@ fn transaction_fee_is_correct_ultimate() { // - 1 MILLICENTS in substrate node. // - 1 milli-dot based on current polkadot runtime. // (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`) - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { - top: map![ - >::hashed_key_for(alice()) => { - (0u32, 0u8, 100 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode() - }, - >::hashed_key_for(bob()) => { - (0u32, 0u8, 10 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => { - (110 * DOLLARS).encode() - }, - >::hashed_key_for(0) => vec![0u8; 32] - ], - children_default: map![], - }); + let mut t = new_test_ext(COMPACT_CODE, false); + t.insert( + >::hashed_key_for(alice()), + (0u32, 0u8, 100 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode() + ); + t.insert( + >::hashed_key_for(bob()), + (0u32, 0u8, 10 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode() + ); + t.insert( + >::hashed_key().to_vec(), + (110 * DOLLARS).encode() + ); + t.insert(>::hashed_key_for(0), vec![0u8; 32]); let tip = 1_000_000; let xt = sign(CheckedExtrinsic { @@ -181,13 +180,13 @@ fn transaction_fee_is_correct_ultimate() { let mut balance_alice = (100 - 69) * DOLLARS; let base_weight = ExtrinsicBaseWeight::get(); - let base_fee = LinearWeightToFee::::convert(base_weight); + let base_fee = IdentityFee::::calc(&base_weight); let length_fee = TransactionByteFee::get() * (xt.clone().encode().len() as Balance); balance_alice -= length_fee; let weight = default_transfer_call().get_dispatch_info().weight; - let weight_fee = LinearWeightToFee::::convert(weight); + let weight_fee = IdentityFee::::calc(&weight); // we know that weight to fee multiplier is effect-less in block 1. // current weight of transfer = 200_000_000 diff --git a/bin/node/executor/tests/submit_transaction.rs b/bin/node/executor/tests/submit_transaction.rs index 4c4e4b085505e02a497bbb677fe3862c8de89091..b3fc25e6cd8fccaadf7dafbf9b03835d4f7224a1 100644 --- a/bin/node/executor/tests/submit_transaction.rs +++ b/bin/node/executor/tests/submit_transaction.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use node_runtime::{ Executive, Indices, Runtime, UncheckedExtrinsic, @@ -122,7 +123,7 @@ fn should_submit_signed_twice_from_the_same_account() { let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { let extra = tx.signature.unwrap().2; - extra.3 + extra.4 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -170,7 +171,7 @@ fn should_submit_signed_twice_from_all_accounts() { let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { let extra = tx.signature.unwrap().2; - extra.3 + extra.4 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -233,7 +234,7 @@ fn submitted_transaction_should_be_valid() { priority: 1_410_710_000_000, requires: vec![], provides: vec![(address, 0).encode()], - longevity: 128, + longevity: 2048, propagate: true, }); }); diff --git a/bin/node/inspect/Cargo.toml b/bin/node/inspect/Cargo.toml index 03d3a94b6277822397af4945b53ed41ddd27f2ce..6006e8c15c7ac95f1b77664974983a6a457f7b36 100644 --- a/bin/node/inspect/Cargo.toml +++ b/bin/node/inspect/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "node-inspect" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -14,10 +14,10 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "1.3.0" } derive_more = "0.99" log = "0.4.8" -sc-cli = { version = "0.8.0-dev", path = "../../../client/cli" } -sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" } -sc-service = { version = "0.8.0-dev", default-features = false, path = "../../../client/service" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } +sc-cli = { version = "0.8.0-rc2", path = "../../../client/cli" } +sc-client-api = { version = "2.0.0-rc2", path = "../../../client/api" } +sc-service = { version = "0.8.0-rc2", default-features = false, path = "../../../client/service" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } structopt = "0.3.8" diff --git a/bin/node/inspect/src/cli.rs b/bin/node/inspect/src/cli.rs index 5d51bd5848f17d308933fdcb69d429504fa8445e..4475d31755fdce08ed7f097eff34572a1533291a 100644 --- a/bin/node/inspect/src/cli.rs +++ b/bin/node/inspect/src/cli.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Structs to easily compose inspect sub-command for CLI. diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index 2212907f763138feef1607b2236bdbbf7e0867a3..fae6c10c7fe7846dc63e990dcf03254655467705 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Command ran by the CLI diff --git a/bin/node/inspect/src/lib.rs b/bin/node/inspect/src/lib.rs index b8101d98a31ce717b4a57f9ee939abe2444253a9..02f5614b81a78044d1418d9d23f87322da2c298c 100644 --- a/bin/node/inspect/src/lib.rs +++ b/bin/node/inspect/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify +// +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// +// This program 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, +// +// This program 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 +// 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 . +// along with this program. If not, see . //! A CLI extension for substrate node, adding sub-command to pretty print debug info //! about blocks and extrinsics. diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml index e69b626b5420fdccefbb7eec36014d05e6599857..55ee2c3829caae9276b23ebcf5784b986baeb016 100644 --- a/bin/node/primitives/Cargo.toml +++ b/bin/node/primitives/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "node-primitives" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,13 +12,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../../../frame/system" } -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/application-crypto" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/system" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/application-crypto" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/runtime" } [dev-dependencies] -sp-serializer = { version = "2.0.0-dev", path = "../../../primitives/serializer" } +sp-serializer = { version = "2.0.0-rc2", path = "../../../primitives/serializer" } pretty_assertions = "0.6.1" [features] diff --git a/bin/node/primitives/src/lib.rs b/bin/node/primitives/src/lib.rs index c6180b31f7e05f1113a51fca5ebc48a7c74091bf..137fb1d94c778aafa6b2f45713d4954070caa1d5 100644 --- a/bin/node/primitives/src/lib.rs +++ b/bin/node/primitives/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Low-level types used throughout the Substrate code. @@ -69,11 +70,11 @@ pub type BlockId = generic::BlockId; pub mod report { use super::{Signature, Verify}; use frame_system::offchain::AppCrypto; - use sp_core::crypto::KeyTypeId; + use sp_core::crypto::{key_types, KeyTypeId}; /// Key type for the reporting module. Used for reporting BABE and GRANDPA /// equivocations. - pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"fish"); + pub const KEY_TYPE: KeyTypeId = key_types::REPORTING; mod app { use sp_application_crypto::{app_crypto, sr25519}; diff --git a/bin/node/rpc-client/Cargo.toml b/bin/node/rpc-client/Cargo.toml index 1df3590d1fe833f2e2c93c98cf4dfc2aa5501c2f..0b529d116c6d4091d10e0c1a142ac79071d00492 100644 --- a/bin/node/rpc-client/Cargo.toml +++ b/bin/node/rpc-client/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "node-rpc-client" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -16,5 +16,5 @@ futures = "0.1.29" hyper = "0.12.35" jsonrpc-core-client = { version = "14.0.5", default-features = false, features = ["http"] } log = "0.4.8" -node-primitives = { version = "2.0.0-dev", path = "../primitives" } -sc-rpc = { version = "2.0.0-dev", path = "../../../client/rpc" } +node-primitives = { version = "2.0.0-rc2", path = "../primitives" } +sc-rpc = { version = "2.0.0-rc2", path = "../../../client/rpc" } diff --git a/bin/node/rpc-client/src/main.rs b/bin/node/rpc-client/src/main.rs index c547d30002d795b07ffc9468027bf1c06f17b877..eadd1c8d472476b6db57570d08a0233d36bea45d 100644 --- a/bin/node/rpc-client/src/main.rs +++ b/bin/node/rpc-client/src/main.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![warn(missing_docs)] diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml index f0c5fc250b0cb9fdd539e662ed64758c037a5df4..00b8be99b1ef186ec584e4bc93285e1b5271b877 100644 --- a/bin/node/rpc/Cargo.toml +++ b/bin/node/rpc/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "node-rpc" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -11,22 +11,23 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sc-client-api = { version = "2.0.0-dev", path = "../../../client/api" } +sc-client-api = { version = "2.0.0-rc2", path = "../../../client/api" } jsonrpc-core = "14.0.3" -node-primitives = { version = "2.0.0-dev", path = "../primitives" } -node-runtime = { version = "2.0.0-dev", path = "../runtime" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -pallet-contracts-rpc = { version = "0.8.0-dev", path = "../../../frame/contracts/rpc/" } -pallet-transaction-payment-rpc = { version = "2.0.0-dev", path = "../../../frame/transaction-payment/rpc/" } -substrate-frame-rpc-system = { version = "2.0.0-dev", path = "../../../utils/frame/rpc/system" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../../primitives/transaction-pool" } -sc-consensus-babe = { version = "0.8.0-dev", path = "../../../client/consensus/babe" } -sc-consensus-babe-rpc = { version = "0.8.0-dev", path = "../../../client/consensus/babe/rpc" } -sp-consensus-babe = { version = "0.8.0-dev", path = "../../../primitives/consensus/babe" } -sc-keystore = { version = "2.0.0-dev", path = "../../../client/keystore" } -sc-consensus-epochs = { version = "0.8.0-dev", path = "../../../client/consensus/epochs" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sc-finality-grandpa = { version = "0.8.0-dev", path = "../../../client/finality-grandpa" } -sc-finality-grandpa-rpc = { version = "0.8.0-dev", path = "../../../client/finality-grandpa/rpc" } +node-primitives = { version = "2.0.0-rc2", path = "../primitives" } +node-runtime = { version = "2.0.0-rc2", path = "../runtime" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +pallet-contracts-rpc = { version = "0.8.0-rc2", path = "../../../frame/contracts/rpc/" } +pallet-transaction-payment-rpc = { version = "2.0.0-rc2", path = "../../../frame/transaction-payment/rpc/" } +substrate-frame-rpc-system = { version = "2.0.0-rc2", path = "../../../utils/frame/rpc/system" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../../primitives/transaction-pool" } +sc-consensus-babe = { version = "0.8.0-rc2", path = "../../../client/consensus/babe" } +sc-consensus-babe-rpc = { version = "0.8.0-rc2", path = "../../../client/consensus/babe/rpc" } +sp-consensus-babe = { version = "0.8.0-rc2", path = "../../../primitives/consensus/babe" } +sc-keystore = { version = "2.0.0-rc2", path = "../../../client/keystore" } +sc-consensus-epochs = { version = "0.8.0-rc2", path = "../../../client/consensus/epochs" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sc-finality-grandpa = { version = "0.8.0-rc2", path = "../../../client/finality-grandpa" } +sc-finality-grandpa-rpc = { version = "0.8.0-rc2", path = "../../../client/finality-grandpa/rpc" } +sc-rpc-api = { version = "0.8.0-rc2", path = "../../../client/rpc-api" } diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 114179c0047e2c580f4657cadd12e6d011a62eb0..259a792441d40e148550a120d1123fa1654d1018 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A collection of node-specific RPC methods. //! @@ -41,9 +42,10 @@ use sc_keystore::KeyStorePtr; use sp_consensus_babe::BabeApi; use sc_consensus_epochs::SharedEpochChanges; use sc_consensus_babe::{Config, Epoch}; -use sc_consensus_babe_rpc::BabeRPCHandler; +use sc_consensus_babe_rpc::BabeRpcHandler; use sc_finality_grandpa::{SharedVoterState, SharedAuthoritySet}; use sc_finality_grandpa_rpc::GrandpaRpcHandler; +use sc_rpc_api::DenyUnsafe; /// Light client extra dependencies. pub struct LightDeps { @@ -83,6 +85,8 @@ pub struct FullDeps { pub pool: Arc

, /// The SelectChain Strategy pub select_chain: SC, + /// Whether to deny unsafe calls + pub deny_unsafe: DenyUnsafe, /// BABE specific dependencies. pub babe: BabeDeps, /// GRANDPA specific dependencies. @@ -114,6 +118,7 @@ pub fn create_full( client, pool, select_chain, + deny_unsafe, babe, grandpa, } = deps; @@ -141,7 +146,14 @@ pub fn create_full( ); io.extend_with( sc_consensus_babe_rpc::BabeApi::to_delegate( - BabeRPCHandler::new(client, shared_epoch_changes, keystore, babe_config, select_chain) + BabeRpcHandler::new( + client, + shared_epoch_changes, + keystore, + babe_config, + select_chain, + deny_unsafe, + ), ) ); io.extend_with( diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 00d1c6dd722b20ac012ffddd45cfc4c57cbac5c2..1bf61c046de8ce6fb34a799411c82965111e77a9 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "node-runtime" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -17,70 +17,71 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } integer-sqrt = { version = "0.1.2" } serde = { version = "1.0.102", optional = true } +static_assertions = "1.1.0" # primitives -sp-authority-discovery = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/authority-discovery" } -sp-consensus-babe = { version = "0.8.0-dev", default-features = false, path = "../../../primitives/consensus/babe" } -sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "2.0.0-dev"} -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/inherents" } -node-primitives = { version = "2.0.0-dev", default-features = false, path = "../primitives" } -sp-offchain = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/offchain" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/std" } -sp-api = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/api" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/staking" } -sp-keyring = { version = "2.0.0-dev", optional = true, path = "../../../primitives/keyring" } -sp-session = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/session" } -sp-transaction-pool = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" } -sp-version = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/version" } +sp-authority-discovery = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/authority-discovery" } +sp-consensus-babe = { version = "0.8.0-rc2", default-features = false, path = "../../../primitives/consensus/babe" } +sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "2.0.0-rc2"} +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/inherents" } +node-primitives = { version = "2.0.0-rc2", default-features = false, path = "../primitives" } +sp-offchain = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/offchain" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/std" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/api" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/staking" } +sp-keyring = { version = "2.0.0-rc2", optional = true, path = "../../../primitives/keyring" } +sp-session = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/session" } +sp-transaction-pool = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/transaction-pool" } +sp-version = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/version" } # frame dependencies -frame-executive = { version = "2.0.0-dev", default-features = false, path = "../../../frame/executive" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../../../frame/benchmarking", optional = true } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../../../frame/support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../../../frame/system" } -frame-system-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../../../frame/system/benchmarking", optional = true } -frame-system-rpc-runtime-api = { version = "2.0.0-dev", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } -pallet-authority-discovery = { version = "2.0.0-dev", default-features = false, path = "../../../frame/authority-discovery" } -pallet-authorship = { version = "2.0.0-dev", default-features = false, path = "../../../frame/authorship" } -pallet-babe = { version = "2.0.0-dev", default-features = false, path = "../../../frame/babe" } -pallet-balances = { version = "2.0.0-dev", default-features = false, path = "../../../frame/balances" } -pallet-collective = { version = "2.0.0-dev", default-features = false, path = "../../../frame/collective" } -pallet-contracts = { version = "2.0.0-dev", default-features = false, path = "../../../frame/contracts" } -pallet-contracts-primitives = { version = "2.0.0-dev", default-features = false, path = "../../../frame/contracts/common/" } -pallet-contracts-rpc-runtime-api = { version = "0.8.0-dev", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } -pallet-democracy = { version = "2.0.0-dev", default-features = false, path = "../../../frame/democracy" } -pallet-elections-phragmen = { version = "2.0.0-dev", default-features = false, path = "../../../frame/elections-phragmen" } -pallet-finality-tracker = { version = "2.0.0-dev", default-features = false, path = "../../../frame/finality-tracker" } -pallet-grandpa = { version = "2.0.0-dev", default-features = false, path = "../../../frame/grandpa" } -pallet-im-online = { version = "2.0.0-dev", default-features = false, path = "../../../frame/im-online" } -pallet-indices = { version = "2.0.0-dev", default-features = false, path = "../../../frame/indices" } -pallet-identity = { version = "2.0.0-dev", default-features = false, path = "../../../frame/identity" } -pallet-membership = { version = "2.0.0-dev", default-features = false, path = "../../../frame/membership" } -pallet-offences = { version = "2.0.0-dev", default-features = false, path = "../../../frame/offences" } -pallet-offences-benchmarking = { version = "2.0.0-dev", path = "../../../frame/offences/benchmarking", default-features = false, optional = true } -pallet-randomness-collective-flip = { version = "2.0.0-dev", default-features = false, path = "../../../frame/randomness-collective-flip" } -pallet-recovery = { version = "2.0.0-dev", default-features = false, path = "../../../frame/recovery" } -pallet-session = { version = "2.0.0-dev", features = ["historical"], path = "../../../frame/session", default-features = false } -pallet-session-benchmarking = { version = "2.0.0-dev", path = "../../../frame/session/benchmarking", default-features = false, optional = true } -pallet-staking = { version = "2.0.0-dev", default-features = false, path = "../../../frame/staking" } -pallet-staking-reward-curve = { version = "2.0.0-dev", default-features = false, path = "../../../frame/staking/reward-curve" } -pallet-scheduler = { version = "2.0.0-dev", default-features = false, path = "../../../frame/scheduler" } -pallet-society = { version = "2.0.0-dev", default-features = false, path = "../../../frame/society" } -pallet-sudo = { version = "2.0.0-dev", default-features = false, path = "../../../frame/sudo" } -pallet-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../../frame/timestamp" } -pallet-treasury = { version = "2.0.0-dev", default-features = false, path = "../../../frame/treasury" } -pallet-utility = { version = "2.0.0-dev", default-features = false, path = "../../../frame/utility" } -pallet-transaction-payment = { version = "2.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } -pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } -pallet-vesting = { version = "2.0.0-dev", default-features = false, path = "../../../frame/vesting" } +frame-executive = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/executive" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/benchmarking", optional = true } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/system" } +frame-system-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/system/benchmarking", optional = true } +frame-system-rpc-runtime-api = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } +pallet-authority-discovery = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/authority-discovery" } +pallet-authorship = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/authorship" } +pallet-babe = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/babe" } +pallet-balances = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/balances" } +pallet-collective = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/collective" } +pallet-contracts = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/contracts" } +pallet-contracts-primitives = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/contracts/common/" } +pallet-contracts-rpc-runtime-api = { version = "0.8.0-rc2", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } +pallet-democracy = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/democracy" } +pallet-elections-phragmen = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/elections-phragmen" } +pallet-finality-tracker = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/finality-tracker" } +pallet-grandpa = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/grandpa" } +pallet-im-online = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/im-online" } +pallet-indices = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/indices" } +pallet-identity = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/identity" } +pallet-membership = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/membership" } +pallet-offences = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/offences" } +pallet-offences-benchmarking = { version = "2.0.0-rc2", path = "../../../frame/offences/benchmarking", default-features = false, optional = true } +pallet-randomness-collective-flip = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/randomness-collective-flip" } +pallet-recovery = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/recovery" } +pallet-session = { version = "2.0.0-rc2", features = ["historical"], path = "../../../frame/session", default-features = false } +pallet-session-benchmarking = { version = "2.0.0-rc2", path = "../../../frame/session/benchmarking", default-features = false, optional = true } +pallet-staking = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/staking" } +pallet-staking-reward-curve = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/staking/reward-curve" } +pallet-scheduler = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/scheduler" } +pallet-society = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/society" } +pallet-sudo = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/sudo" } +pallet-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/timestamp" } +pallet-treasury = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/treasury" } +pallet-utility = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/utility" } +pallet-transaction-payment = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/transaction-payment" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } +pallet-vesting = { version = "2.0.0-rc2", default-features = false, path = "../../../frame/vesting" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } [dev-dependencies] -sp-io = { version = "2.0.0-dev", path = "../../../primitives/io" } +sp-io = { version = "2.0.0-rc2", path = "../../../primitives/io" } [features] default = ["std"] diff --git a/bin/node/runtime/build.rs b/bin/node/runtime/build.rs index 647b4768141d2203155bf5325f9ff87f7d9c2446..a4f323566006cf7c003cec2e413e1d23ecffead1 100644 --- a/bin/node/runtime/build.rs +++ b/bin/node/runtime/build.rs @@ -1,25 +1,26 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/bin/node/runtime/src/constants.rs b/bin/node/runtime/src/constants.rs index bf12492f8db029dc22b519dd52af74adcad99a7f..45f1ab19a450ecc69cbe54de6ba09b32428dafab 100644 --- a/bin/node/runtime/src/constants.rs +++ b/bin/node/runtime/src/constants.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A set of constant values used in substrate runtime. diff --git a/bin/node/runtime/src/impls.rs b/bin/node/runtime/src/impls.rs index f613dc5af5048cfdd5ea214600099d60df83097f..0047ae5c1b6c80a9c86b39255751f47fc7c5fcc7 100644 --- a/bin/node/runtime/src/impls.rs +++ b/bin/node/runtime/src/impls.rs @@ -1,26 +1,26 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Some configurable implementations as associated type for the substrate runtime. -use core::num::NonZeroI128; use node_primitives::Balance; use sp_runtime::traits::{Convert, Saturating}; -use sp_runtime::{Fixed128, Perquintill}; -use frame_support::{traits::{OnUnbalanced, Currency, Get}, weights::Weight}; +use sp_runtime::{FixedPointNumber, Fixed128, Perquintill}; +use frame_support::traits::{OnUnbalanced, Currency, Get}; use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance}; pub struct Author; @@ -46,18 +46,6 @@ impl Convert for CurrencyToVoteHandler { fn convert(x: u128) -> Balance { x * Self::factor() } } -/// Convert from weight to balance via a simple coefficient multiplication -/// The associated type C encapsulates a constant in units of balance per weight -pub struct LinearWeightToFee(sp_std::marker::PhantomData); - -impl> Convert for LinearWeightToFee { - fn convert(w: Weight) -> Balance { - // setting this to zero will disable the weight fee. - let coefficient = C::get(); - Balance::from(w).saturating_mul(coefficient) - } -} - /// Update the given multiplier based on the following formula /// /// diff = (previous_block_weight - target_weight)/max_weight @@ -70,26 +58,22 @@ pub struct TargetedFeeAdjustment(sp_std::marker::PhantomData); impl> Convert for TargetedFeeAdjustment { fn convert(multiplier: Fixed128) -> Fixed128 { - let block_weight = System::all_extrinsics_weight(); let max_weight = MaximumBlockWeight::get(); + let block_weight = System::block_weight().total().min(max_weight); let target_weight = (T::get() * max_weight) as u128; let block_weight = block_weight as u128; // determines if the first_term is positive let positive = block_weight >= target_weight; let diff_abs = block_weight.max(target_weight) - block_weight.min(target_weight); - // safe, diff_abs cannot exceed u64 and it can always be computed safely even with the lossy - // `Fixed128::from_rational`. - let diff = Fixed128::from_rational( - diff_abs as i128, - NonZeroI128::new(max_weight.max(1) as i128).unwrap(), - ); + // safe, diff_abs cannot exceed u64. + let diff = Fixed128::saturating_from_rational(diff_abs, max_weight.max(1)); let diff_squared = diff.saturating_mul(diff); // 0.00004 = 4/100_000 = 40_000/10^9 - let v = Fixed128::from_rational(4, NonZeroI128::new(100_000).unwrap()); + let v = Fixed128::saturating_from_rational(4, 100_000); // 0.00004^2 = 16/10^10 Taking the future /2 into account... 8/10^10 - let v_squared_2 = Fixed128::from_rational(8, NonZeroI128::new(10_000_000_000).unwrap()); + let v_squared_2 = Fixed128::saturating_from_rational(8, 10_000_000_000u64); let first_term = v.saturating_mul(diff); let second_term = v_squared_2.saturating_mul(diff_squared); @@ -108,7 +92,7 @@ impl> Convert for TargetedFeeAdjustment< // multiplier. While at -1, it means that the network is so un-congested that all // transactions have no weight fee. We stop here and only increase if the network // became more busy. - .max(Fixed128::from_natural(-1)) + .max(Fixed128::saturating_from_integer(-1)) } } } @@ -119,8 +103,7 @@ mod tests { use sp_runtime::assert_eq_error_rate; use crate::{MaximumBlockWeight, AvailableBlockRatio, Runtime}; use crate::{constants::currency::*, TransactionPayment, TargetBlockFullness}; - use frame_support::weights::Weight; - use core::num::NonZeroI128; + use frame_support::weights::{Weight, WeightToFeePolynomial}; fn max() -> Weight { MaximumBlockWeight::get() @@ -132,18 +115,19 @@ mod tests { // poc reference implementation. fn fee_multiplier_update(block_weight: Weight, previous: Fixed128) -> Fixed128 { - let block_weight = block_weight as f64; - let v: f64 = 0.00004; - // maximum tx weight let m = max() as f64; + // block weight always truncated to max weight + let block_weight = (block_weight as f64).min(m); + let v: f64 = 0.00004; + // Ideal saturation in terms of weight let ss = target() as f64; // Current saturation in terms of weight let s = block_weight; let fm = v * (s/m - ss/m) + v.powi(2) * (s/m - ss/m).powi(2) / 2.0; - let addition_fm = Fixed128::from_parts((fm * Fixed128::accuracy() as f64).round() as i128); + let addition_fm = Fixed128::from_inner((fm * Fixed128::accuracy() as f64).round() as i128); previous.saturating_add(addition_fm) } @@ -158,7 +142,7 @@ mod tests { #[test] fn fee_multiplier_update_poc_works() { - let fm = Fixed128::from_rational(0, NonZeroI128::new(1).unwrap()); + let fm = Fixed128::saturating_from_rational(0, 1); let test_set = vec![ (0, fm.clone()), (100, fm.clone()), @@ -172,7 +156,7 @@ mod tests { fee_multiplier_update(w, fm), TargetedFeeAdjustment::::convert(fm), // Error is only 1 in 10^18 - Fixed128::from_parts(1), + Fixed128::from_inner(1), ); }) }) @@ -188,7 +172,7 @@ mod tests { loop { let next = TargetedFeeAdjustment::::convert(fm); fm = next; - if fm == Fixed128::from_natural(-1) { break; } + if fm == Fixed128::saturating_from_integer(-1) { break; } iterations += 1; } println!("iteration {}, new fm = {:?}. Weight fee is now zero", iterations, fm); @@ -226,8 +210,9 @@ mod tests { if fm == next { panic!("The fee should ever increase"); } fm = next; iterations += 1; - let fee = ::WeightToFee::convert(tx_weight); - let adjusted_fee = fm.saturated_multiply_accumulate(fee); + let fee = + ::WeightToFee::calc(&tx_weight); + let adjusted_fee = fm.saturating_mul_acc_int(fee); println!( "iteration {}, new fm = {:?}. Fee at this point is: {} units / {} millicents, \ {} cents, {} dollars", @@ -330,8 +315,8 @@ mod tests { // ... stops going down at -1 assert_eq!( - TargetedFeeAdjustment::::convert(Fixed128::from_natural(-1)), - Fixed128::from_natural(-1) + TargetedFeeAdjustment::::convert(Fixed128::saturating_from_integer(-1)), + Fixed128::saturating_from_integer(-1) ); }) } @@ -340,7 +325,7 @@ mod tests { fn weight_to_fee_should_not_overflow_on_large_weights() { let kb = 1024 as Weight; let mb = kb * kb; - let max_fm = Fixed128::from_natural(i128::max_value()); + let max_fm = Fixed128::saturating_from_integer(i128::max_value()); // check that for all values it can compute, correctly. vec![ @@ -363,7 +348,7 @@ mod tests { run_with_system_weight(i, || { let next = TargetedFeeAdjustment::::convert(Fixed128::default()); let truth = fee_multiplier_update(i, Fixed128::default()); - assert_eq_error_rate!(truth, next, Fixed128::from_parts(50_000_000)); + assert_eq_error_rate!(truth, next, Fixed128::from_inner(50_000_000)); }); }); diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index a67f4855ac56bd971a43b236d1dd4ba659d7bf45..229aa3a9bed4f3d49028566cbdf74150e741322b 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! The Substrate runtime. This can be compiled with ``#[no_std]`, ready for Wasm. @@ -24,7 +26,7 @@ use sp_std::prelude::*; use frame_support::{ construct_runtime, parameter_types, debug, weights::{ - Weight, + Weight, IdentityFee, constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, }, traits::{Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness, LockIdentifier}, @@ -38,14 +40,14 @@ pub use node_primitives::{AccountId, Signature}; use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment}; use sp_api::impl_runtime_apis; use sp_runtime::{ - Permill, Perbill, Perquintill, Percent, ApplyExtrinsicResult, + Permill, Perbill, Perquintill, Percent, PerThing, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str, ModuleId, }; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority}; use sp_runtime::traits::{ self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion, - ConvertInto, OpaqueKeys, NumberFor, + ConvertInto, OpaqueKeys, NumberFor, Saturating, }; use sp_version::RuntimeVersion; #[cfg(any(feature = "std", test))] @@ -58,20 +60,21 @@ use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; use pallet_contracts_rpc_runtime_api::ContractExecResult; use pallet_session::{historical as pallet_session_historical}; use sp_inherents::{InherentData, CheckInherentsResult}; +use codec::Encode; +use static_assertions::const_assert; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; -pub use pallet_timestamp::Call as TimestampCall; +#[cfg(any(feature = "std", test))] pub use pallet_balances::Call as BalancesCall; +#[cfg(any(feature = "std", test))] pub use frame_system::Call as SystemCall; -pub use pallet_contracts::Gas; -pub use frame_support::StorageValue; +#[cfg(any(feature = "std", test))] pub use pallet_staking::StakerStatus; -use codec::Encode; /// Implementations of some helper traits passed into runtime modules as associated types. pub mod impls; -use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustment}; +use impls::{CurrencyToVoteHandler, Author, TargetedFeeAdjustment}; /// Constant values used within the runtime. pub mod constants; @@ -90,8 +93,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 247, - impl_version: 0, + spec_version: 251, + impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, }; @@ -123,15 +126,22 @@ impl OnUnbalanced for DealWithFees { } } +const AVERAGE_ON_INITIALIZE_WEIGHT: Perbill = Perbill::from_percent(10); parameter_types! { - pub const BlockHashCount: BlockNumber = 250; + pub const BlockHashCount: BlockNumber = 2400; /// We allow for 2 seconds of compute with a 6 second average block time. pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + /// Assume 10% of weight for average on_initialize calls. + pub MaximumExtrinsicWeight: Weight = + AvailableBlockRatio::get().saturating_sub(AVERAGE_ON_INITIALIZE_WEIGHT) + * MaximumBlockWeight::get(); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } +const_assert!(AvailableBlockRatio::get().deconstruct() >= AVERAGE_ON_INITIALIZE_WEIGHT.deconstruct()); + impl frame_system::Trait for Runtime { type Origin = Origin; type Call = Call; @@ -148,6 +158,7 @@ impl frame_system::Trait for Runtime { type DbWeight = RocksDbWeight; type BlockExecutionWeight = BlockExecutionWeight; type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = Version; @@ -172,10 +183,11 @@ impl pallet_utility::Trait for Runtime { type MultisigDepositBase = MultisigDepositBase; type MultisigDepositFactor = MultisigDepositFactor; type MaxSignatories = MaxSignatories; + type IsCallable = (); } parameter_types! { - pub const MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); } impl pallet_scheduler::Trait for Runtime { @@ -221,18 +233,23 @@ impl pallet_balances::Trait for Runtime { parameter_types! { pub const TransactionByteFee: Balance = 10 * MILLICENTS; - // In the Substrate node, a weight of 10_000_000 (smallest non-zero weight) - // is mapped to 10_000_000 units of fees, hence: - pub const WeightFeeCoefficient: Balance = 1; - // for a sane configuration, this should always be less than `AvailableBlockRatio`. pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); } +// for a sane configuration, this should always be less than `AvailableBlockRatio`. +const_assert!( + TargetBlockFullness::get().deconstruct() < + (AvailableBlockRatio::get().deconstruct() as ::Inner) + * (::ACCURACY / ::ACCURACY as ::Inner) +); + impl pallet_transaction_payment::Trait for Runtime { type Currency = Balances; type OnTransactionPayment = DealWithFees; type TransactionByteFee = TransactionByteFee; - type WeightToFee = LinearWeightToFee; + // In the Substrate node, a weight of 10_000_000 (smallest non-zero weight) + // is mapped to 10_000_000 units of fees, hence: + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = TargetedFeeAdjustment; } @@ -341,6 +358,7 @@ parameter_types! { pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; // One cent: $10,000 / MB pub const PreimageByteDeposit: Balance = 1 * CENTS; + pub const MaxVotes: u32 = 100; } impl pallet_democracy::Trait for Runtime { @@ -371,12 +389,15 @@ impl pallet_democracy::Trait for Runtime { type VetoOrigin = pallet_collective::EnsureMember; type CooloffPeriod = CooloffPeriod; type PreimageByteDeposit = PreimageByteDeposit; + type OperationalPreimageOrigin = pallet_collective::EnsureMember; type Slash = Treasury; type Scheduler = Scheduler; + type MaxVotes = MaxVotes; } parameter_types! { pub const CouncilMotionDuration: BlockNumber = 5 * DAYS; + pub const CouncilMaxProposals: u32 = 100; } type CouncilCollective = pallet_collective::Instance1; @@ -385,6 +406,7 @@ impl pallet_collective::Trait for Runtime { type Proposal = Call; type Event = Event; type MotionDuration = CouncilMotionDuration; + type MaxProposals = CouncilMaxProposals; } parameter_types! { @@ -396,6 +418,9 @@ parameter_types! { pub const ElectionsPhragmenModuleId: LockIdentifier = *b"phrelect"; } +// Make sure that there are no more than `MAX_MEMBERS` members elected via phragmen. +const_assert!(DesiredMembers::get() <= pallet_collective::MAX_MEMBERS); + impl pallet_elections_phragmen::Trait for Runtime { type ModuleId = ElectionsPhragmenModuleId; type Event = Event; @@ -417,6 +442,7 @@ impl pallet_elections_phragmen::Trait for Runtime { parameter_types! { pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; + pub const TechnicalMaxProposals: u32 = 100; } type TechnicalCollective = pallet_collective::Instance2; @@ -425,6 +451,7 @@ impl pallet_collective::Trait for Runtime { type Proposal = Call; type Event = Event; type MotionDuration = TechnicalMotionDuration; + type MaxProposals = TechnicalMaxProposals; } impl pallet_membership::Trait for Runtime { @@ -527,7 +554,8 @@ impl frame_system::offchain::CreateSignedTransaction for R .saturating_sub(1); let tip = 0; let extra: SignedExtra = ( - frame_system::CheckVersion::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), frame_system::CheckNonce::::from(nonce), @@ -567,10 +595,15 @@ impl pallet_im_online::Trait for Runtime { type UnsignedPriority = ImOnlineUnsignedPriority; } +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); +} + impl pallet_offences::Trait for Runtime { type Event = Event; type IdentificationTuple = pallet_session::historical::IdentificationTuple; type OnOffenceHandler = Staking; + type WeightSoftLimit = OffencesWeightSoftLimit; } impl pallet_authority_discovery::Trait for Runtime {} @@ -737,8 +770,13 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. +/// +/// When you change this, you **MUST** modify [`sign`] in `bin/node/testing/src/keyring.rs`! +/// +/// [`sign`]: <../../testing/src/keyring.rs.html> pub type SignedExtra = ( - frame_system::CheckVersion, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, frame_system::CheckGenesis, frame_system::CheckEra, frame_system::CheckNonce, @@ -964,6 +1002,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, b"balances", Balances); add_benchmark!(params, batches, b"collective", Council); add_benchmark!(params, batches, b"democracy", Democracy); + add_benchmark!(params, batches, b"elections", Elections); add_benchmark!(params, batches, b"identity", Identity); add_benchmark!(params, batches, b"im-online", ImOnline); add_benchmark!(params, batches, b"offences", OffencesBench::); diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml index af375c774de425c3a940efd43e75ac49924a9606..7fe39763a48e578b30d0cf07a548fa8de0a75b40 100644 --- a/bin/node/testing/Cargo.toml +++ b/bin/node/testing/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "node-testing" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] description = "Test utilities for Substrate node." edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = true @@ -13,40 +13,40 @@ publish = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -pallet-balances = { version = "2.0.0-dev", path = "../../../frame/balances" } -sc-service = { version = "0.8.0-dev", features = ["test-helpers", "db"], path = "../../../client/service" } -sc-client-db = { version = "0.8.0-dev", path = "../../../client/db/", features = ["kvdb-rocksdb", "parity-db"] } -sc-client-api = { version = "2.0.0-dev", path = "../../../client/api/" } +pallet-balances = { version = "2.0.0-rc2", path = "../../../frame/balances" } +sc-service = { version = "0.8.0-rc2", features = ["test-helpers", "db"], path = "../../../client/service" } +sc-client-db = { version = "0.8.0-rc2", path = "../../../client/db/", features = ["kvdb-rocksdb", "parity-db"] } +sc-client-api = { version = "2.0.0-rc2", path = "../../../client/api/" } codec = { package = "parity-scale-codec", version = "1.3.0" } -pallet-contracts = { version = "2.0.0-dev", path = "../../../frame/contracts" } -pallet-grandpa = { version = "2.0.0-dev", path = "../../../frame/grandpa" } -pallet-indices = { version = "2.0.0-dev", path = "../../../frame/indices" } -sp-keyring = { version = "2.0.0-dev", path = "../../../primitives/keyring" } -node-executor = { version = "2.0.0-dev", path = "../executor" } -node-primitives = { version = "2.0.0-dev", path = "../primitives" } -node-runtime = { version = "2.0.0-dev", path = "../runtime" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-io = { version = "2.0.0-dev", path = "../../../primitives/io" } -frame-support = { version = "2.0.0-dev", path = "../../../frame/support" } -pallet-session = { version = "2.0.0-dev", path = "../../../frame/session" } -pallet-society = { version = "2.0.0-dev", path = "../../../frame/society" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -pallet-staking = { version = "2.0.0-dev", path = "../../../frame/staking" } -sc-executor = { version = "0.8.0-dev", path = "../../../client/executor", features = ["wasmtime"] } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -frame-system = { version = "2.0.0-dev", path = "../../../frame/system" } -substrate-test-client = { version = "2.0.0-dev", path = "../../../test-utils/client" } -pallet-timestamp = { version = "2.0.0-dev", path = "../../../frame/timestamp" } -pallet-transaction-payment = { version = "2.0.0-dev", path = "../../../frame/transaction-payment" } -pallet-treasury = { version = "2.0.0-dev", path = "../../../frame/treasury" } +pallet-contracts = { version = "2.0.0-rc2", path = "../../../frame/contracts" } +pallet-grandpa = { version = "2.0.0-rc2", path = "../../../frame/grandpa" } +pallet-indices = { version = "2.0.0-rc2", path = "../../../frame/indices" } +sp-keyring = { version = "2.0.0-rc2", path = "../../../primitives/keyring" } +node-executor = { version = "2.0.0-rc2", path = "../executor" } +node-primitives = { version = "2.0.0-rc2", path = "../primitives" } +node-runtime = { version = "2.0.0-rc2", path = "../runtime" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-io = { version = "2.0.0-rc2", path = "../../../primitives/io" } +frame-support = { version = "2.0.0-rc2", path = "../../../frame/support" } +pallet-session = { version = "2.0.0-rc2", path = "../../../frame/session" } +pallet-society = { version = "2.0.0-rc2", path = "../../../frame/society" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +pallet-staking = { version = "2.0.0-rc2", path = "../../../frame/staking" } +sc-executor = { version = "0.8.0-rc2", path = "../../../client/executor", features = ["wasmtime"] } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +frame-system = { version = "2.0.0-rc2", path = "../../../frame/system" } +substrate-test-client = { version = "2.0.0-rc2", path = "../../../test-utils/client" } +pallet-timestamp = { version = "2.0.0-rc2", path = "../../../frame/timestamp" } +pallet-transaction-payment = { version = "2.0.0-rc2", path = "../../../frame/transaction-payment" } +pallet-treasury = { version = "2.0.0-rc2", path = "../../../frame/treasury" } wabt = "0.9.2" -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -sp-finality-tracker = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/finality-tracker" } -sp-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/timestamp" } -sp-block-builder = { version = "2.0.0-dev", path = "../../../primitives/block-builder" } -sc-block-builder = { version = "0.8.0-dev", path = "../../../client/block-builder" } -sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +sp-finality-tracker = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/finality-tracker" } +sp-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/timestamp" } +sp-block-builder = { version = "2.0.0-rc2", path = "../../../primitives/block-builder" } +sc-block-builder = { version = "0.8.0-rc2", path = "../../../client/block-builder" } +sp-inherents = { version = "2.0.0-rc2", path = "../../../primitives/inherents" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } log = "0.4.8" tempfile = "3.1.0" fs_extra = "1" @@ -54,4 +54,4 @@ futures = "0.3.1" [dev-dependencies] criterion = "0.3.0" -sc-cli = { version = "0.8.0-dev", path = "../../../client/cli" } +sc-cli = { version = "0.8.0-rc2", path = "../../../client/cli" } diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index cdc9cc86e5709c17ffb55bdf9510f45ffa5dd01f..fc5daa80ad63ebd7657331492154320de9912090 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Benchmarking module. //! @@ -20,7 +22,7 @@ //! can pregenerate seed database and `clone` it for every iteration of your benchmarks //! or tests to get consistent, smooth benchmark experience! -use std::{sync::Arc, path::Path, collections::BTreeMap}; +use std::{sync::Arc, path::{Path, PathBuf}, collections::BTreeMap}; use node_primitives::Block; use crate::client::{Client, Backend}; @@ -94,11 +96,13 @@ impl BenchPair { pub struct BenchDb { keyring: BenchKeyring, directory_guard: Guard, + database_type: DatabaseType, } impl Clone for BenchDb { fn clone(&self) -> Self { let keyring = self.keyring.clone(); + let database_type = self.database_type; let dir = tempfile::tempdir().expect("temp dir creation failed"); let seed_dir = self.directory_guard.0.path(); @@ -122,7 +126,7 @@ impl Clone for BenchDb { &fs_extra::dir::CopyOptions::new(), ).expect("Copy of seed database is ok"); - BenchDb { keyring, directory_guard: Guard(dir) } + BenchDb { keyring, directory_guard: Guard(dir), database_type } } } @@ -130,18 +134,57 @@ impl Clone for BenchDb { #[derive(Debug, PartialEq, Clone, Copy)] pub enum BlockType { /// Bunch of random transfers. - RandomTransfersKeepAlive(usize), + RandomTransfersKeepAlive, /// Bunch of random transfers that drain all of the source balance. - RandomTransfersReaping(usize), + RandomTransfersReaping, /// Bunch of "no-op" calls. - Noop(usize), + Noop, } impl BlockType { - /// Number of transactions for this block type. - pub fn transactions(&self) -> usize { + /// Create block content description with specified number of transactions. + pub fn to_content(self, size: Option) -> BlockContent { + BlockContent { + block_type: self, + size: size, + } + } +} + +/// Content of the generated block. +pub struct BlockContent { + block_type: BlockType, + size: Option, +} + +impl BlockContent { + fn iter_while(&self, mut f: impl FnMut(usize) -> bool) { + match self.size { + Some(v) => { for i in 0..v { if !f(i) { break; }}} + None => { for i in 0.. { if !f(i) { break; }}} + } + } +} + +/// Type of backend database. +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum DatabaseType { + /// RocksDb backend. + RocksDb, + /// Parity DB backend. + ParityDb, +} + +impl DatabaseType { + fn into_settings(self, path: PathBuf) -> sc_client_db::DatabaseSettingsSrc { match self { - Self::RandomTransfersKeepAlive(v) | Self::RandomTransfersReaping(v) | Self::Noop(v) => *v, + Self::RocksDb => sc_client_db::DatabaseSettingsSrc::RocksDb { + path, + cache_size: 512, + }, + Self::ParityDb => sc_client_db::DatabaseSettingsSrc::ParityDb { + path, + } } } } @@ -179,9 +222,13 @@ impl CloneableSpawn for TaskExecutor { impl BenchDb { /// New immutable benchmarking database. /// - /// See [`new`] method documentation for more information about the purpose + /// See [`BenchDb::new`] method documentation for more information about the purpose /// of this structure. - pub fn with_key_types(keyring_length: usize, key_types: KeyTypes) -> Self { + pub fn with_key_types( + database_type: DatabaseType, + keyring_length: usize, + key_types: KeyTypes, + ) -> Self { let keyring = BenchKeyring::new(keyring_length, key_types); let dir = tempfile::tempdir().expect("temp dir creation failed"); @@ -190,10 +237,10 @@ impl BenchDb { "Created seed db at {}", dir.path().to_string_lossy(), ); - let (_client, _backend) = Self::bench_client(dir.path(), Profile::Native, &keyring); + let (_client, _backend) = Self::bench_client(database_type, dir.path(), Profile::Native, &keyring); let directory_guard = Guard(dir); - BenchDb { keyring, directory_guard } + BenchDb { keyring, directory_guard, database_type } } /// New immutable benchmarking database. @@ -204,8 +251,8 @@ impl BenchDb { /// You can `clone` this database or you can `create_context` from it /// (which also does `clone`) to run actual operation against new database /// which will be identical to the original. - pub fn new(keyring_length: usize) -> Self { - Self::with_key_types(keyring_length, KeyTypes::Sr25519) + pub fn new(database_type: DatabaseType, keyring_length: usize) -> Self { + Self::with_key_types(database_type, keyring_length, KeyTypes::Sr25519) } // This should return client that is doing everything that full node @@ -213,15 +260,17 @@ impl BenchDb { // // - This client should use best wasm execution method. // - This client should work with real database only. - fn bench_client(dir: &std::path::Path, profile: Profile, keyring: &BenchKeyring) -> (Client, std::sync::Arc) { + fn bench_client( + database_type: DatabaseType, + dir: &std::path::Path, + profile: Profile, + keyring: &BenchKeyring, + ) -> (Client, std::sync::Arc) { let db_config = sc_client_db::DatabaseSettings { state_cache_size: 16*1024*1024, state_cache_child_ratio: Some((0, 100)), pruning: PruningMode::ArchiveAll, - source: sc_client_db::DatabaseSettingsSrc::RocksDb { - path: dir.into(), - cache_size: 512, - }, + source: database_type.into_settings(dir.into()), }; let (client, backend) = sc_service::new_client( @@ -240,16 +289,16 @@ impl BenchDb { } /// Generate new block using this database. - pub fn generate_block(&mut self, block_type: BlockType) -> Block { + pub fn generate_block(&mut self, content: BlockContent) -> Block { let (client, _backend) = Self::bench_client( + self.database_type, self.directory_guard.path(), Profile::Wasm, &self.keyring, ); - let version = client.runtime_version_at(&BlockId::number(0)) - .expect("There should be runtime version at 0") - .spec_version; + let runtime_version = client.runtime_version_at(&BlockId::number(0)) + .expect("There should be runtime version at 0"); let genesis_hash = client.block_hash(Zero::zero()) .expect("Database error?") @@ -278,10 +327,8 @@ impl BenchDb { block.push(extrinsic).expect("Push inherent failed"); } - let mut iteration = 0; let start = std::time::Instant::now(); - for _ in 0..block_type.transactions() { - + content.iter_while(|iteration| { let sender = self.keyring.at(iteration); let receiver = get_account_id_from_seed::( &format!("random-user//{}", iteration) @@ -290,8 +337,8 @@ impl BenchDb { let signed = self.keyring.sign( CheckedExtrinsic { signed: Some((sender, signed_extra(0, node_runtime::ExistentialDeposit::get() + 1))), - function: match block_type { - BlockType::RandomTransfersKeepAlive(_) => { + function: match content.block_type { + BlockType::RandomTransfersKeepAlive => { Call::Balances( BalancesCall::transfer_keep_alive( pallet_indices::address::Address::Id(receiver), @@ -299,7 +346,7 @@ impl BenchDb { ) ) }, - BlockType::RandomTransfersReaping(_) => { + BlockType::RandomTransfersReaping => { Call::Balances( BalancesCall::transfer( pallet_indices::address::Address::Id(receiver), @@ -309,14 +356,15 @@ impl BenchDb { ) ) }, - BlockType::Noop(_) => { + BlockType::Noop => { Call::System( SystemCall::remark(Vec::new()) ) }, }, }, - version, + runtime_version.spec_version, + runtime_version.transaction_version, genesis_hash, ); @@ -329,13 +377,13 @@ impl BenchDb { Err(sp_blockchain::Error::ApplyExtrinsicFailed( sp_blockchain::ApplyExtrinsicFailed::Validity(e) )) if e.exhausted_resources() => { - break; + return false; }, Err(err) => panic!("Error pushing transaction: {:?}", err), - Ok(_) => {}, + Ok(_) => true, } - iteration += 1; - } + }); + let block = block.build().expect("Block build failed").block; log::info!( @@ -354,8 +402,13 @@ impl BenchDb { /// Clone this database and create context for testing/benchmarking. pub fn create_context(&self, profile: Profile) -> BenchContext { - let BenchDb { directory_guard, keyring } = self.clone(); - let (client, backend) = Self::bench_client(directory_guard.path(), profile, &keyring); + let BenchDb { directory_guard, keyring, database_type } = self.clone(); + let (client, backend) = Self::bench_client( + database_type, + directory_guard.path(), + profile, + &keyring + ); BenchContext { client, backend, db_guard: directory_guard, @@ -409,10 +462,16 @@ impl BenchKeyring { } /// Sign transaction with keypair from this keyring. - pub fn sign(&self, xt: CheckedExtrinsic, version: u32, genesis_hash: [u8; 32]) -> UncheckedExtrinsic { + pub fn sign( + &self, + xt: CheckedExtrinsic, + spec_version: u32, + tx_version: u32, + genesis_hash: [u8; 32] + ) -> UncheckedExtrinsic { match xt.signed { Some((signed, extra)) => { - let payload = (xt.function, extra.clone(), version, genesis_hash, genesis_hash); + let payload = (xt.function, extra.clone(), spec_version, tx_version, genesis_hash, genesis_hash); let key = self.accounts.get(&signed).expect("Account id not found in keyring"); let signature = payload.using_encoded(|b| { if b.len() > 256 { diff --git a/bin/node/testing/src/client.rs b/bin/node/testing/src/client.rs index 69583e37dc90f25a73dfa0660b5d692f9520d57d..f44747b26b7a6eb6409e76063b23914f3fb43f66 100644 --- a/bin/node/testing/src/client.rs +++ b/bin/node/testing/src/client.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Utilities to build a `TestClient` for `node-runtime`. diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 0f72d2c5471bd835be225a9d046d02867ca6fbc4..2bbae96cf4332f08c24469857388d72877877653 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Genesis Configuration. @@ -21,7 +23,7 @@ use sp_keyring::{Ed25519Keyring, Sr25519Keyring}; use node_runtime::{ GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, SystemConfig, GrandpaConfig, IndicesConfig, ContractsConfig, SocietyConfig, WASM_BINARY, - AccountId, + AccountId, StakerStatus, }; use node_runtime::constants::currency::*; use sp_core::ChangesTrieConfiguration; @@ -85,9 +87,9 @@ pub fn config_endowed( }), pallet_staking: Some(StakingConfig { stakers: vec![ - (dave(), alice(), 111 * DOLLARS, pallet_staking::StakerStatus::Validator), - (eve(), bob(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator), - (ferdie(), charlie(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator) + (dave(), alice(), 111 * DOLLARS, StakerStatus::Validator), + (eve(), bob(), 100 * DOLLARS, StakerStatus::Validator), + (ferdie(), charlie(), 100 * DOLLARS, StakerStatus::Validator) ], validator_count: 3, minimum_validator_count: 0, diff --git a/bin/node/testing/src/keyring.rs b/bin/node/testing/src/keyring.rs index 7ed2b36502e8534c0d30e7714fc00e9c4071b278..efa47a59821945caa16a271b81bc7dcd344b5292 100644 --- a/bin/node/testing/src/keyring.rs +++ b/bin/node/testing/src/keyring.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Test accounts. @@ -68,7 +70,8 @@ pub fn to_session_keys( /// Returns transaction extra. pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { ( - frame_system::CheckVersion::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), frame_system::CheckGenesis::new(), frame_system::CheckEra::from(Era::mortal(256, 0)), frame_system::CheckNonce::from(nonce), @@ -79,10 +82,10 @@ pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { } /// Sign given `CheckedExtrinsic`. -pub fn sign(xt: CheckedExtrinsic, version: u32, genesis_hash: [u8; 32]) -> UncheckedExtrinsic { +pub fn sign(xt: CheckedExtrinsic, spec_version: u32, tx_version: u32, genesis_hash: [u8; 32]) -> UncheckedExtrinsic { match xt.signed { Some((signed, extra)) => { - let payload = (xt.function, extra.clone(), version, genesis_hash, genesis_hash); + let payload = (xt.function, extra.clone(), spec_version, tx_version, genesis_hash, genesis_hash); let key = AccountKeyring::from_account_id(&signed).unwrap(); let signature = payload.using_encoded(|b| { if b.len() > 256 { diff --git a/bin/node/testing/src/lib.rs b/bin/node/testing/src/lib.rs index 6a06d318016f290fd96d6a33fbe7c2e2163ce988..d682347e40019dd4a7ff74a8716929130623f31e 100644 --- a/bin/node/testing/src/lib.rs +++ b/bin/node/testing/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! A set of testing utilities for Substrate Node. diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml index a6c2b671fe687f3d103c4673842a9b8a3a73266e..7ac1da46066770849d7c6c606d8064af4b726b29 100644 --- a/bin/utils/chain-spec-builder/Cargo.toml +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "chain-spec-builder" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -13,9 +13,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] ansi_term = "0.12.1" -sc-keystore = { version = "2.0.0-dev", path = "../../../client/keystore" } -sc-chain-spec = { version = "2.0.0-dev", path = "../../../client/chain-spec" } -node-cli = { version = "2.0.0-dev", path = "../../node/cli" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } +sc-keystore = { version = "2.0.0-rc2", path = "../../../client/keystore" } +sc-chain-spec = { version = "2.0.0-rc2", path = "../../../client/chain-spec" } +node-cli = { version = "2.0.0-rc2", path = "../../node/cli" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } rand = "0.7.2" structopt = "0.3.8" diff --git a/bin/utils/chain-spec-builder/build.rs b/bin/utils/chain-spec-builder/build.rs index 513cc234d4363a854961db1efdea1cbc7007ce56..8d5aac1a08742486a9b0e5d55aaf7959941abd77 100644 --- a/bin/utils/chain-spec-builder/build.rs +++ b/bin/utils/chain-spec-builder/build.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::env; diff --git a/bin/utils/chain-spec-builder/src/main.rs b/bin/utils/chain-spec-builder/src/main.rs index 144018701460e79254db45b81cd1ef2431e2b866..4fbcc1e850723982de125067c931f27110f82ec9 100644 --- a/bin/utils/chain-spec-builder/src/main.rs +++ b/bin/utils/chain-spec-builder/src/main.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{fs, path::{Path, PathBuf}}; diff --git a/bin/utils/subkey/Cargo.toml b/bin/utils/subkey/Cargo.toml index 7f50f4546ce5a54c892f62842e6f302cb795978e..c955ac3dd1241afebb853b34d8306114c2091fd8 100644 --- a/bin/utils/subkey/Cargo.toml +++ b/bin/utils/subkey/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "subkey" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,10 +12,10 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] futures = "0.1.29" -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -node-runtime = { version = "2.0.0-dev", path = "../../node/runtime" } -node-primitives = { version = "2.0.0-dev", path = "../../node/primitives" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +node-runtime = { version = "2.0.0-rc2", path = "../../node/runtime" } +node-primitives = { version = "2.0.0-rc2", path = "../../node/primitives" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } rand = "0.7.2" clap = "2.33.0" tiny-bip39 = "0.7" @@ -23,17 +23,17 @@ substrate-bip39 = "0.4.1" hex = "0.4.0" hex-literal = "0.2.1" codec = { package = "parity-scale-codec", version = "1.3.0" } -frame-system = { version = "2.0.0-dev", path = "../../../frame/system" } -pallet-balances = { version = "2.0.0-dev", path = "../../../frame/balances" } -pallet-transaction-payment = { version = "2.0.0-dev", path = "../../../frame/transaction-payment" } -pallet-grandpa = { version = "2.0.0-dev", path = "../../../frame/grandpa" } +frame-system = { version = "2.0.0-rc2", path = "../../../frame/system" } +pallet-balances = { version = "2.0.0-rc2", path = "../../../frame/balances" } +pallet-transaction-payment = { version = "2.0.0-rc2", path = "../../../frame/transaction-payment" } +pallet-grandpa = { version = "2.0.0-rc2", path = "../../../frame/grandpa" } rpassword = "4.0.1" itertools = "0.8.2" derive_more = { version = "0.99.2" } -sc-rpc = { version = "2.0.0-dev", path = "../../../client/rpc" } +sc-rpc = { version = "2.0.0-rc2", path = "../../../client/rpc" } jsonrpc-core-client = { version = "14.0.3", features = ["http"] } hyper = "0.12.35" -libp2p = "0.18.1" +libp2p = "0.19.1" serde_json = "1.0" [features] diff --git a/bin/utils/subkey/src/main.rs b/bin/utils/subkey/src/main.rs index 754a2611bcd0f997e5f18b8b68868cb9a0c451d3..4153e769c97f57ce65e3f6eb2c36c1991c586224 100644 --- a/bin/utils/subkey/src/main.rs +++ b/bin/utils/subkey/src/main.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . #![cfg_attr(feature = "bench", feature(test))] #[cfg(feature = "bench")] @@ -265,6 +267,9 @@ fn get_app<'a, 'b>(usage: &'a str) -> App<'a, 'b> { If the value is a file, the file content is used as URI. \ If not given, you will be prompted for the URI.' "), + SubCommand::with_name("inspect-node-key") + .about("Print the peer ID corresponding to the node key in the given file") + .args_from_usage("[file] 'Name of file to read the secret key from'"), SubCommand::with_name("sign") .about("Sign a message, provided on STDIN, with a given (secret) key") .args_from_usage(" @@ -437,6 +442,17 @@ where ("inspect", Some(matches)) => { C::print_from_uri(&get_uri("uri", &matches)?, password, maybe_network, output); } + ("inspect-node-key", Some(matches)) => { + let file = matches.value_of("file").ok_or(Error::Static("Input file name is required"))?; + + let mut file_content = fs::read(file)?; + let secret = libp2p_ed25519::SecretKey::from_bytes(&mut file_content) + .map_err(|_| Error::Static("Bad node key file"))?; + let keypair = libp2p_ed25519::Keypair::from(secret); + let peer_id = PublicKey::Ed25519(keypair.public()).into_peer_id(); + + println!("{}", peer_id); + } ("sign", Some(matches)) => { let suri = get_uri("suri", &matches)?; let should_decode = matches.is_present("hex"); @@ -523,7 +539,7 @@ where let account_id: AccountId = ModuleId(id_fixed_array).into_account(); let v = maybe_network.unwrap_or(Ss58AddressFormat::SubstrateAccount); - + C::print_from_uri(&account_id.to_ss58check_with_version(v), password, maybe_network, output); } _ => print_usage(&matches), @@ -702,7 +718,8 @@ fn create_extrinsic( { let extra = |i: Index, f: Balance| { ( - frame_system::CheckVersion::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(Era::Immortal), frame_system::CheckNonce::::from(i), @@ -715,7 +732,8 @@ fn create_extrinsic( function, extra(index, 0), ( - VERSION.spec_version as u32, + VERSION.spec_version, + VERSION.transaction_version, genesis_hash, genesis_hash, (), diff --git a/bin/utils/subkey/src/rpc.rs b/bin/utils/subkey/src/rpc.rs index e08ccc19a22b8de89088ffade2809f7418eb7d25..e24cf50dc45026615891782cc2440a3eda5749a0 100644 --- a/bin/utils/subkey/src/rpc.rs +++ b/bin/utils/subkey/src/rpc.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Helper to run commands against current node RPC diff --git a/bin/utils/subkey/src/vanity.rs b/bin/utils/subkey/src/vanity.rs index f921470946ec04732654091922711808f8aa6ad7..d09aeeef25a47a79ff434035a4d43a20d88c53a6 100644 --- a/bin/utils/subkey/src/vanity.rs +++ b/bin/utils/subkey/src/vanity.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use super::{PublicOf, PublicT, Crypto}; use sp_core::Pair; diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml index a18068b83322f289ee26ec3a0fad7ce6717aae7b..f46c45a691e26e1117b804ac5a5dcd1dacdf87ff 100644 --- a/client/api/Cargo.toml +++ b/client/api/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-client-api" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate client interfaces." @@ -14,36 +14,36 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" } +sp-consensus = { version = "0.8.0-rc2", path = "../../primitives/consensus/common" } derive_more = { version = "0.99.2" } -sc-executor = { version = "0.8.0-dev", path = "../executor" } -sp-externalities = { version = "0.8.0-dev", path = "../../primitives/externalities" } +sc-executor = { version = "0.8.0-rc2", path = "../executor" } +sp-externalities = { version = "0.8.0-rc2", path = "../../primitives/externalities" } fnv = { version = "1.0.6" } futures = { version = "0.3.1" } hash-db = { version = "0.15.2", default-features = false } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } hex-literal = { version = "0.2.1" } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" } -kvdb = "0.5.0" +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/inherents" } +sp-keyring = { version = "2.0.0-rc2", path = "../../primitives/keyring" } +kvdb = "0.6.0" log = { version = "0.4.8" } parking_lot = "0.10.0" lazy_static = "1.4.0" -sp-database = { version = "2.0.0-dev", path = "../../primitives/database" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-version = { version = "2.0.0-dev", default-features = false, path = "../../primitives/version" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } -sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" } -sp-trie = { version = "2.0.0-dev", path = "../../primitives/trie" } -sp-storage = { version = "2.0.0-dev", path = "../../primitives/storage" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transaction-pool" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-dev", path = "../../utils/prometheus" } +sp-database = { version = "2.0.0-rc2", path = "../../primitives/database" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-version = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/version" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } +sc-telemetry = { version = "2.0.0-rc2", path = "../telemetry" } +sp-trie = { version = "2.0.0-rc2", path = "../../primitives/trie" } +sp-storage = { version = "2.0.0-rc2", path = "../../primitives/storage" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../primitives/transaction-pool" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-rc2", path = "../../utils/prometheus" } [dev-dependencies] -kvdb-memorydb = "0.5.0" -sp-test-primitives = { version = "2.0.0-dev", path = "../../primitives/test-primitives" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../test-utils/runtime" } +kvdb-memorydb = "0.6.0" +sp-test-primitives = { version = "2.0.0-rc2", path = "../../primitives/test-primitives" } +substrate-test-runtime = { version = "2.0.0-rc2", path = "../../test-utils/runtime" } diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs index 8aaeb944833908bf26149b818fd99ded46da42e4..6a7114fcc825c413f0fd94b7f1c772b758806254 100644 --- a/client/api/src/backend.rs +++ b/client/api/src/backend.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate Client data backend diff --git a/client/api/src/call_executor.rs b/client/api/src/call_executor.rs index 00711e83b75ac639f08246527e0aa08d0ce210e2..d9d43900dfc94f2732db7be0051401a832bf8c5b 100644 --- a/client/api/src/call_executor.rs +++ b/client/api/src/call_executor.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! A method call executor interface. diff --git a/client/api/src/cht.rs b/client/api/src/cht.rs index ecf52d0bab49bd409c6e7a60fb5b117f3d684d3a..30cfd3a1b671b8f159d40bdcb499137de8fe5a69 100644 --- a/client/api/src/cht.rs +++ b/client/api/src/cht.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Canonical hash trie definitions and helper functions. //! diff --git a/client/api/src/in_mem.rs b/client/api/src/in_mem.rs index d5b4800f4e421dfdf55321059c036944ca05111d..45c41fbcb7b20412a8d792577ff67bff457497b1 100644 --- a/client/api/src/in_mem.rs +++ b/client/api/src/in_mem.rs @@ -1,27 +1,28 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! In memory client backend use std::collections::HashMap; use std::sync::Arc; use parking_lot::RwLock; -use sp_core::storage::well_known_keys; -use sp_core::offchain::storage::{ - InMemOffchainStorage as OffchainStorage +use sp_core::{ + storage::well_known_keys, offchain::storage::InMemOffchainStorage as OffchainStorage, }; use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor, HashFor}; @@ -517,13 +518,17 @@ impl backend::BlockImportOperation for BlockImportOperatio fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result { check_genesis_storage(&storage)?; - let child_delta = storage.children_default.into_iter() + let child_delta = storage.children_default.iter() .map(|(_storage_key, child_content)| - (child_content.child_info, child_content.data.into_iter().map(|(k, v)| (k, Some(v))))); + ( + &child_content.child_info, + child_content.data.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))) + ) + ); let (root, transaction) = self.old_state.full_storage_root( - storage.top.into_iter().map(|(k, v)| (k, Some(v))), - child_delta + storage.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))), + child_delta, ); self.new_state = Some(transaction); diff --git a/client/api/src/leaves.rs b/client/api/src/leaves.rs index a555943444ad1a120ad11c3ad40433af54560e25..25f9f3d29b02259d82ce8f7e9b0a8b8bd38c1a12 100644 --- a/client/api/src/leaves.rs +++ b/client/api/src/leaves.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Helper for managing the set of available leaves in the chain for DB implementations. diff --git a/client/api/src/notifications.rs b/client/api/src/notifications.rs index 412fe8adc1e5ba1e8bc36b6e3cb7e7da8cc04619..ec63c372c7e5969b28e5dfdbd54afae0b757b1b6 100644 --- a/client/api/src/notifications.rs +++ b/client/api/src/notifications.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Storage notifications diff --git a/client/api/src/proof_provider.rs b/client/api/src/proof_provider.rs index 93160855eaebe733a3058f7373b3e78a11f5813b..5749ae0576fc38799d8c2eeb9b2aeaccd49b2bca 100644 --- a/client/api/src/proof_provider.rs +++ b/client/api/src/proof_provider.rs @@ -1,18 +1,21 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . + //! Proof utilities use sp_runtime::{ generic::BlockId, diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml index 1a0c3d89afce7c47078e3949bb04a30990ae7170..c32fb67c51caeac557af8ed9ad199cb3764d31e9 100644 --- a/client/authority-discovery/Cargo.toml +++ b/client/authority-discovery/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-authority-discovery" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate authority discovery." @@ -21,23 +21,23 @@ codec = { package = "parity-scale-codec", default-features = false, version = "1 derive_more = "0.99.2" futures = "0.3.4" futures-timer = "3.0.1" -libp2p = { version = "0.18.1", default-features = false, features = ["secp256k1", "libp2p-websocket"] } +libp2p = { version = "0.19.1", default-features = false, features = ["secp256k1", "libp2p-websocket"] } log = "0.4.8" -prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-dev"} +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc2"} prost = "0.6.1" rand = "0.7.2" -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sc-keystore = { version = "2.0.0-dev", path = "../keystore" } -sc-network = { version = "0.8.0-dev", path = "../network" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sc-keystore = { version = "2.0.0-rc2", path = "../keystore" } +sc-network = { version = "0.8.0-rc2", path = "../network" } serde_json = "1.0.41" -sp-authority-discovery = { version = "2.0.0-dev", path = "../../primitives/authority-discovery" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } +sp-authority-discovery = { version = "2.0.0-rc2", path = "../../primitives/authority-discovery" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } [dev-dependencies] env_logger = "0.7.0" quickcheck = "0.9.0" -sc-peerset = { version = "2.0.0-dev", path = "../peerset" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client"} +sc-peerset = { version = "2.0.0-rc2", path = "../peerset" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client"} diff --git a/client/authority-discovery/src/tests.rs b/client/authority-discovery/src/tests.rs index c13bca894c60bfca4e67c7a97f49d056c7721e86..12edcf5fc9008eb56dbd62aa3f637011de67bd94 100644 --- a/client/authority-discovery/src/tests.rs +++ b/client/authority-discovery/src/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{iter::FromIterator, sync::{Arc, Mutex}}; diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml index a9ac58ef3211be3bc835bdc73754344964247934..dad9c54f841f1d42bcfd70ae2249e8acea1d5bb1 100644 --- a/client/basic-authorship/Cargo.toml +++ b/client/basic-authorship/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-basic-authorship" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Basic implementation of block-authoring logic." @@ -12,23 +12,25 @@ description = "Basic implementation of block-authoring logic." targets = ["x86_64-unknown-linux-gnu"] [dependencies] -log = "0.4.8" -futures = "0.3.4" codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" } -sp-inherents = { version = "2.0.0-dev", path = "../../primitives/inherents" } -sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transaction-pool" } -sc-block-builder = { version = "0.8.0-dev", path = "../block-builder" } -tokio-executor = { version = "0.2.0-alpha.6", features = ["blocking"] } +futures = "0.3.4" futures-timer = "3.0.1" +log = "0.4.8" +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc2"} +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-consensus = { version = "0.8.0-rc2", path = "../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0-rc2", path = "../../primitives/inherents" } +sc-telemetry = { version = "2.0.0-rc2", path = "../telemetry" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../primitives/transaction-pool" } +sc-block-builder = { version = "0.8.0-rc2", path = "../block-builder" } +sc-proposer-metrics = { version = "0.8.0-rc2", path = "../proposer-metrics" } +tokio-executor = { version = "0.2.0-alpha.6", features = ["blocking"] } [dev-dependencies] -sc-transaction-pool = { version = "2.0.0-dev", path = "../../client/transaction-pool" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sc-transaction-pool = { version = "2.0.0-rc2", path = "../../client/transaction-pool" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } parking_lot = "0.10.0" diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index e1e99938e375eb54ba16607938087626680df826..fe64097e424451538359f6ada041c5533e804f18 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! A consensus proposer for "basic" chains which use the primitive inherent-data. @@ -37,21 +39,31 @@ use futures::{executor, future, future::Either}; use sp_blockchain::{HeaderBackend, ApplyExtrinsicFailed::Validity, Error::ApplyExtrinsicFailed}; use std::marker::PhantomData; +use prometheus_endpoint::Registry as PrometheusRegistry; +use sc_proposer_metrics::MetricsLink as PrometheusMetrics; + /// Proposer factory. pub struct ProposerFactory { /// The client instance. client: Arc, /// The transaction pool. transaction_pool: Arc, + /// Prometheus Link, + metrics: PrometheusMetrics, /// phantom member to pin the `Backend` type. _phantom: PhantomData, } impl ProposerFactory { - pub fn new(client: Arc, transaction_pool: Arc) -> Self { + pub fn new( + client: Arc, + transaction_pool: Arc, + prometheus: Option<&PrometheusRegistry>, + ) -> Self { ProposerFactory { client, transaction_pool, + metrics: PrometheusMetrics::new(prometheus), _phantom: PhantomData, } } @@ -79,15 +91,14 @@ impl ProposerFactory info!("🙌 Starting consensus session on top of parent {:?}", parent_hash); let proposer = Proposer { - inner: Arc::new(ProposerInner { - client: self.client.clone(), - parent_hash, - parent_id: id, - parent_number: *parent_header.number(), - transaction_pool: self.transaction_pool.clone(), - now, - _phantom: PhantomData, - }), + client: self.client.clone(), + parent_hash, + parent_id: id, + parent_number: *parent_header.number(), + transaction_pool: self.transaction_pool.clone(), + now, + metrics: self.metrics.clone(), + _phantom: PhantomData, }; proposer @@ -119,17 +130,13 @@ impl sp_consensus::Environment for /// The proposer logic. pub struct Proposer { - inner: Arc>, -} - -/// Proposer inner, to wrap parameters under Arc. -struct ProposerInner { client: Arc, parent_hash: ::Hash, parent_id: BlockId, parent_number: <::Header as HeaderT>::Number, transaction_pool: Arc, now: Box time::Instant + Send + Sync>, + metrics: PrometheusMetrics, _phantom: PhantomData, } @@ -151,22 +158,21 @@ impl sp_consensus::Proposer for type Error = sp_blockchain::Error; fn propose( - &mut self, + self, inherent_data: InherentData, inherent_digests: DigestFor, max_duration: time::Duration, record_proof: RecordProof, ) -> Self::Proposal { - let inner = self.inner.clone(); tokio_executor::blocking::run(move || { // leave some time for evaluation and block finalization (33%) - let deadline = (inner.now)() + max_duration - max_duration / 3; - inner.propose_with(inherent_data, inherent_digests, deadline, record_proof) + let deadline = (self.now)() + max_duration - max_duration / 3; + self.propose_with(inherent_data, inherent_digests, deadline, record_proof) }) } } -impl ProposerInner +impl Proposer where A: TransactionPool, B: backend::Backend + Send + Sync + 'static, @@ -177,7 +183,7 @@ impl ProposerInner + BlockBuilderApi, { fn propose_with( - &self, + self, inherent_data: InherentData, inherent_digests: DigestFor, deadline: time::Instant, @@ -218,6 +224,7 @@ impl ProposerInner } // proceed with transactions + let block_timer = time::Instant::now(); let mut is_first = true; let mut skipped = 0; let mut unqueue_invalid = Vec::new(); @@ -288,6 +295,13 @@ impl ProposerInner let (block, storage_changes, proof) = block_builder.build()?.into_inner(); + self.metrics.report( + |metrics| { + metrics.number_of_transactions.set(block.extrinsics().len() as u64); + metrics.block_constructed.observe(block_timer.elapsed().as_secs_f64()); + } + ); + info!("🎁 Prepared block for proposing at {} [hash: {:?}; parent_hash: {}; extrinsics ({}): [{}]]", block.header().number(), ::Hash::from(block.header().hash()), @@ -378,10 +392,10 @@ mod tests { )) ); - let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); let cell = Mutex::new((false, time::Instant::now())); - let mut proposer = proposer_factory.init_with_now( + let proposer = proposer_factory.init_with_now( &client.header(&BlockId::number(0)).unwrap().unwrap(), Box::new(move || { let mut value = cell.lock(); @@ -419,10 +433,10 @@ mod tests { ).0 ); - let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); let cell = Mutex::new((false, time::Instant::now())); - let mut proposer = proposer_factory.init_with_now( + let proposer = proposer_factory.init_with_now( &client.header(&BlockId::number(0)).unwrap().unwrap(), Box::new(move || { let mut value = cell.lock(); @@ -469,9 +483,9 @@ mod tests { )) ); - let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); - let mut proposer = proposer_factory.init_with_now( + let proposer = proposer_factory.init_with_now( &client.header(&block_id).unwrap().unwrap(), Box::new(move || time::Instant::now()), ); @@ -535,14 +549,14 @@ mod tests { ]) ).unwrap(); - let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); let mut propose_block = | client: &TestClient, number, expected_block_extrinsics, expected_pool_transactions, | { - let mut proposer = proposer_factory.init_with_now( + let proposer = proposer_factory.init_with_now( &client.header(&BlockId::number(number)).unwrap().unwrap(), Box::new(move || time::Instant::now()), ); diff --git a/client/basic-authorship/src/lib.rs b/client/basic-authorship/src/lib.rs index 5eb60f1cd586c53099b0aedb6542db2298e0dbc6..63020c0e68af7c830c7c5131017d7cfed961bf90 100644 --- a/client/basic-authorship/src/lib.rs +++ b/client/basic-authorship/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Basic implementation of block-authoring logic. //! @@ -28,7 +30,7 @@ //! # let client = Arc::new(substrate_test_runtime_client::new()); //! # let txpool = Arc::new(BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone())), None).0); //! // The first step is to create a `ProposerFactory`. -//! let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); +//! let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone(), None); //! //! // From this factory, we create a `Proposer`. //! let proposer = proposer_factory.init( @@ -36,7 +38,7 @@ //! ); //! //! // The proposer is created asynchronously. -//! let mut proposer = futures::executor::block_on(proposer).unwrap(); +//! let proposer = futures::executor::block_on(proposer).unwrap(); //! //! // This `Proposer` allows us to create a block proposition. //! // The proposer will grab transactions from the transaction pool, and put them into the block. diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 15cc3c13934fa7e5fda805ce5d6fc5082aac25f4..fb5add1d8fe14382976700b63fd86306271c4166 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-block-builder" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate block builder" @@ -13,16 +13,16 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } -sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-block-builder = { version = "2.0.0-dev", path = "../../primitives/block-builder" } -sc-client-api = { version = "2.0.0-dev", path = "../api" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } +sp-consensus = { version = "0.8.0-rc2", path = "../../primitives/consensus/common" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-block-builder = { version = "2.0.0-rc2", path = "../../primitives/block-builder" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } [dev-dependencies] substrate-test-runtime-client = { path = "../../test-utils/runtime/client" } -sp-trie = { version = "2.0.0-dev", path = "../../primitives/trie" } +sp-trie = { version = "2.0.0-rc2", path = "../../primitives/trie" } diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 2154a1f5f26800ae26fca594b0d995bef9b1450f..af40b336623d85ac441c8e76a7f9619688726746 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate block builder //! diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 6906b1ecdad434884437af619548e2b34daedf4c..eee78ef676269730d6e742f2a5f2a9899ae613b9 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-chain-spec" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate chain configurations." @@ -12,12 +12,12 @@ description = "Substrate chain configurations." targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sc-chain-spec-derive = { version = "2.0.0-dev", path = "./derive" } +sc-chain-spec-derive = { version = "2.0.0-rc2", path = "./derive" } impl-trait-for-tuples = "0.1.3" -sc-network = { version = "0.8.0-dev", path = "../network" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-chain-spec = { version = "2.0.0-dev", path = "../../primitives/chain-spec" } -sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-chain-spec = { version = "2.0.0-rc2", path = "../../primitives/chain-spec" } +sc-telemetry = { version = "2.0.0-rc2", path = "../telemetry" } diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml index 66058b3f729963d100b846527a538d5c0c8915b1..1f753689aefa23158f0d331740ae6809dfb17872 100644 --- a/client/chain-spec/derive/Cargo.toml +++ b/client/chain-spec/derive/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-chain-spec-derive" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Macros to derive chain spec extension traits implementation." diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs index 8e941161ee5a01d32c2606188846f7660e8f1da2..52414f8687c96ed97f56e84e1345d3c0f8423ecc 100644 --- a/client/chain-spec/src/chain_spec.rs +++ b/client/chain-spec/src/chain_spec.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate chain configurations. diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 198a9df5b53fdbef22f16d7cec3b8741153aeaaa..8c19da95c493b41351fdf7b15c10995b68b79eca 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-cli" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Substrate CLI interface." edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,7 +12,6 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -clap = "2.33.0" derive_more = "0.99.2" env_logger = "0.7.0" log = "0.4.8" @@ -21,28 +20,28 @@ regex = "1.3.1" time = "0.1.42" ansi_term = "0.12.1" lazy_static = "1.4.0" -app_dirs = "1.2.1" +directories = "2.0.2" tokio = { version = "0.2.9", features = [ "signal", "rt-core", "rt-threaded" ] } futures = "0.3.4" fdlimit = "0.1.4" serde_json = "1.0.41" -sc-informant = { version = "0.8.0-dev", path = "../informant" } -sp-panic-handler = { version = "2.0.0-dev", path = "../../primitives/panic-handler" } -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sc-network = { version = "0.8.0-dev", path = "../network" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" } -sp-version = { version = "2.0.0-dev", path = "../../primitives/version" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sc-service = { version = "0.8.0-dev", default-features = false, path = "../service" } -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } -sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" } -substrate-prometheus-endpoint = { path = "../../utils/prometheus" , version = "0.8.0-dev"} -sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" } +sc-informant = { version = "0.8.0-rc2", path = "../informant" } +sp-panic-handler = { version = "2.0.0-rc2", path = "../../primitives/panic-handler" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } +sp-version = { version = "2.0.0-rc2", path = "../../primitives/version" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sc-service = { version = "0.8.0-rc2", default-features = false, path = "../service" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } +sc-telemetry = { version = "2.0.0-rc2", path = "../telemetry" } +substrate-prometheus-endpoint = { path = "../../utils/prometheus" , version = "0.8.0-rc2"} +sp-keyring = { version = "2.0.0-rc2", path = "../../primitives/keyring" } names = "0.11.0" structopt = "0.3.8" -sc-tracing = { version = "2.0.0-dev", path = "../tracing" } +sc-tracing = { version = "2.0.0-rc2", path = "../tracing" } chrono = "0.4.10" parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] } diff --git a/client/cli/src/arg_enums.rs b/client/cli/src/arg_enums.rs index c146a16886016e8a3ff8dc34f5f7ea63f162ebe4..4dfd384d9513c3603b94cd5f2c83f255d7552f96 100644 --- a/client/cli/src/arg_enums.rs +++ b/client/cli/src/arg_enums.rs @@ -1,19 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . // NOTE: we allow missing docs here because arg_enum! creates the function variants without doc #![allow(missing_docs)] diff --git a/client/cli/src/commands/build_spec_cmd.rs b/client/cli/src/commands/build_spec_cmd.rs index a01101fa7965563795eb3058bf3be0f752801517..d2e2ef3a5467cbadfb050467cea4aae6f3b85c45 100644 --- a/client/cli/src/commands/build_spec_cmd.rs +++ b/client/cli/src/commands/build_spec_cmd.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::error; use crate::params::NodeKeyParams; @@ -22,6 +24,7 @@ use log::info; use sc_network::config::build_multiaddr; use sc_service::{config::MultiaddrWithPeerId, Configuration}; use structopt::StructOpt; +use std::io::Write; /// The `build-spec` command used to build a specification. #[derive(Debug, StructOpt, Clone)] @@ -64,9 +67,9 @@ impl BuildSpecCmd { } let json = sc_service::chain_ops::build_spec(&*spec, raw_output)?; - - print!("{}", json); - + if std::io::stdout().write_all(json.as_bytes()).is_err() { + let _ = std::io::stderr().write_all(b"Error writing to stdout\n"); + } Ok(()) } } diff --git a/client/cli/src/commands/check_block_cmd.rs b/client/cli/src/commands/check_block_cmd.rs index d5242cda8598131a25a4dccc32e8d78075a1e65a..d1241f010d597f8327d9de9446c05dc7a3fb355e 100644 --- a/client/cli/src/commands/check_block_cmd.rs +++ b/client/cli/src/commands/check_block_cmd.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::{ CliConfiguration, error, params::{ImportParams, SharedParams, BlockNumberOrHash}, diff --git a/client/cli/src/commands/export_blocks_cmd.rs b/client/cli/src/commands/export_blocks_cmd.rs index 4f7cf0f48c05a172547e2308d4de0ef4e25ffeac..2fdc408250bce8a49b80ceda1bd64696393e8b41 100644 --- a/client/cli/src/commands/export_blocks_cmd.rs +++ b/client/cli/src/commands/export_blocks_cmd.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::error; use crate::params::{BlockNumber, DatabaseParams, PruningParams, SharedParams}; diff --git a/client/cli/src/commands/export_state_cmd.rs b/client/cli/src/commands/export_state_cmd.rs index db6f81c498f28d7bf8197f61a31571da8e64a446..33111e7737b1cdb18fdff71327930cd3feaef215 100644 --- a/client/cli/src/commands/export_state_cmd.rs +++ b/client/cli/src/commands/export_state_cmd.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::{ CliConfiguration, error, params::{PruningParams, SharedParams, BlockNumberOrHash}, @@ -20,7 +22,7 @@ use crate::{ use log::info; use sc_service::{Configuration, ServiceBuilderCommand}; use sp_runtime::traits::{Block as BlockT, NumberFor}; -use std::{fmt::Debug, str::FromStr}; +use std::{fmt::Debug, str::FromStr, io::Write}; use structopt::StructOpt; /// The `export-state` command used to export the state of a given block into @@ -63,9 +65,9 @@ impl ExportStateCmd { info!("Generating new chain spec..."); let json = sc_service::chain_ops::build_spec(&*input_spec, true)?; - - print!("{}", json); - + if std::io::stdout().write_all(json.as_bytes()).is_err() { + let _ = std::io::stderr().write_all(b"Error writing to stdout\n"); + } Ok(()) } } diff --git a/client/cli/src/commands/import_blocks_cmd.rs b/client/cli/src/commands/import_blocks_cmd.rs index ce95640f469ceb3f380f07727f4ed5bc09d431ae..a74f4d524c95bf09403a7b3d47009809b9b0f5d2 100644 --- a/client/cli/src/commands/import_blocks_cmd.rs +++ b/client/cli/src/commands/import_blocks_cmd.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::error; use crate::params::ImportParams; @@ -39,6 +41,10 @@ pub struct ImportBlocksCmd { #[structopt(long = "default-heap-pages", value_name = "COUNT")] pub default_heap_pages: Option, + /// Try importing blocks from binary format rather than JSON. + #[structopt(long)] + pub binary: bool, + #[allow(missing_docs)] #[structopt(flatten)] pub shared_params: SharedParams, @@ -77,7 +83,7 @@ impl ImportBlocksCmd { }; builder(config)? - .import_blocks(file, false) + .import_blocks(file, false, self.binary) .await .map_err(Into::into) } diff --git a/client/cli/src/commands/mod.rs b/client/cli/src/commands/mod.rs index d2bab5bca07604bbb77f67c8e8a48e50dbc2b9ca..62757890ef01d3db56de747b20c759f9c72422e1 100644 --- a/client/cli/src/commands/mod.rs +++ b/client/cli/src/commands/mod.rs @@ -1,19 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . mod build_spec_cmd; mod check_block_cmd; mod export_blocks_cmd; @@ -396,7 +397,7 @@ macro_rules! substrate_cli_subcommands { } } - fn log_filters(&self) -> $crate::Result<::std::option::Option> { + fn log_filters(&self) -> $crate::Result { match self { $($enum::$variant(cmd) => cmd.log_filters()),* } diff --git a/client/cli/src/commands/purge_chain_cmd.rs b/client/cli/src/commands/purge_chain_cmd.rs index b3fb0de2470de36038f6c478d1145b3c9b923ade..9d364a45f7d097f28ab1b1cb11d4b3b97f7d07d0 100644 --- a/client/cli/src/commands/purge_chain_cmd.rs +++ b/client/cli/src/commands/purge_chain_cmd.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::error; use crate::params::{DatabaseParams, SharedParams}; diff --git a/client/cli/src/commands/revert_cmd.rs b/client/cli/src/commands/revert_cmd.rs index f7629ff2f6357e71ed417b0bad6d6ad1fc96851b..6117eaf4880bf4425ae0c059bbde5ae3f8010ceb 100644 --- a/client/cli/src/commands/revert_cmd.rs +++ b/client/cli/src/commands/revert_cmd.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::error; use crate::params::{BlockNumber, PruningParams, SharedParams}; diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index f7cec61df1b22b01e7efc4b901f7cf50e1ba3a6f..23a410d679b8f6405ea563c719f3bba5eaae7000 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::arg_enums::RpcMethods; use crate::error::{Error, Result}; @@ -63,7 +65,7 @@ pub struct RunCmd { pub sentry: Vec, /// Disable GRANDPA voter when running in validator mode, otherwise disable the GRANDPA observer. - #[structopt(long = "no-grandpa")] + #[structopt(long)] pub no_grandpa: bool, /// Experimental: Run in light client mode. diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index f2a6715cf2f56007be42d677d01c99d8ad05e93e..a1ee1b0cc1da91947ed712bd8ccf5c5ae290e6a7 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Configuration trait for a CLI based on substrate @@ -22,7 +24,6 @@ use crate::{ init_logger, DatabaseParams, ImportParams, KeystoreParams, NetworkParams, NodeKeyParams, OffchainWorkerParams, PruningParams, SharedParams, SubstrateCli, }; -use app_dirs::{AppDataType, AppInfo}; use names::{Generator, Name}; use sc_client_api::execution_extensions::ExecutionStrategies; use sc_service::config::{ @@ -404,14 +405,10 @@ pub trait CliConfiguration: Sized { let config_dir = self .base_path()? .unwrap_or_else(|| { - app_dirs::get_app_root( - AppDataType::UserData, - &AppInfo { - name: C::executable_name(), - author: C::author(), - }, - ) - .expect("app directories exist on all supported platforms; qed") + directories::ProjectDirs::from("", "", C::executable_name()) + .expect("app directories exist on all supported platforms; qed") + .data_local_dir() + .into() }) .join("chains") .join(chain_spec.id()); @@ -472,9 +469,12 @@ pub trait CliConfiguration: Sized { /// Get the filters for the logging. /// + /// This should be a list of comma-separated values. + /// Example: `foo=trace,bar=debug,baz=info` + /// /// By default this is retrieved from `SharedParams`. - fn log_filters(&self) -> Result> { - Ok(self.shared_params().log_filters()) + fn log_filters(&self) -> Result { + Ok(self.shared_params().log_filters().join(",")) } /// Initialize substrate. This must be done only once. @@ -485,12 +485,12 @@ pub trait CliConfiguration: Sized { /// 2. Raise the FD limit /// 3. Initialize the logger fn init(&self) -> Result<()> { - let logger_pattern = self.log_filters()?.unwrap_or_default(); + let logger_pattern = self.log_filters()?; sp_panic_handler::set(C::support_url(), C::impl_version()); fdlimit::raise_fd_limit(); - init_logger(logger_pattern.as_str()); + init_logger(&logger_pattern); Ok(()) } diff --git a/client/cli/src/error.rs b/client/cli/src/error.rs index edc1adecc762c5f70c11958d1b6f9b0b93863904..31f6e1c1ff47fa3c33684cb5b1edccefcd437305 100644 --- a/client/cli/src/error.rs +++ b/client/cli/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Initialization errors. @@ -25,7 +27,7 @@ pub enum Error { /// Io error Io(std::io::Error), /// Cli error - Cli(clap::Error), + Cli(structopt::clap::Error), /// Service error Service(sc_service::Error), /// Client error diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index e723573bc2bdd43059563c809799e5bdecae7b86..2ea59129ea05e3db9c309f084c9a40ab40d8becd 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate CLI library. @@ -129,7 +131,27 @@ pub trait SubstrateCli: Sized { AppSettings::SubcommandsNegateReqs, ]); - ::from_clap(&app.get_matches_from(iter)) + let matches = match app.get_matches_from_safe(iter) { + Ok(matches) => matches, + Err(mut e) => { + // To support pipes, we can not use `writeln!` as any error + // results in a "broken pipe" error. + // + // Instead we write directly to `stdout` and ignore any error + // as we exit afterwards anyway. + e.message.extend("\n".chars()); + + if e.use_stderr() { + let _ = std::io::stderr().write_all(e.message.as_bytes()); + std::process::exit(1); + } else { + let _ = std::io::stdout().write_all(e.message.as_bytes()); + std::process::exit(0); + } + }, + }; + + ::from_clap(&matches) } /// Helper function used to parse the command line arguments. This is the equivalent of @@ -143,9 +165,9 @@ pub trait SubstrateCli: Sized { /// Print the error message and quit the program in case of failure. /// /// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are - /// used. It will return a [`clap::Error`], where the [`kind`] is a - /// [`ErrorKind::HelpDisplayed`] or [`ErrorKind::VersionDisplayed`] respectively. You must call - /// [`Error::exit`] or perform a [`std::process::exit`]. + /// used. It will return a [`clap::Error`], where the [`clap::Error::kind`] is a + /// [`clap::ErrorKind::HelpDisplayed`] or [`clap::ErrorKind::VersionDisplayed`] respectively. + /// You must call [`clap::Error::exit`] or perform a [`std::process::exit`]. fn try_from_iter(iter: I) -> clap::Result where Self: StructOpt + Sized, @@ -197,6 +219,7 @@ pub fn init_logger(pattern: &str) { let mut builder = env_logger::Builder::new(); // Disable info logging by default for some modules: builder.filter(Some("ws"), log::LevelFilter::Off); + builder.filter(Some("yamux"), log::LevelFilter::Off); builder.filter(Some("hyper"), log::LevelFilter::Warn); builder.filter(Some("cranelift_wasm"), log::LevelFilter::Warn); // Always log the special target `sc_tracing`, overrides global level @@ -264,21 +287,3 @@ fn kill_color(s: &str) -> String { } RE.replace_all(s, "").to_string() } - -/// Reset the signal pipe (`SIGPIPE`) handler to the default one provided by the system. -/// This will end the program on `SIGPIPE` instead of panicking. -/// -/// This should be called before calling any cli method or printing any output. -pub fn reset_signal_pipe_handler() -> Result<()> { - #[cfg(target_family = "unix")] - { - use nix::sys::signal; - - unsafe { - signal::signal(signal::Signal::SIGPIPE, signal::SigHandler::SigDfl) - .map_err(|e| Error::Other(e.to_string()))?; - } - } - - Ok(()) -} diff --git a/client/cli/src/params/database_params.rs b/client/cli/src/params/database_params.rs index dd0d1686e099e8544e9bd6b9e84f259597a65a4d..3ff8eb01d0643b225112584472c072c24a04300b 100644 --- a/client/cli/src/params/database_params.rs +++ b/client/cli/src/params/database_params.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::arg_enums::Database; use structopt::StructOpt; diff --git a/client/cli/src/params/import_params.rs b/client/cli/src/params/import_params.rs index c5acc6bd8144013dc91d0fa9cb42b5096201e3ec..fb683df6d3be9a734148c863c7b3549cfe1c268c 100644 --- a/client/cli/src/params/import_params.rs +++ b/client/cli/src/params/import_params.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::arg_enums::{ ExecutionStrategy, TracingReceiver, WasmExecutionMethod, diff --git a/client/cli/src/params/keystore_params.rs b/client/cli/src/params/keystore_params.rs index c6131c2f64941afa507931e5e090a4389a1e61eb..2fd610377d7935831a87356d600f2a901ffdf0cf 100644 --- a/client/cli/src/params/keystore_params.rs +++ b/client/cli/src/params/keystore_params.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::error::Result; use sc_service::config::KeystoreConfig; diff --git a/client/cli/src/params/mod.rs b/client/cli/src/params/mod.rs index da236ee1656850d35db04b34957c3675fb384cd5..3a66e5f05588a7fb13615575ad61185898b347f4 100644 --- a/client/cli/src/params/mod.rs +++ b/client/cli/src/params/mod.rs @@ -1,19 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . mod database_params; mod import_params; mod keystore_params; diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index 79112b041cf3757c7f2aa8e863d55aef30ac9981..c1639ad2b43708960160ef7f45244da255a50e1b 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::params::node_key_params::NodeKeyParams; use sc_network::{ @@ -122,6 +124,9 @@ impl NetworkParams { let listen_addresses = if self.listen_addr.is_empty() { vec![ + Multiaddr::empty() + .with(Protocol::Ip6([0, 0, 0, 0, 0, 0, 0, 0].into())) + .with(Protocol::Tcp(port)), Multiaddr::empty() .with(Protocol::Ip4([0, 0, 0, 0].into())) .with(Protocol::Tcp(port)), diff --git a/client/cli/src/params/node_key_params.rs b/client/cli/src/params/node_key_params.rs index 2913ff2c1035e2f04ae30888e9f352420c40331d..7d19971ad64703f30a6df5c7e08ca8faca287c13 100644 --- a/client/cli/src/params/node_key_params.rs +++ b/client/cli/src/params/node_key_params.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use sc_network::config::NodeKeyConfig; use sp_core::H256; diff --git a/client/cli/src/params/offchain_worker_params.rs b/client/cli/src/params/offchain_worker_params.rs index eb3cc74ad900cd72db2511a305e2ebc733a1a299..ca99ab506e48483ba035c88f0f5ace056571df01 100644 --- a/client/cli/src/params/offchain_worker_params.rs +++ b/client/cli/src/params/offchain_worker_params.rs @@ -1,19 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . //! Offchain worker related configuration parameters. //! diff --git a/client/cli/src/params/pruning_params.rs b/client/cli/src/params/pruning_params.rs index ed8f7ab16858dce49f0b8a78ae2bb60141a47eac..36179359063e748490de5c60c1be8e60177c00cd 100644 --- a/client/cli/src/params/pruning_params.rs +++ b/client/cli/src/params/pruning_params.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::error; use sc_service::{PruningMode, Role}; diff --git a/client/cli/src/params/shared_params.rs b/client/cli/src/params/shared_params.rs index 68c9a30453528390ca528a1696d5fb4fac48620d..e9440f38a1fad4669e3d5d45eb0e58a78c8ad02c 100644 --- a/client/cli/src/params/shared_params.rs +++ b/client/cli/src/params/shared_params.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::path::PathBuf; use structopt::StructOpt; @@ -21,16 +23,16 @@ use structopt::StructOpt; #[derive(Debug, StructOpt, Clone)] pub struct SharedParams { /// Specify the chain specification (one of dev, local, or staging). - #[structopt(long = "chain", value_name = "CHAIN_SPEC")] + #[structopt(long, value_name = "CHAIN_SPEC")] pub chain: Option, /// Specify the development chain. - #[structopt(long = "dev")] + #[structopt(long, conflicts_with_all = &["chain"])] pub dev: bool, /// Specify custom base path. #[structopt( - long = "base-path", + long, short = "d", value_name = "PATH", parse(from_os_str) @@ -41,8 +43,8 @@ pub struct SharedParams { /// /// Log levels (least to most verbose) are error, warn, info, debug, and trace. /// By default, all targets log `info`. The global log level can be set with -l. - #[structopt(short = "l", long = "log", value_name = "LOG_PATTERN")] - pub log: Option, + #[structopt(short = "l", long, value_name = "LOG_PATTERN")] + pub log: Vec, } impl SharedParams { @@ -71,7 +73,7 @@ impl SharedParams { } /// Get the filters for the logging - pub fn log_filters(&self) -> Option { - self.log.clone() + pub fn log_filters(&self) -> &[String] { + &self.log } } diff --git a/client/cli/src/params/transaction_pool_params.rs b/client/cli/src/params/transaction_pool_params.rs index dfcdf9af70537e51586654e4cc72da4a7549f118..2283c0f39f9c7e995d54c95dfd90836ffcc73129 100644 --- a/client/cli/src/params/transaction_pool_params.rs +++ b/client/cli/src/params/transaction_pool_params.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use sc_service::config::TransactionPoolOptions; use structopt::StructOpt; diff --git a/client/cli/src/runner.rs b/client/cli/src/runner.rs index 10e98906bfaf1b9c6bfda56f96eaa165d484cc7d..2d27743163ae4e2671789d0aa5de16cdc12428f6 100644 --- a/client/cli/src/runner.rs +++ b/client/cli/src/runner.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::CliConfiguration; use crate::Result; @@ -217,12 +219,16 @@ impl Runner { // and drop the runtime first. let _telemetry = service.telemetry(); - let f = service.fuse(); - pin_mut!(f); + { + let f = service.fuse(); + self.tokio_runtime + .block_on(main(f)) + .map_err(|e| e.to_string())?; + } - self.tokio_runtime - .block_on(main(f)) - .map_err(|e| e.to_string())?; + // The `service` **must** have been destroyed here for the shutdown signal to propagate + // to all the tasks. Dropping `tokio_runtime` will block the thread until all tasks have + // shut down. drop(self.tokio_runtime); Ok(()) diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml index 82196feac0396ae32567bf9c2173f83d5618f2a4..afd72462664da49d11dcf754f0d44cb3d600fe99 100644 --- a/client/consensus/aura/Cargo.toml +++ b/client/consensus/aura/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-consensus-aura" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Aura consensus algorithm for substrate" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,36 +12,37 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "2.0.0-dev", path = "../../../primitives/application-crypto" } -sp-consensus-aura = { version = "0.8.0-dev", path = "../../../primitives/consensus/aura" } -sp-block-builder = { version = "2.0.0-dev", path = "../../../primitives/block-builder" } -sc-block-builder = { version = "0.8.0-dev", path = "../../../client/block-builder" } -sc-client-api = { version = "2.0.0-dev", path = "../../api" } +sp-application-crypto = { version = "2.0.0-rc2", path = "../../../primitives/application-crypto" } +sp-consensus-aura = { version = "0.8.0-rc2", path = "../../../primitives/consensus/aura" } +sp-block-builder = { version = "2.0.0-rc2", path = "../../../primitives/block-builder" } +sc-block-builder = { version = "0.8.0-rc2", path = "../../../client/block-builder" } +sc-client-api = { version = "2.0.0-rc2", path = "../../api" } codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } derive_more = "0.99.2" futures = "0.3.4" futures-timer = "3.0.1" -sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" } -sc-keystore = { version = "2.0.0-dev", path = "../../keystore" } +sp-inherents = { version = "2.0.0-rc2", path = "../../../primitives/inherents" } +sc-keystore = { version = "2.0.0-rc2", path = "../../keystore" } log = "0.4.8" parking_lot = "0.10.0" -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-io = { version = "2.0.0-dev", path = "../../../primitives/io" } -sp-version = { version = "2.0.0-dev", path = "../../../primitives/version" } -sc-consensus-slots = { version = "0.8.0-dev", path = "../slots" } -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-timestamp = { version = "2.0.0-dev", path = "../../../primitives/timestamp" } -sc-telemetry = { version = "2.0.0-dev", path = "../../telemetry" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-io = { version = "2.0.0-rc2", path = "../../../primitives/io" } +sp-version = { version = "2.0.0-rc2", path = "../../../primitives/version" } +sc-consensus-slots = { version = "0.8.0-rc2", path = "../slots" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-timestamp = { version = "2.0.0-rc2", path = "../../../primitives/timestamp" } +sc-telemetry = { version = "2.0.0-rc2", path = "../../telemetry" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc2"} [dev-dependencies] -sp-keyring = { version = "2.0.0-dev", path = "../../../primitives/keyring" } -sc-executor = { version = "0.8.0-dev", path = "../../executor" } -sc-network = { version = "0.8.0-dev", path = "../../network" } -sc-network-test = { version = "0.8.0-dev", path = "../../network/test" } -sc-service = { version = "0.8.0-dev", default-features = false, path = "../../service" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } +sp-keyring = { version = "2.0.0-rc2", path = "../../../primitives/keyring" } +sc-executor = { version = "0.8.0-rc2", path = "../../executor" } +sc-network = { version = "0.8.0-rc2", path = "../../network" } +sc-network-test = { version = "0.8.0-rc2", path = "../../network/test" } +sc-service = { version = "0.8.0-rc2", default-features = false, path = "../../service" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../test-utils/runtime/client" } env_logger = "0.7.0" tempfile = "3.1.0" diff --git a/client/consensus/aura/src/digests.rs b/client/consensus/aura/src/digests.rs index 8dd42fc01def2ee6ac93c9551e68f038c658d428..3332e4c6a6dff99f2ee9ad367031fde15a33ada6 100644 --- a/client/consensus/aura/src/digests.rs +++ b/client/consensus/aura/src/digests.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Aura (Authority-Round) digests //! diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index f61fdf44917a20271f93fab971ceecec9e15417a..818bb563484be84cf83cbf878febf07b07bde63c 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Aura (Authority-round) consensus in substrate. //! @@ -30,12 +32,13 @@ #![forbid(missing_docs, unsafe_code)] use std::{ sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug, pin::Pin, - collections::HashMap + collections::HashMap, convert::{TryFrom, TryInto}, }; use futures::prelude::*; use parking_lot::Mutex; use log::{debug, info, trace}; +use prometheus_endpoint::Registry; use codec::{Encode, Decode, Codec}; @@ -52,11 +55,15 @@ use sp_blockchain::{ ProvideCache, HeaderBackend, }; use sp_block_builder::BlockBuilder as BlockBuilderApi; -use sp_runtime::{generic::{BlockId, OpaqueDigestItemId}, Justification}; +use sp_core::crypto::Public; +use sp_application_crypto::{AppKey, AppPublic}; +use sp_runtime::{ + generic::{BlockId, OpaqueDigestItemId}, + Justification, +}; use sp_runtime::traits::{Block as BlockT, Header, DigestItemFor, Zero, Member}; use sp_api::ProvideRuntimeApi; - -use sp_core::crypto::Pair; +use sp_core::{traits::BareCryptoStore, crypto::Pair}; use sp_inherents::{InherentDataProviders, InherentData}; use sp_timestamp::{ TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError @@ -150,8 +157,8 @@ pub fn start_aura( E: Environment + Send + Sync + 'static, E::Proposer: Proposer>, P: Pair + Send + Sync, - P::Public: Hash + Member + Encode + Decode, - P::Signature: Hash + Member + Encode + Decode, + P::Public: AppPublic + Hash + Member + Encode + Decode, + P::Signature: TryFrom> + Hash + Member + Encode + Decode, I: BlockImport> + Send + Sync + 'static, Error: std::error::Error + Send + From + 'static, SO: SyncOracle + Send + Sync + Clone, @@ -199,8 +206,8 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW E::Proposer: Proposer>, I: BlockImport> + Send + Sync + 'static, P: Pair + Send + Sync, - P::Public: Member + Encode + Decode + Hash, - P::Signature: Member + Encode + Decode + Hash + Debug, + P::Public: AppPublic + Public + Member + Encode + Decode + Hash, + P::Signature: TryFrom> + Member + Encode + Decode + Hash + Debug, SO: SyncOracle + Send + Clone, Error: std::error::Error + Send + From + 'static, { @@ -210,7 +217,7 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW dyn Future> + Send + 'static >>; type Proposer = E::Proposer; - type Claim = P; + type Claim = P::Public; type EpochData = Vec>; fn logging_target(&self) -> &'static str { @@ -240,10 +247,11 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW epoch_data: &Self::EpochData, ) -> Option { let expected_author = slot_author::

(slot_number, epoch_data); - expected_author.and_then(|p| { self.keystore.read() .key_pair_by_type::

(&p, sp_application_crypto::key_types::AURA).ok() + }).and_then(|p| { + Some(p.public()) }) } @@ -264,11 +272,30 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW StorageChanges, B>, Self::Claim, Self::EpochData, - ) -> sp_consensus::BlockImportParams> + Send> { - Box::new(|header, header_hash, body, storage_changes, pair, _epoch| { + ) -> Result< + sp_consensus::BlockImportParams>, + sp_consensus::Error> + Send + 'static> + { + let keystore = self.keystore.clone(); + Box::new(move |header, header_hash, body, storage_changes, public, _epoch| { // sign the pre-sealed hash of the block and then // add it to a digest item. - let signature = pair.sign(header_hash.as_ref()); + let public_type_pair = public.to_public_crypto_pair(); + let public = public.to_raw_vec(); + let signature = keystore.read() + .sign_with( + as AppKey>::ID, + &public_type_pair, + header_hash.as_ref() + ) + .map_err(|e| sp_consensus::Error::CannotSign( + public.clone(), e.to_string(), + ))?; + let signature = signature.clone().try_into() + .map_err(|_| sp_consensus::Error::InvalidSignature( + signature, public + ))?; + let signature_digest_item = as CompatibleDigestItem

>::aura_seal(signature); let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); @@ -277,7 +304,7 @@ impl sc_consensus_slots::SimpleSlotWorker for AuraW import_block.storage_changes = Some(storage_changes); import_block.fork_choice = Some(ForkChoiceStrategy::LongestChain); - import_block + Ok(import_block) }) } @@ -331,8 +358,8 @@ impl SlotWorker for AuraWorker>, I: BlockImport> + Send + Sync + 'static, P: Pair + Send + Sync, - P::Public: Member + Encode + Decode + Hash, - P::Signature: Member + Encode + Decode + Hash + Debug, + P::Public: AppPublic + Member + Encode + Decode + Hash, + P::Signature: TryFrom> + Member + Encode + Decode + Hash + Debug, SO: SyncOracle + Send + Sync + Clone, Error: std::error::Error + Send + From + 'static, { @@ -796,6 +823,7 @@ pub fn import_queue( client: Arc, inherent_data_providers: InherentDataProviders, spawner: &S, + registry: Option<&Registry>, ) -> Result>, sp_consensus::Error> where B: BlockT, C::Api: BlockBuilderApi + AuraApi> + ApiExt, @@ -822,6 +850,7 @@ pub fn import_queue( justification_import, finality_proof_import, spawner, + registry, )) } @@ -836,8 +865,11 @@ mod tests { use sp_keyring::sr25519::Keyring; use sc_client_api::BlockchainEvents; use sp_consensus_aura::sr25519::AuthorityPair; + use sc_consensus_slots::SimpleSlotWorker; use std::task::Poll; use sc_block_builder::BlockBuilderProvider; + use sp_runtime::traits::Header as _; + use substrate_test_runtime_client::runtime::{Header, H256}; type Error = sp_blockchain::Error; @@ -872,7 +904,7 @@ mod tests { type Proposal = future::Ready, Error>>; fn propose( - &mut self, + self, _: InherentData, digests: DigestFor, _: Duration, @@ -1021,4 +1053,55 @@ mod tests { Keyring::Charlie.public().into() ]); } + + #[test] + fn current_node_authority_should_claim_slot() { + let net = AuraTestNet::new(4); + + let mut authorities = vec![ + Keyring::Alice.public().into(), + Keyring::Bob.public().into(), + Keyring::Charlie.public().into() + ]; + + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); + let keystore = sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore."); + let my_key = keystore.write() + .generate_by_type::(AuthorityPair::ID) + .expect("Key should be created"); + authorities.push(my_key.public()); + + let net = Arc::new(Mutex::new(net)); + + let mut net = net.lock(); + let peer = net.peer(3); + let client = peer.client().as_full().expect("full clients are created").clone(); + let environ = DummyFactory(client.clone()); + + let worker = AuraWorker { + client: client.clone(), + block_import: Arc::new(Mutex::new(client)), + env: environ, + keystore, + sync_oracle: DummyOracle.clone(), + force_authoring: false, + _key_type: PhantomData::, + }; + + let head = Header::new( + 1, + H256::from_low_u64_be(0), + H256::from_low_u64_be(0), + Default::default(), + Default::default() + ); + assert!(worker.claim_slot(&head, 0, &authorities).is_none()); + assert!(worker.claim_slot(&head, 1, &authorities).is_none()); + assert!(worker.claim_slot(&head, 2, &authorities).is_none()); + assert!(worker.claim_slot(&head, 3, &authorities).is_some()); + assert!(worker.claim_slot(&head, 4, &authorities).is_none()); + assert!(worker.claim_slot(&head, 5, &authorities).is_none()); + assert!(worker.claim_slot(&head, 6, &authorities).is_none()); + assert!(worker.claim_slot(&head, 7, &authorities).is_some()); + } } diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml index ddae8f84b7e3ae9edc265df6d3b1f76bcc40e837..ca77b14d0ed0a8cdc8b07dc73d9b604d156b7da2 100644 --- a/client/consensus/babe/Cargo.toml +++ b/client/consensus/babe/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-consensus-babe" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "BABE consensus algorithm for substrate" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-consensus-babe" @@ -14,30 +14,31 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -sp-consensus-babe = { version = "0.8.0-dev", path = "../../../primitives/consensus/babe" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-application-crypto = { version = "2.0.0-dev", path = "../../../primitives/application-crypto" } +sp-consensus-babe = { version = "0.8.0-rc2", path = "../../../primitives/consensus/babe" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-application-crypto = { version = "2.0.0-rc2", path = "../../../primitives/application-crypto" } num-bigint = "0.2.3" num-rational = "0.2.2" num-traits = "0.2.8" serde = { version = "1.0.104", features = ["derive"] } -sp-version = { version = "2.0.0-dev", path = "../../../primitives/version" } -sp-io = { version = "2.0.0-dev", path = "../../../primitives/io" } -sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" } -sp-timestamp = { version = "2.0.0-dev", path = "../../../primitives/timestamp" } -sc-telemetry = { version = "2.0.0-dev", path = "../../telemetry" } -sc-keystore = { version = "2.0.0-dev", path = "../../keystore" } -sc-client-api = { version = "2.0.0-dev", path = "../../api" } -sc-consensus-epochs = { version = "0.8.0-dev", path = "../epochs" } -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -sp-block-builder = { version = "2.0.0-dev", path = "../../../primitives/block-builder" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sp-consensus-vrf = { version = "0.8.0-dev", path = "../../../primitives/consensus/vrf" } -sc-consensus-uncles = { version = "0.8.0-dev", path = "../uncles" } -sc-consensus-slots = { version = "0.8.0-dev", path = "../slots" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -fork-tree = { version = "2.0.0-dev", path = "../../../utils/fork-tree" } +sp-version = { version = "2.0.0-rc2", path = "../../../primitives/version" } +sp-io = { version = "2.0.0-rc2", path = "../../../primitives/io" } +sp-inherents = { version = "2.0.0-rc2", path = "../../../primitives/inherents" } +sp-timestamp = { version = "2.0.0-rc2", path = "../../../primitives/timestamp" } +sc-telemetry = { version = "2.0.0-rc2", path = "../../telemetry" } +sc-keystore = { version = "2.0.0-rc2", path = "../../keystore" } +sc-client-api = { version = "2.0.0-rc2", path = "../../api" } +sc-consensus-epochs = { version = "0.8.0-rc2", path = "../epochs" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +sp-block-builder = { version = "2.0.0-rc2", path = "../../../primitives/block-builder" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sp-consensus-vrf = { version = "0.8.0-rc2", path = "../../../primitives/consensus/vrf" } +sc-consensus-uncles = { version = "0.8.0-rc2", path = "../uncles" } +sc-consensus-slots = { version = "0.8.0-rc2", path = "../slots" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +fork-tree = { version = "2.0.0-rc2", path = "../../../utils/fork-tree" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc2"} futures = "0.3.4" futures-timer = "3.0.1" parking_lot = "0.10.0" @@ -49,13 +50,13 @@ pdqselect = "0.1.0" derive_more = "0.99.2" [dev-dependencies] -sp-keyring = { version = "2.0.0-dev", path = "../../../primitives/keyring" } -sc-executor = { version = "0.8.0-dev", path = "../../executor" } -sc-network = { version = "0.8.0-dev", path = "../../network" } -sc-network-test = { version = "0.8.0-dev", path = "../../network/test" } -sc-service = { version = "0.8.0-dev", default-features = false, path = "../../service" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sc-block-builder = { version = "0.8.0-dev", path = "../../block-builder" } +sp-keyring = { version = "2.0.0-rc2", path = "../../../primitives/keyring" } +sc-executor = { version = "0.8.0-rc2", path = "../../executor" } +sc-network = { version = "0.8.0-rc2", path = "../../network" } +sc-network-test = { version = "0.8.0-rc2", path = "../../network/test" } +sc-service = { version = "0.8.0-rc2", default-features = false, path = "../../service" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../test-utils/runtime/client" } +sc-block-builder = { version = "0.8.0-rc2", path = "../../block-builder" } env_logger = "0.7.0" tempfile = "3.1.0" diff --git a/client/consensus/babe/rpc/Cargo.toml b/client/consensus/babe/rpc/Cargo.toml index 1856ff8bafe63eb945a910cb4b4971ad80a827c7..20f7e487587875ad145b6fcefdaa0125bcac36da 100644 --- a/client/consensus/babe/rpc/Cargo.toml +++ b/client/consensus/babe/rpc/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-consensus-babe-rpc" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "RPC extensions for the BABE consensus algorithm" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,24 +12,27 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sc-consensus-babe = { version = "0.8.0-dev", path = "../" } +sc-consensus-babe = { version = "0.8.0-rc2", path = "../" } +sc-rpc-api = { version = "0.8.0-rc2", path = "../../../rpc-api" } jsonrpc-core = "14.0.3" jsonrpc-core-client = "14.0.5" jsonrpc-derive = "14.0.3" -sp-consensus-babe = { version = "0.8.0-dev", path = "../../../../primitives/consensus/babe" } +sp-consensus-babe = { version = "0.8.0-rc2", path = "../../../../primitives/consensus/babe" } serde = { version = "1.0.104", features=["derive"] } -sp-blockchain = { version = "2.0.0-dev", path = "../../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-dev", path = "../../../../primitives/runtime" } -sc-consensus-epochs = { version = "0.8.0-dev", path = "../../epochs" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../../primitives/runtime" } +sc-consensus-epochs = { version = "0.8.0-rc2", path = "../../epochs" } futures = { version = "0.3.4", features = ["compat"] } derive_more = "0.99.2" -sp-api = { version = "2.0.0-dev", path = "../../../../primitives/api" } -sp-consensus = { version = "0.8.0-dev", path = "../../../../primitives/consensus/common" } -sp-core = { version = "2.0.0-dev", path = "../../../../primitives/core" } -sc-keystore = { version = "2.0.0-dev", path = "../../../keystore" } +sp-api = { version = "2.0.0-rc2", path = "../../../../primitives/api" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../../primitives/consensus/common" } +sp-core = { version = "2.0.0-rc2", path = "../../../../primitives/core" } +sc-keystore = { version = "2.0.0-rc2", path = "../../../keystore" } [dev-dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../../test-utils/runtime/client" } -sp-application-crypto = { version = "2.0.0-dev", path = "../../../../primitives/application-crypto" } -sp-keyring = { version = "2.0.0-dev", path = "../../../../primitives/keyring" } +sc-consensus = { version = "0.8.0-rc2", path = "../../../consensus/common" } +serde_json = "1.0.50" +sp-application-crypto = { version = "2.0.0-rc2", path = "../../../../primitives/application-crypto" } +sp-keyring = { version = "2.0.0-rc2", path = "../../../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../../test-utils/runtime/client" } tempfile = "3.1.0" diff --git a/client/consensus/babe/rpc/src/lib.rs b/client/consensus/babe/rpc/src/lib.rs index fa5421761cea818b8ebef9909458764db0155ad7..8e1282a8d79a7ec634437703eb0404286a2948c9 100644 --- a/client/consensus/babe/rpc/src/lib.rs +++ b/client/consensus/babe/rpc/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! RPC api for babe. @@ -31,8 +33,8 @@ use sp_consensus_babe::{ }; use serde::{Deserialize, Serialize}; use sc_keystore::KeyStorePtr; +use sc_rpc_api::DenyUnsafe; use sp_api::{ProvideRuntimeApi, BlockId}; -use sp_core::crypto::Pair; use sp_runtime::traits::{Block as BlockT, Header as _}; use sp_consensus::{SelectChain, Error as ConsensusError}; use sp_blockchain::{HeaderBackend, HeaderMetadata, Error as BlockChainError}; @@ -49,8 +51,8 @@ pub trait BabeApi { fn epoch_authorship(&self) -> FutureResult>; } -/// Implements the BabeRPC trait for interacting with Babe. -pub struct BabeRPCHandler { +/// Implements the BabeRpc trait for interacting with Babe. +pub struct BabeRpcHandler { /// shared reference to the client. client: Arc, /// shared reference to EpochChanges @@ -61,9 +63,11 @@ pub struct BabeRPCHandler { babe_config: Config, /// The SelectChain strategy select_chain: SC, + /// Whether to deny unsafe calls + deny_unsafe: DenyUnsafe, } -impl BabeRPCHandler { +impl BabeRpcHandler { /// Creates a new instance of the BabeRpc handler. pub fn new( client: Arc, @@ -71,6 +75,7 @@ impl BabeRPCHandler { keystore: KeyStorePtr, babe_config: Config, select_chain: SC, + deny_unsafe: DenyUnsafe, ) -> Self { Self { client, @@ -78,11 +83,12 @@ impl BabeRPCHandler { keystore, babe_config, select_chain, + deny_unsafe, } } } -impl BabeApi for BabeRPCHandler +impl BabeApi for BabeRpcHandler where B: BlockT, C: ProvideRuntimeApi + HeaderBackend + HeaderMetadata + 'static, @@ -91,6 +97,10 @@ impl BabeApi for BabeRPCHandler SC: SelectChain + Clone + 'static, { fn epoch_authorship(&self) -> FutureResult> { + if let Err(err) = self.deny_unsafe.check_if_safe() { + return Box::new(rpc_future::err(err.into())); + } + let ( babe_config, keystore, @@ -116,18 +126,32 @@ impl BabeApi for BabeRPCHandler let mut claims: HashMap = HashMap::new(); + let key_pairs = { + let keystore = keystore.read(); + epoch.authorities.iter() + .enumerate() + .flat_map(|(i, a)| { + keystore + .key_pair::(&a.0) + .ok() + .map(|kp| (kp, i)) + }) + .collect::>() + }; + for slot_number in epoch_start..epoch_end { - let epoch = epoch_data(&shared_epoch, &client, &babe_config, slot_number, &select_chain)?; - if let Some((claim, key)) = authorship::claim_slot(slot_number, &epoch, &keystore) { + if let Some((claim, key)) = + authorship::claim_slot_using_key_pairs(slot_number, &epoch, &key_pairs) + { match claim { PreDigest::Primary { .. } => { - claims.entry(key.public()).or_default().primary.push(slot_number); + claims.entry(key).or_default().primary.push(slot_number); } PreDigest::SecondaryPlain { .. } => { - claims.entry(key.public()).or_default().secondary.push(slot_number); + claims.entry(key).or_default().secondary.push(slot_number); } PreDigest::SecondaryVRF { .. } => { - claims.entry(key.public()).or_default().secondary_vrf.push(slot_number); + claims.entry(key).or_default().secondary_vrf.push(slot_number); }, }; } @@ -163,7 +187,7 @@ pub enum Error { impl From for jsonrpc_core::Error { fn from(error: Error) -> Self { jsonrpc_core::Error { - message: format!("{}", error).into(), + message: format!("{}", error), code: jsonrpc_core::ErrorCode::ServerError(1234), data: None, } @@ -199,7 +223,10 @@ fn epoch_data( mod tests { use super::*; use substrate_test_runtime_client::{ + runtime::Block, + Backend, DefaultTestClientBuilderExt, + TestClient, TestClientBuilderExt, TestClientBuilder, }; @@ -221,8 +248,9 @@ mod tests { (keystore, keystore_path) } - #[test] - fn rpc() { + fn test_babe_rpc_handler( + deny_unsafe: DenyUnsafe + ) -> BabeRpcHandler> { let builder = TestClientBuilder::new(); let (client, longest_chain) = builder.build_with_longest_chain(); let client = Arc::new(client); @@ -234,9 +262,21 @@ mod tests { ).expect("can initialize block-import"); let epoch_changes = link.epoch_changes().clone(); - let select_chain = longest_chain; let keystore = create_temp_keystore::(Ed25519Keyring::Alice).0; - let handler = BabeRPCHandler::new(client.clone(), epoch_changes, keystore, config, select_chain); + + BabeRpcHandler::new( + client.clone(), + epoch_changes, + keystore, + config, + longest_chain, + deny_unsafe, + ) + } + + #[test] + fn epoch_authorship_works() { + let handler = test_babe_rpc_handler(DenyUnsafe::No); let mut io = IoHandler::new(); io.extend_with(BabeApi::to_delegate(handler)); @@ -245,4 +285,19 @@ mod tests { assert_eq!(Some(response.into()), io.handle_request_sync(request)); } + + #[test] + fn epoch_authorship_is_unsafe() { + let handler = test_babe_rpc_handler(DenyUnsafe::Yes); + let mut io = IoHandler::new(); + + io.extend_with(BabeApi::to_delegate(handler)); + let request = r#"{"jsonrpc":"2.0","method":"babe_epochAuthorship","params": [],"id":1}"#; + + let response = io.handle_request_sync(request).unwrap(); + let mut response: serde_json::Value = serde_json::from_str(&response).unwrap(); + let error: RpcError = serde_json::from_value(response["error"].take()).unwrap(); + + assert_eq!(error, RpcError::method_not_found()) + } } diff --git a/client/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs index 1810f9f5bef110ef8860e46f0c199c23aa1b4d68..1a6852c0c186dd35a38a9dadc94c70caea838013 100644 --- a/client/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -124,9 +124,9 @@ pub(super) fn secondary_slot_author( fn claim_secondary_slot( slot_number: SlotNumber, epoch: &Epoch, - keystore: &KeyStorePtr, + key_pairs: &[(AuthorityPair, usize)], author_secondary_vrf: bool, -) -> Option<(PreDigest, AuthorityPair)> { +) -> Option<(PreDigest, AuthorityId)> { let Epoch { authorities, randomness, epoch_index, .. } = epoch; if authorities.is_empty() { @@ -139,14 +139,7 @@ fn claim_secondary_slot( *randomness, )?; - let keystore = keystore.read(); - - for (pair, authority_index) in authorities.iter() - .enumerate() - .flat_map(|(i, a)| { - keystore.key_pair::(&a.0).ok().map(|kp| (kp, i)) - }) - { + for (pair, authority_index) in key_pairs { if pair.public() == *expected_author { let pre_digest = if author_secondary_vrf { let transcript = super::authorship::make_transcript( @@ -161,16 +154,16 @@ fn claim_secondary_slot( slot_number, vrf_output: VRFOutput(s.0.to_output()), vrf_proof: VRFProof(s.1), - authority_index: authority_index as u32, + authority_index: *authority_index as u32, }) } else { PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot_number, - authority_index: authority_index as u32, + authority_index: *authority_index as u32, }) }; - return Some((pre_digest, pair)); + return Some((pre_digest, pair.public())); } } @@ -185,8 +178,27 @@ pub fn claim_slot( slot_number: SlotNumber, epoch: &Epoch, keystore: &KeyStorePtr, -) -> Option<(PreDigest, AuthorityPair)> { - claim_primary_slot(slot_number, epoch, epoch.config.c, keystore) +) -> Option<(PreDigest, AuthorityId)> { + let key_pairs = { + let keystore = keystore.read(); + epoch.authorities.iter() + .enumerate() + .flat_map(|(i, a)| { + keystore.key_pair::(&a.0).ok().map(|kp| (kp, i)) + }) + .collect::>() + }; + claim_slot_using_key_pairs(slot_number, epoch, &key_pairs) +} + +/// Like `claim_slot`, but allows passing an explicit set of key pairs. Useful if we intend +/// to make repeated calls for different slots using the same key pairs. +pub fn claim_slot_using_key_pairs( + slot_number: SlotNumber, + epoch: &Epoch, + key_pairs: &[(AuthorityPair, usize)], +) -> Option<(PreDigest, AuthorityId)> { + claim_primary_slot(slot_number, epoch, epoch.config.c, &key_pairs) .or_else(|| { if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() || epoch.config.allowed_slots.is_secondary_vrf_slots_allowed() @@ -194,7 +206,7 @@ pub fn claim_slot( claim_secondary_slot( slot_number, &epoch, - keystore, + &key_pairs, epoch.config.allowed_slots.is_secondary_vrf_slots_allowed(), ) } else { @@ -216,39 +228,33 @@ fn claim_primary_slot( slot_number: SlotNumber, epoch: &Epoch, c: (u64, u64), - keystore: &KeyStorePtr, -) -> Option<(PreDigest, AuthorityPair)> { + key_pairs: &[(AuthorityPair, usize)], +) -> Option<(PreDigest, AuthorityId)> { let Epoch { authorities, randomness, epoch_index, .. } = epoch; - let keystore = keystore.read(); - for (pair, authority_index) in authorities.iter() - .enumerate() - .flat_map(|(i, a)| { - keystore.key_pair::(&a.0).ok().map(|kp| (kp, i)) - }) - { + for (pair, authority_index) in key_pairs { let transcript = super::authorship::make_transcript(randomness, slot_number, *epoch_index); // Compute the threshold we will use. // // We already checked that authorities contains `key.public()`, so it can't // be empty. Therefore, this division in `calculate_threshold` is safe. - let threshold = super::authorship::calculate_primary_threshold(c, authorities, authority_index); + let threshold = super::authorship::calculate_primary_threshold(c, authorities, *authority_index); - let pre_digest = get_keypair(&pair) + let pre_digest = get_keypair(pair) .vrf_sign_after_check(transcript, |inout| super::authorship::check_primary_threshold(inout, threshold)) .map(|s| { PreDigest::Primary(PrimaryPreDigest { slot_number, vrf_output: VRFOutput(s.0.to_output()), vrf_proof: VRFProof(s.1), - authority_index: authority_index as u32, + authority_index: *authority_index as u32, }) }); // early exit on first successful claim if let Some(pre_digest) = pre_digest { - return Some((pre_digest, pair)); + return Some((pre_digest, pair.public())); } } diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs index 2a3f23981dc3026288259f5c90cf4da17c96b625..4f26568d833430e7fd6454f8f0e58eeb4677688a 100644 --- a/client/consensus/babe/src/aux_schema.rs +++ b/client/consensus/babe/src/aux_schema.rs @@ -112,7 +112,7 @@ pub(crate) fn write_epoch_changes( /// Write the cumulative chain-weight of a block ot aux storage. pub(crate) fn write_block_weight( block_hash: H, - block_weight: &BabeBlockWeight, + block_weight: BabeBlockWeight, write_aux: F, ) -> R where F: FnOnce(&[(Vec, &[u8])]) -> R, diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 678a33cbcc7a6e376aacd2264861eba3ae246462..3d14f0a7bf08d9a497ce0d8a7736ba0ce13c419d 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -76,13 +76,14 @@ pub use sp_consensus_babe::{ pub use sp_consensus::SyncOracle; use std::{ collections::HashMap, sync::Arc, u64, pin::Pin, time::{Instant, Duration}, - any::Any, borrow::Cow + any::Any, borrow::Cow, convert::TryInto, }; -use sp_consensus_babe; use sp_consensus::{ImportResult, CanAuthorWith}; use sp_consensus::import_queue::{ BoxJustificationImport, BoxFinalityProofImport, }; +use sp_core::{crypto::Public, traits::BareCryptoStore}; +use sp_application_crypto::AppKey; use sp_runtime::{ generic::{BlockId, OpaqueDigestItemId}, Justification, traits::{Block as BlockT, Header, DigestItemFor, Zero}, @@ -90,7 +91,6 @@ use sp_runtime::{ use sp_api::{ProvideRuntimeApi, NumberFor}; use sc_keystore::KeyStorePtr; use parking_lot::Mutex; -use sp_core::Pair; use sp_inherents::{InherentDataProviders, InherentData}; use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG}; use sp_consensus::{ @@ -109,6 +109,7 @@ use sp_block_builder::BlockBuilder as BlockBuilderApi; use futures::prelude::*; use log::{debug, info, log, trace, warn}; +use prometheus_endpoint::Registry; use sc_consensus_slots::{ SlotWorker, SlotInfo, SlotCompatible, StorageChanges, CheckedHeader, check_equivocation, }; @@ -186,7 +187,7 @@ impl Epoch { start_slot: slot_number, duration: genesis_config.epoch_length, authorities: genesis_config.genesis_authorities.clone(), - randomness: genesis_config.randomness.clone(), + randomness: genesis_config.randomness, config: BabeEpochConfiguration { c: genesis_config.c, allowed_slots: genesis_config.allowed_slots, @@ -399,7 +400,7 @@ pub fn start_babe(BabeParams { register_babe_inherent_data_provider(&inherent_data_providers, config.slot_duration())?; sc_consensus_uncles::register_uncles_inherent_data_provider( - client.clone(), + client, select_chain.clone(), &inherent_data_providers, )?; @@ -441,7 +442,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork Error: std::error::Error + Send + From + From + 'static, { type EpochData = ViableEpochDescriptor, Epoch>; - type Claim = (PreDigest, AuthorityPair); + type Claim = (PreDigest, AuthorityId); type SyncOracle = SO; type CreateProposer = Pin> + Send + 'static @@ -494,7 +495,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork &self.keystore, ); - if let Some(_) = s { + if s.is_some() { debug!(target: "babe", "Claimed slot {}", slot_number); } @@ -518,12 +519,30 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork StorageChanges, Self::Claim, Self::EpochData, - ) -> sp_consensus::BlockImportParams + Send> { - Box::new(|header, header_hash, body, storage_changes, (_, pair), epoch_descriptor| { + ) -> Result< + sp_consensus::BlockImportParams, + sp_consensus::Error> + Send + 'static> + { + let keystore = self.keystore.clone(); + Box::new(move |header, header_hash, body, storage_changes, (_, public), epoch_descriptor| { // sign the pre-sealed hash of the block and then // add it to a digest item. - let signature = pair.sign(header_hash.as_ref()); - let digest_item = as CompatibleDigestItem>::babe_seal(signature); + let public_type_pair = public.clone().into(); + let public = public.to_raw_vec(); + let signature = keystore.read() + .sign_with( + ::ID, + &public_type_pair, + header_hash.as_ref() + ) + .map_err(|e| sp_consensus::Error::CannotSign( + public.clone(), e.to_string(), + ))?; + let signature: AuthoritySignature = signature.clone().try_into() + .map_err(|_| sp_consensus::Error::InvalidSignature( + signature, public + ))?; + let digest_item = as CompatibleDigestItem>::babe_seal(signature.into()); let mut import_block = BlockImportParams::new(BlockOrigin::Own, header); import_block.post_digests.push(digest_item); @@ -534,7 +553,7 @@ impl sc_consensus_slots::SimpleSlotWorker for BabeWork Box::new(BabeIntermediate:: { epoch_descriptor }) as Box, ); - import_block + Ok(import_block) }) } @@ -796,7 +815,7 @@ impl Verifier for BabeVerifier where // FIXME #1019 in the future, alter this queue to allow deferring of headers let v_params = verification::VerificationParams { header: header.clone(), - pre_digest: Some(pre_digest.clone()), + pre_digest: Some(pre_digest), slot_now: slot_now + 1, epoch: viable_epoch.as_ref(), }; @@ -952,7 +971,7 @@ impl BlockImport for BabeBlockImport>, ) -> Result { let hash = block.post_hash(); - let number = block.header.number().clone(); + let number = *block.header.number(); // early exit if block already in chain, otherwise the check for // epoch changes will error when trying to re-import an epoch change @@ -1133,7 +1152,7 @@ impl BlockImport for BabeBlockImport BlockImport for BabeBlockImport BlockImport for BabeBlockImport( client: Arc, inherent_data_providers: InherentDataProviders, spawner: &impl sp_core::traits::SpawnBlocking, + registry: Option<&Registry>, ) -> ClientResult>> where Inner: BlockImport> + Send + Sync + 'static, @@ -1283,7 +1303,7 @@ pub fn import_queue( register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?; let verifier = BabeVerifier { - client: client.clone(), + client, inherent_data_providers, config: babe_link.config, epoch_changes: babe_link.epoch_changes, @@ -1296,6 +1316,7 @@ pub fn import_queue( justification_import, finality_proof_import, spawner, + registry, )) } diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs index f933251d18e8fb624cc6162d6eda1fa1e56b6f35..ada1332295d46c4fd99ae9948931d234f5fa9b57 100644 --- a/client/consensus/babe/src/tests.rs +++ b/client/consensus/babe/src/tests.rs @@ -21,7 +21,7 @@ #![allow(deprecated)] use super::*; use authorship::claim_slot; - +use sp_core::crypto::Pair; use sp_consensus_babe::{AuthorityPair, SlotNumber, AllowedSlots}; use sc_block_builder::{BlockBuilder, BlockBuilderProvider}; use sp_consensus::{ @@ -159,7 +159,7 @@ impl Proposer for DummyProposer { type Proposal = future::Ready, Error>>; fn propose( - &mut self, + mut self, _: InherentData, pre_digests: DigestFor, _: Duration, diff --git a/client/consensus/common/Cargo.toml b/client/consensus/common/Cargo.toml index dae6f341d134731917851b73c4eb7c9e4838bb2e..256237900b504b96f423a1982a335f535a973c68 100644 --- a/client/consensus/common/Cargo.toml +++ b/client/consensus/common/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-consensus" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Collection of common consensus specific imlementations for Substrate (client)" @@ -12,7 +12,7 @@ description = "Collection of common consensus specific imlementations for Substr targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sc-client-api = { version = "2.0.0-dev", path = "../../api" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } +sc-client-api = { version = "2.0.0-rc2", path = "../../api" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } diff --git a/client/consensus/epochs/Cargo.toml b/client/consensus/epochs/Cargo.toml index de14b5c6be617ff01038abbaeb5c833aa81d05d8..969d4f7d2c5133b58d7a09a69b10b640d62d5aa9 100644 --- a/client/consensus/epochs/Cargo.toml +++ b/client/consensus/epochs/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-consensus-epochs" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Generic epochs-based utilities for consensus" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } parking_lot = "0.10.0" -fork-tree = { version = "2.0.0-dev", path = "../../../utils/fork-tree" } -sp-runtime = { path = "../../../primitives/runtime" , version = "2.0.0-dev"} -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sc-client-api = { path = "../../api" , version = "2.0.0-dev"} +fork-tree = { version = "2.0.0-rc2", path = "../../../utils/fork-tree" } +sp-runtime = { path = "../../../primitives/runtime" , version = "2.0.0-rc2"} +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sc-client-api = { path = "../../api" , version = "2.0.0-rc2"} diff --git a/client/consensus/manual-seal/Cargo.toml b/client/consensus/manual-seal/Cargo.toml index b0a3c2bd72b56cd087dbd879f0e58dbdab5972ad..de2bf68d767456159df28f154e157a01010f7de5 100644 --- a/client/consensus/manual-seal/Cargo.toml +++ b/client/consensus/manual-seal/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-consensus-manual-seal" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Manual sealing engine for Substrate" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -22,19 +22,20 @@ parking_lot = "0.10.0" serde = { version = "1.0", features=["derive"] } assert_matches = "1.3.0" -sc-client-api = { path = "../../../client/api" , version = "2.0.0-dev"} -sc-transaction-pool = { path = "../../transaction-pool" , version = "2.0.0-dev"} -sp-blockchain = { path = "../../../primitives/blockchain" , version = "2.0.0-dev"} -sp-consensus = { package = "sp-consensus", path = "../../../primitives/consensus/common" , version = "0.8.0-dev"} -sp-inherents = { path = "../../../primitives/inherents" , version = "2.0.0-dev"} -sp-runtime = { path = "../../../primitives/runtime" , version = "2.0.0-dev"} -sp-core = { path = "../../../primitives/core" , version = "2.0.0-dev"} -sp-transaction-pool = { path = "../../../primitives/transaction-pool" , version = "2.0.0-dev"} +sc-client-api = { path = "../../../client/api", version = "2.0.0-rc2" } +sc-transaction-pool = { path = "../../transaction-pool", version = "2.0.0-rc2" } +sp-blockchain = { path = "../../../primitives/blockchain", version = "2.0.0-rc2" } +sp-consensus = { package = "sp-consensus", path = "../../../primitives/consensus/common", version = "0.8.0-rc2" } +sp-inherents = { path = "../../../primitives/inherents", version = "2.0.0-rc2" } +sp-runtime = { path = "../../../primitives/runtime", version = "2.0.0-rc2" } +sp-core = { path = "../../../primitives/core", version = "2.0.0-rc2" } +sp-transaction-pool = { path = "../../../primitives/transaction-pool", version = "2.0.0-rc2" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc2" } [dev-dependencies] -sc-basic-authorship = { path = "../../basic-authorship" , version = "0.8.0-dev"} -substrate-test-runtime-client = { path = "../../../test-utils/runtime/client" , version = "2.0.0-dev"} -substrate-test-runtime-transaction-pool = { path = "../../../test-utils/runtime/transaction-pool" , version = "2.0.0-dev"} +sc-basic-authorship = { path = "../../basic-authorship", version = "0.8.0-rc2" } +substrate-test-runtime-client = { path = "../../../test-utils/runtime/client", version = "2.0.0-rc2" } +substrate-test-runtime-transaction-pool = { path = "../../../test-utils/runtime/transaction-pool", version = "2.0.0-rc2" } tokio = { version = "0.2", features = ["rt-core", "macros"] } env_logger = "0.7.0" tempfile = "3.1.0" diff --git a/client/consensus/manual-seal/src/error.rs b/client/consensus/manual-seal/src/error.rs index d6ee9f176772128a8f597e91b944cbca3e978a0c..2411a839b027ceb51b6e927f5c09ad030571231a 100644 --- a/client/consensus/manual-seal/src/error.rs +++ b/client/consensus/manual-seal/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! A manual sealing engine: the engine listens for rpc calls to seal blocks and create forks. //! This is suitable for a testing environment. diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index c59bd61a973cf94fff32edd2684d7d952d40b070..26f493d5d220cacd7793030b650adedab1ea7d35 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! A manual sealing engine: the engine listens for rpc calls to seal blocks and create forks. //! This is suitable for a testing environment. @@ -28,6 +30,7 @@ use sp_runtime::{traits::Block as BlockT, Justification}; use sc_client_api::backend::{Backend as ClientBackend, Finalizer}; use sc_transaction_pool::txpool; use std::{sync::Arc, marker::PhantomData}; +use prometheus_endpoint::Registry; mod error; mod finalize_block; @@ -68,6 +71,7 @@ impl Verifier for ManualSealVerifier { pub fn import_queue( block_import: BoxBlockImport, spawner: &impl sp_core::traits::SpawnBlocking, + registry: Option<&Registry>, ) -> BasicQueue where Block: BlockT, @@ -79,6 +83,7 @@ pub fn import_queue( None, None, spawner, + registry, ) } @@ -221,7 +226,8 @@ mod tests { let pool = Arc::new(BasicPool::new(Options::default(), api(), None).0); let env = ProposerFactory::new( client.clone(), - pool.clone() + pool.clone(), + None, ); // this test checks that blocks are created as soon as transactions are imported into the pool. let (sender, receiver) = futures::channel::oneshot::channel(); @@ -285,7 +291,8 @@ mod tests { let pool = Arc::new(BasicPool::new(Options::default(), api(), None).0); let env = ProposerFactory::new( client.clone(), - pool.clone() + pool.clone(), + None, ); // this test checks that blocks are created as soon as an engine command is sent over the stream. let (mut sink, stream) = futures::channel::mpsc::channel(1024); @@ -354,6 +361,7 @@ mod tests { let env = ProposerFactory::new( client.clone(), pool.clone(), + None, ); // this test checks that blocks are created as soon as an engine command is sent over the stream. let (mut sink, stream) = futures::channel::mpsc::channel(1024); diff --git a/client/consensus/manual-seal/src/seal_new_block.rs b/client/consensus/manual-seal/src/seal_new_block.rs index 88b58ef4cc2b39cbbe3af1209e54408390e074ef..a608c978e6edb21f699318d7c018ca91a6f08903 100644 --- a/client/consensus/manual-seal/src/seal_new_block.rs +++ b/client/consensus/manual-seal/src/seal_new_block.rs @@ -108,7 +108,7 @@ pub async fn seal_new_block( None => select_chain.best_chain()? }; - let mut proposer = env.init(&header) + let proposer = env.init(&header) .map_err(|err| Error::StringError(format!("{}", err))).await?; let id = inherent_data_provider.create_inherent_data()?; let inherents_len = id.len(); diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml index 0c1cc9c12cd5f61068ed16d7e980c7f03feb1260..c6eab297814e6052b2b1be0e393de02fe4f564ea 100644 --- a/client/consensus/pow/Cargo.toml +++ b/client/consensus/pow/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-consensus-pow" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "PoW consensus algorithm for substrate" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -13,16 +13,17 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -sc-client-api = { version = "2.0.0-dev", path = "../../api" } -sp-block-builder = { version = "2.0.0-dev", path = "../../../primitives/block-builder" } -sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" } -sp-consensus-pow = { version = "0.8.0-dev", path = "../../../primitives/consensus/pow" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +sc-client-api = { version = "2.0.0-rc2", path = "../../api" } +sp-block-builder = { version = "2.0.0-rc2", path = "../../../primitives/block-builder" } +sp-inherents = { version = "2.0.0-rc2", path = "../../../primitives/inherents" } +sp-consensus-pow = { version = "0.8.0-rc2", path = "../../../primitives/consensus/pow" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } log = "0.4.8" futures = { version = "0.3.1", features = ["compat"] } -sp-timestamp = { version = "2.0.0-dev", path = "../../../primitives/timestamp" } +sp-timestamp = { version = "2.0.0-rc2", path = "../../../primitives/timestamp" } derive_more = "0.99.2" +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc2"} diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs index 8d17071f4c15c3f9ec4817ec8058e666b82fe909..24a8b6328120858a9d8593a9a178b3b98ff3269a 100644 --- a/client/consensus/pow/src/lib.rs +++ b/client/consensus/pow/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Proof of work consensus for Substrate. //! @@ -53,6 +55,7 @@ use sp_consensus::import_queue::{ BoxBlockImport, BasicQueue, Verifier, BoxJustificationImport, BoxFinalityProofImport, }; use codec::{Encode, Decode}; +use prometheus_endpoint::Registry; use sc_client_api; use log::*; use sp_timestamp::{InherentError as TIError, TimestampInherentData}; @@ -464,6 +467,7 @@ pub fn import_queue( algorithm: Algorithm, inherent_data_providers: InherentDataProviders, spawner: &impl sp_core::traits::SpawnBlocking, + registry: Option<&Registry>, ) -> Result< PowImportQueue, sp_consensus::Error @@ -482,6 +486,7 @@ pub fn import_queue( justification_import, finality_proof_import, spawner, + registry, )) } @@ -605,7 +610,7 @@ fn mine_loop( continue 'outer } - let mut proposer = futures::executor::block_on(env.init(&best_header)) + let proposer = futures::executor::block_on(env.init(&best_header)) .map_err(|e| Error::Environment(format!("{:?}", e)))?; let inherent_data = inherent_data_providers diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml index d39d5382557ddc84c6a3f3a1d232ea191c0d0eb8..6cc4a658e3748a42910fedac9f12da9370d3f878 100644 --- a/client/consensus/slots/Cargo.toml +++ b/client/consensus/slots/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "sc-consensus-slots" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Generic slots-based utilities for consensus" edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -14,19 +14,20 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-client-api = { version = "2.0.0-dev", path = "../../api" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-state-machine = { version = "0.8.0-dev", path = "../../../primitives/state-machine" } -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -sc-telemetry = { version = "2.0.0-dev", path = "../../telemetry" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" } +sc-client-api = { version = "2.0.0-rc2", path = "../../api" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-application-crypto = { version = "2.0.0-rc2", path = "../../../primitives/application-crypto" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../../primitives/state-machine" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +sc-telemetry = { version = "2.0.0-rc2", path = "../../telemetry" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0-rc2", path = "../../../primitives/inherents" } futures = "0.3.4" futures-timer = "3.0.1" parking_lot = "0.10.0" log = "0.4.8" [dev-dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../test-utils/runtime/client" } diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs index 611e0fbb7b8053675c7b385fccbe03747eaa00a4..fe1c6bab7b579e5c383b2deefbbe300632887b58 100644 --- a/client/consensus/slots/src/lib.rs +++ b/client/consensus/slots/src/lib.rs @@ -20,7 +20,6 @@ //! time during which certain events can and/or must occur. This crate //! provides generic functionality for slots. -#![deny(warnings)] #![forbid(unsafe_code, missing_docs)] mod slots; @@ -121,11 +120,10 @@ pub trait SimpleSlotWorker { StorageChanges<>::Transaction, B>, Self::Claim, Self::EpochData, - ) -> sp_consensus::BlockImportParams< - B, - >::Transaction - > - + Send + ) -> Result< + sp_consensus::BlockImportParams>::Transaction>, + sp_consensus::Error + > + Send + 'static >; /// Whether to force authoring if offline. @@ -240,7 +238,7 @@ pub trait SimpleSlotWorker { let logs = self.pre_digest_data(slot_number, &claim); // deadline our production to approx. the end of the slot - let proposing = awaiting_proposer.and_then(move |mut proposer| proposer.propose( + let proposing = awaiting_proposer.and_then(move |proposer| proposer.propose( slot_info.inherent_data, sp_runtime::generic::Digest { logs, @@ -273,7 +271,7 @@ pub trait SimpleSlotWorker { let block_import = self.block_import(); let logging_target = self.logging_target(); - Box::pin(proposal_work.map_ok(move |(proposal, claim)| { + Box::pin(proposal_work.and_then(move |(proposal, claim)| { let (header, body) = proposal.block.deconstruct(); let header_num = *header.number(); let header_hash = header.hash(); @@ -288,6 +286,11 @@ pub trait SimpleSlotWorker { epoch_data, ); + let block_import_params = match block_import_params { + Ok(params) => params, + Err(e) => return future::err(e), + }; + info!( "🔖 Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", header_num, @@ -312,6 +315,7 @@ pub trait SimpleSlotWorker { "hash" => ?parent_hash, "err" => ?err, ); } + future::ready(Ok(())) })) } } diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml index 019c933a20e0cc24ef3cbd0e284afce66dd379cc..e01e0720b43b0930fd4aeb14809aee7b11b2a061 100644 --- a/client/consensus/uncles/Cargo.toml +++ b/client/consensus/uncles/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-consensus-uncles" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Generic uncle inclusion utilities for consensus" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,10 +12,10 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sc-client-api = { version = "2.0.0-dev", path = "../../api" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-authorship = { version = "2.0.0-dev", path = "../../../primitives/authorship" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sp-inherents = { version = "2.0.0-dev", path = "../../../primitives/inherents" } +sc-client-api = { version = "2.0.0-rc2", path = "../../api" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-authorship = { version = "2.0.0-rc2", path = "../../../primitives/authorship" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0-rc2", path = "../../../primitives/inherents" } log = "0.4.8" diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index 2df1836850cd7957145198f55afc889ed2a3ac15..32e6f9daa2be3a493978de5b4adc43b5910098ba 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-client-db" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Client backend that uses RocksDB database as storage." @@ -14,34 +14,34 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] parking_lot = "0.10.0" log = "0.4.8" -kvdb = "0.5.0" -kvdb-rocksdb = { version = "0.7", optional = true } -kvdb-memorydb = "0.5.0" +kvdb = "0.6.0" +kvdb-rocksdb = { version = "0.8", optional = true } +kvdb-memorydb = "0.6.0" linked-hash-map = "0.5.2" hash-db = "0.15.2" parity-util-mem = { version = "0.6.1", default-features = false, features = ["std"] } codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } blake2-rfc = "0.2.18" -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } -sc-executor = { version = "0.8.0-dev", path = "../executor" } -sc-state-db = { version = "0.8.0-dev", path = "../state-db" } -sp-trie = { version = "2.0.0-dev", path = "../../primitives/trie" } -sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sp-database = { version = "2.0.0-dev", path = "../../primitives/database" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } +sc-executor = { version = "0.8.0-rc2", path = "../executor" } +sc-state-db = { version = "0.8.0-rc2", path = "../state-db" } +sp-trie = { version = "2.0.0-rc2", path = "../../primitives/trie" } +sp-consensus = { version = "0.8.0-rc2", path = "../../primitives/consensus/common" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sp-database = { version = "2.0.0-rc2", path = "../../primitives/database" } parity-db = { version = "0.1.2", optional = true } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-dev", path = "../../utils/prometheus" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-rc2", path = "../../utils/prometheus" } [dev-dependencies] -sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sp-keyring = { version = "2.0.0-rc2", path = "../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } env_logger = "0.7.0" quickcheck = "0.9" -kvdb-rocksdb = "0.7" +kvdb-rocksdb = "0.8" tempfile = "3" [features] diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index 9d6f595498bd0e3f5a4f287090b25485142c0bb0..99ce1edae00c5dfb2eca3a62a133b872f9af0cd0 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! State backend that's useful for benchmarking @@ -77,12 +79,12 @@ impl BenchmarkingState { }; state.reopen()?; - let child_delta = genesis.children_default.into_iter().map(|(_storage_key, child_content)| ( - child_content.child_info, - child_content.data.into_iter().map(|(k, v)| (k, Some(v))), + let child_delta = genesis.children_default.iter().map(|(_storage_key, child_content)| ( + &child_content.child_info, + child_content.data.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))), )); let (root, transaction): (B::Hash, _) = state.state.borrow_mut().as_mut().unwrap().full_storage_root( - genesis.top.into_iter().map(|(k, v)| (k, Some(v))), + genesis.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))), child_delta, ); state.genesis = transaction.clone().drain(); @@ -191,19 +193,18 @@ impl StateBackend> for BenchmarkingState { } } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) where - I: IntoIterator, Option>)> - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (B::Hash, Self::Transaction) where B::Hash: Ord { self.state.borrow().as_ref().map_or(Default::default(), |s| s.storage_root(delta)) } - fn child_storage_root( + fn child_storage_root<'a>( &self, child_info: &ChildInfo, - delta: I, - ) -> (B::Hash, bool, Self::Transaction) where - I: IntoIterator, Option>)>, - { + delta: impl Iterator)>, + ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord { self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_storage_root(child_info, delta)) } diff --git a/client/db/src/cache/list_cache.rs b/client/db/src/cache/list_cache.rs index f3a8171342c9158997cb1dd08e3d90aa03e94b8a..0856350fb091069ee5a33db055a6ba256ed3d26d 100644 --- a/client/db/src/cache/list_cache.rs +++ b/client/db/src/cache/list_cache.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! List-based cache. //! @@ -1764,7 +1766,7 @@ pub mod tests { Some(Entry { valid_from: test_id(20), value: 20 }), vec![5, 6].into_iter().collect(), ))); - + assert_eq!( ops.operations, vec![CommitOperation::BlockFinalized( diff --git a/client/db/src/cache/list_entry.rs b/client/db/src/cache/list_entry.rs index e18434329079b68d1bc4a13af4a06698dd88d9d8..565a62cff4f2d9643624d0836bb39e10f35b2027 100644 --- a/client/db/src/cache/list_entry.rs +++ b/client/db/src/cache/list_entry.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! List-cache storage entries. diff --git a/client/db/src/cache/list_storage.rs b/client/db/src/cache/list_storage.rs index 07cd9fb866359b377ce7bc35f97efcb208c3adf5..377d744effa60faf57521d2a490852ef757ce1bf 100644 --- a/client/db/src/cache/list_storage.rs +++ b/client/db/src/cache/list_storage.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! List-cache storage definition and implementation. diff --git a/client/db/src/cache/mod.rs b/client/db/src/cache/mod.rs index f2d357ca9ece86e86a7ead75b5d2d46e8e4d5905..2b7cd2e62076e42e7534b7609be709687ae19962 100644 --- a/client/db/src/cache/mod.rs +++ b/client/db/src/cache/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! DB-backed cache of blockchain data. diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index d1eb10ea31646e9cccf3d3c46cad6992fc7a5f3e..9fb8f3c8c0454cf0b111d2022d39b27231162528 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Client backend that is backed by a database. //! @@ -210,21 +212,18 @@ impl StateBackend> for RefTrackingState { self.state.for_child_keys_with_prefix(child_info, prefix, f) } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) - where - I: IntoIterator, Option>)> - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (B::Hash, Self::Transaction) where B::Hash: Ord { self.state.storage_root(delta) } - fn child_storage_root( + fn child_storage_root<'a>( &self, child_info: &ChildInfo, - delta: I, - ) -> (B::Hash, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - { + delta: impl Iterator)>, + ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord { self.state.child_storage_root(child_info, delta) } @@ -603,26 +602,25 @@ impl sc_client_api::backend::BlockImportOperation for Bloc &mut self, storage: Storage, ) -> ClientResult { - - if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { + if storage.top.keys().any(|k| well_known_keys::is_child_storage_key(&k)) { return Err(sp_blockchain::Error::GenesisInvalid.into()); } - let child_delta = storage.children_default.into_iter().map(|(_storage_key, child_content)|( - child_content.child_info, - child_content.data.into_iter().map(|(k, v)| (k, Some(v))), + let child_delta = storage.children_default.iter().map(|(_storage_key, child_content)|( + &child_content.child_info, + child_content.data.iter().map(|(k, v)| (&k[..], Some(&v[..]))), )); let mut changes_trie_config: Option = None; let (root, transaction) = self.old_state.full_storage_root( - storage.top.into_iter().map(|(k, v)| { - if k == well_known_keys::CHANGES_TRIE_CONFIG { + storage.top.iter().map(|(k, v)| { + if &k[..] == well_known_keys::CHANGES_TRIE_CONFIG { changes_trie_config = Some( Decode::decode(&mut &v[..]) .expect("changes trie configuration is encoded properly at genesis") ); } - (k, Some(v)) + (&k[..], Some(&v[..])) }), child_delta ); @@ -1808,13 +1806,12 @@ pub(crate) mod tests { header.state_root = op.old_state.storage_root(storage .iter() - .cloned() - .map(|(x, y)| (x, Some(y))) + .map(|(x, y)| (&x[..], Some(&y[..]))) ).0.into(); let hash = header.hash(); op.reset_storage(Storage { - top: storage.iter().cloned().collect(), + top: storage.into_iter().collect(), children_default: Default::default(), }).unwrap(); op.set_block_data( @@ -1851,7 +1848,10 @@ pub(crate) mod tests { (vec![5, 5, 5], Some(vec![4, 5, 6])), ]; - let (root, overlay) = op.old_state.storage_root(storage.iter().cloned()); + let (root, overlay) = op.old_state.storage_root( + storage.iter() + .map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..]))) + ); op.update_db_storage(overlay).unwrap(); header.state_root = root.into(); @@ -1890,17 +1890,11 @@ pub(crate) mod tests { extrinsics_root: Default::default(), }; - let storage: Vec<(_, _)> = vec![]; - - header.state_root = op.old_state.storage_root(storage - .iter() - .cloned() - .map(|(x, y)| (x, Some(y))) - ).0.into(); + header.state_root = op.old_state.storage_root(std::iter::empty()).0.into(); let hash = header.hash(); op.reset_storage(Storage { - top: storage.iter().cloned().collect(), + top: Default::default(), children_default: Default::default(), }).unwrap(); diff --git a/client/db/src/light.rs b/client/db/src/light.rs index 849b439424d30d173d7d16263d4479424cb1dad9..f115ac9599e8dca6871751af22e343441300bfe6 100644 --- a/client/db/src/light.rs +++ b/client/db/src/light.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! RocksDB-based light client blockchain storage. diff --git a/client/db/src/offchain.rs b/client/db/src/offchain.rs index 8c58d5f42c391293268268eedd60859df0e54766..f6a0925a086171002e3479cc2206559be09a9250 100644 --- a/client/db/src/offchain.rs +++ b/client/db/src/offchain.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! RocksDB-based offchain workers local storage. @@ -65,6 +67,14 @@ impl sp_core::offchain::OffchainStorage for LocalStorage { self.db.commit(tx); } + fn remove(&mut self, prefix: &[u8], key: &[u8]) { + let key: Vec = prefix.iter().chain(key).cloned().collect(); + let mut tx = Transaction::new(); + tx.remove(columns::OFFCHAIN, &key); + + self.db.commit(tx); + } + fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { let key: Vec = prefix.iter().chain(key).cloned().collect(); self.db.get(columns::OFFCHAIN, &key) diff --git a/client/db/src/parity_db.rs b/client/db/src/parity_db.rs index 7333f70e25f36ae0418e43d5fd4e8ebff8fff496..ea25aaa9f89e36c80a9227c4367fc067bc0a6f98 100644 --- a/client/db/src/parity_db.rs +++ b/client/db/src/parity_db.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . /// A `Database` adapter for parity-db. use sp_database::{Database, Change, Transaction, ColumnId}; diff --git a/client/db/src/stats.rs b/client/db/src/stats.rs index 8bc93b5b644cf985ff81fa0aaa0c0154c64eeaa0..8d208024b4bb29a1f064dfc00f3fa14b8df07f85 100644 --- a/client/db/src/stats.rs +++ b/client/db/src/stats.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Database usage statistics diff --git a/client/db/src/storage_cache.rs b/client/db/src/storage_cache.rs index 66ac74afa4f2a1d00458c58eeeda86e0b19e0f51..434b301ed6240e94539cbf5d3c06265231639039 100644 --- a/client/db/src/storage_cache.rs +++ b/client/db/src/storage_cache.rs @@ -621,21 +621,18 @@ impl>, B: BlockT> StateBackend> for Cachin self.state.for_child_keys_with_prefix(child_info, prefix, f) } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) - where - I: IntoIterator, Option>)>, - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (B::Hash, Self::Transaction) where B::Hash: Ord { self.state.storage_root(delta) } - fn child_storage_root( + fn child_storage_root<'a>( &self, child_info: &ChildInfo, - delta: I, - ) -> (B::Hash, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - { + delta: impl Iterator)>, + ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord { self.state.child_storage_root(child_info, delta) } @@ -806,21 +803,18 @@ impl>, B: BlockT> StateBackend> for Syncin self.caching_state().for_child_keys_with_prefix(child_info, prefix, f) } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) - where - I: IntoIterator, Option>)>, - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (B::Hash, Self::Transaction) where B::Hash: Ord { self.caching_state().storage_root(delta) } - fn child_storage_root( + fn child_storage_root<'a>( &self, child_info: &ChildInfo, - delta: I, - ) -> (B::Hash, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - { + delta: impl Iterator)>, + ) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord { self.caching_state().child_storage_root(child_info, delta) } diff --git a/client/db/src/subdb.rs b/client/db/src/subdb.rs index 2e436aa2c92c870dfe60117ec50b61c6213094f3..2f72632b045622fcd035e50f7560c2c4b0fe753c 100644 --- a/client/db/src/subdb.rs +++ b/client/db/src/subdb.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . /// A `Database` adapter for subdb. use sp_database::{self, ColumnId}; diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs index d40abcab6693c6b0cb8cce5820256ae95bccd4ab..80b08b3a6e59c20779213637c015fc2438e7088b 100644 --- a/client/db/src/utils.rs +++ b/client/db/src/utils.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Db-based backend utility structures and functions, used by both //! full and light storages. @@ -210,6 +212,12 @@ pub fn open_database( config: &DatabaseSettings, db_type: DatabaseType, ) -> sp_blockchain::Result>> { + let db_open_error = |feat| Err( + sp_blockchain::Error::Backend( + format!("`{}` feature not enabled, database can not be opened", feat), + ), + ); + let db: Arc> = match &config.source { #[cfg(any(feature = "kvdb-rocksdb", test))] DatabaseSettingsSrc::RocksDb { path, cache_size } => { @@ -247,21 +255,29 @@ pub fn open_database( .map_err(|err| sp_blockchain::Error::Backend(format!("{}", err)))?; sp_database::as_database(db) }, + #[cfg(not(any(feature = "kvdb-rocksdb", test)))] + DatabaseSettingsSrc::RocksDb { .. } => { + return db_open_error("kvdb-rocksdb"); + }, #[cfg(feature = "subdb")] DatabaseSettingsSrc::SubDb { path } => { crate::subdb::open(&path, NUM_COLUMNS) .map_err(|e| sp_blockchain::Error::Backend(format!("{:?}", e)))? }, + #[cfg(not(feature = "subdb"))] + DatabaseSettingsSrc::SubDb { .. } => { + return db_open_error("subdb"); + }, #[cfg(feature = "parity-db")] DatabaseSettingsSrc::ParityDb { path } => { crate::parity_db::open(&path) .map_err(|e| sp_blockchain::Error::Backend(format!("{:?}", e)))? }, - DatabaseSettingsSrc::Custom(db) => db.clone(), - _ => { - let msg = "Trying to open a unsupported database".into(); - return Err(sp_blockchain::Error::Backend(msg)); + #[cfg(not(feature = "parity-db"))] + DatabaseSettingsSrc::ParityDb { .. } => { + return db_open_error("parity-db"); }, + DatabaseSettingsSrc::Custom(db) => db.clone(), }; check_database_type(&*db, db_type)?; diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index ef1b24ea7112615f21cc48c6569e2adc54cf8d40..7290538f487b93b12f87219aaa94ca11f1493ba9 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-executor" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "A crate that provides means of executing/dispatching calls into the runtime." @@ -15,22 +15,22 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] derive_more = "0.99.2" codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-trie = { version = "2.0.0-dev", path = "../../primitives/trie" } -sp-serializer = { version = "2.0.0-dev", path = "../../primitives/serializer" } -sp-version = { version = "2.0.0-dev", path = "../../primitives/version" } -sp-panic-handler = { version = "2.0.0-dev", path = "../../primitives/panic-handler" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-trie = { version = "2.0.0-rc2", path = "../../primitives/trie" } +sp-serializer = { version = "2.0.0-rc2", path = "../../primitives/serializer" } +sp-version = { version = "2.0.0-rc2", path = "../../primitives/version" } +sp-panic-handler = { version = "2.0.0-rc2", path = "../../primitives/panic-handler" } wasmi = "0.6.2" parity-wasm = "0.41.0" lazy_static = "1.4.0" -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } -sp-wasm-interface = { version = "2.0.0-dev", path = "../../primitives/wasm-interface" } -sp-runtime-interface = { version = "2.0.0-dev", path = "../../primitives/runtime-interface" } -sp-externalities = { version = "0.8.0-dev", path = "../../primitives/externalities" } -sc-executor-common = { version = "0.8.0-dev", path = "common" } -sc-executor-wasmi = { version = "0.8.0-dev", path = "wasmi" } -sc-executor-wasmtime = { version = "0.8.0-dev", path = "wasmtime", optional = true } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } +sp-wasm-interface = { version = "2.0.0-rc2", path = "../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0-rc2", path = "../../primitives/runtime-interface" } +sp-externalities = { version = "0.8.0-rc2", path = "../../primitives/externalities" } +sc-executor-common = { version = "0.8.0-rc2", path = "common" } +sc-executor-wasmi = { version = "0.8.0-rc2", path = "wasmi" } +sc-executor-wasmtime = { version = "0.8.0-rc2", path = "wasmtime", optional = true } parking_lot = "0.10.0" log = "0.4.8" libsecp256k1 = "0.3.4" @@ -39,11 +39,11 @@ libsecp256k1 = "0.3.4" assert_matches = "1.3.0" wabt = "0.9.2" hex-literal = "0.2.1" -sc-runtime-test = { version = "2.0.0-dev", path = "runtime-test" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../test-utils/runtime" } -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } +sc-runtime-test = { version = "2.0.0-rc2", path = "runtime-test" } +substrate-test-runtime = { version = "2.0.0-rc2", path = "../../test-utils/runtime" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } test-case = "0.3.3" -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } [features] default = [ "std" ] diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml index c27ed8db0ae885bc22ef5377d975164e83bc57a9..f5d3c38c6111d61e1966d12b5baf3fd4e4443afe 100644 --- a/client/executor/common/Cargo.toml +++ b/client/executor/common/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-executor-common" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "A set of common definitions that are needed for defining execution engines." @@ -18,11 +18,11 @@ derive_more = "0.99.2" parity-wasm = "0.41.0" codec = { package = "parity-scale-codec", version = "1.3.0" } wasmi = "0.6.2" -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-allocator = { version = "2.0.0-dev", path = "../../../primitives/allocator" } -sp-wasm-interface = { version = "2.0.0-dev", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "2.0.0-dev", path = "../../../primitives/runtime-interface" } -sp-serializer = { version = "2.0.0-dev", path = "../../../primitives/serializer" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-allocator = { version = "2.0.0-rc2", path = "../../../primitives/allocator" } +sp-wasm-interface = { version = "2.0.0-rc2", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0-rc2", path = "../../../primitives/runtime-interface" } +sp-serializer = { version = "2.0.0-rc2", path = "../../../primitives/serializer" } [features] default = [] diff --git a/client/executor/common/src/error.rs b/client/executor/common/src/error.rs index 66d520e942411d01c540bd64f7bde4147be28c74..04850e6f8dd7e34b1b438ec1a4c58f6ed026eb5b 100644 --- a/client/executor/common/src/error.rs +++ b/client/executor/common/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Rust executor possible errors. diff --git a/client/executor/common/src/sandbox.rs b/client/executor/common/src/sandbox.rs index ccfdc2f3e0e28c2e8b6a1b1734ee8be450b088ff..b2c35b758271829c8771034da08aee46c52dd3db 100644 --- a/client/executor/common/src/sandbox.rs +++ b/client/executor/common/src/sandbox.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! This module implements sandboxing support in the runtime. //! @@ -236,21 +238,33 @@ impl<'a, FE: SandboxCapabilities + 'a> Externals for GuestExternals<'a, FE> { .supervisor_externals .allocate_memory(invoke_args_len) .map_err(|_| trap("Can't allocate memory in supervisor for the arguments"))?; - self + + let deallocate = |this: &mut GuestExternals, ptr, fail_msg| { + this + .supervisor_externals + .deallocate_memory(ptr) + .map_err(|_| trap(fail_msg)) + }; + + if self .supervisor_externals .write_memory(invoke_args_ptr, &invoke_args_data) - .map_err(|_| trap("Can't write invoke args into memory"))?; + .is_err() + { + deallocate(self, invoke_args_ptr, "Failed dealloction after failed write of invoke arguments")?; + return Err(trap("Can't write invoke args into memory")); + } + let result = self.supervisor_externals.invoke( &self.sandbox_instance.dispatch_thunk, invoke_args_ptr, invoke_args_len, state, func_idx, - )?; - self - .supervisor_externals - .deallocate_memory(invoke_args_ptr) - .map_err(|_| trap("Can't deallocate memory for dispatch thunk's invoke arguments"))?; + ); + + deallocate(self, invoke_args_ptr, "Can't deallocate memory for dispatch thunk's invoke arguments")?; + let result = result?; // dispatch_thunk returns pointer to serialized arguments. // Unpack pointer and len of the serialized result data. @@ -264,12 +278,11 @@ impl<'a, FE: SandboxCapabilities + 'a> Externals for GuestExternals<'a, FE> { let serialized_result_val = self.supervisor_externals .read_memory(serialized_result_val_ptr, serialized_result_val_len) - .map_err(|_| trap("Can't read the serialized result from dispatch thunk"))?; - self.supervisor_externals - .deallocate_memory(serialized_result_val_ptr) - .map_err(|_| trap("Can't deallocate memory for dispatch thunk's result"))?; + .map_err(|_| trap("Can't read the serialized result from dispatch thunk")); - deserialize_result(&serialized_result_val) + deallocate(self, serialized_result_val_ptr, "Can't deallocate memory for dispatch thunk's result") + .and_then(|_| serialized_result_val) + .and_then(|serialized_result_val| deserialize_result(&serialized_result_val)) } } diff --git a/client/executor/common/src/util.rs b/client/executor/common/src/util.rs index 149db13bc0768a92408f8b1af1a05d518a8ae97d..92a48e14018143944dae245abddb1db481ce4021 100644 --- a/client/executor/common/src/util.rs +++ b/client/executor/common/src/util.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! A set of utilities for resetting a wasm instance to its initial state. diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml index b8ae805192d9408c474febd8d6d266df2d81b7b2..5700ee2f98b60ebd3480d5e95eb4d61e748fca59 100644 --- a/client/executor/runtime-test/Cargo.toml +++ b/client/executor/runtime-test/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-runtime-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -13,12 +13,12 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/io" } -sp-sandbox = { version = "0.8.0-dev", default-features = false, path = "../../../primitives/sandbox" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-allocator = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/allocator" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/io" } +sp-sandbox = { version = "0.8.0-rc2", default-features = false, path = "../../../primitives/sandbox" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/runtime" } +sp-allocator = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/allocator" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } diff --git a/client/executor/runtime-test/build.rs b/client/executor/runtime-test/build.rs index 647b4768141d2203155bf5325f9ff87f7d9c2446..c5f1f2402bd8b21d278c888044b94362c181672e 100644 --- a/client/executor/runtime-test/build.rs +++ b/client/executor/runtime-test/build.rs @@ -19,7 +19,7 @@ use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 2e62e0601574d542abd0a1652c6242bbdc90f640..80b123ed4b5564eb1a87cd857323d06cc46f092a 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . mod sandbox; use codec::{Encode, Decode}; @@ -92,9 +93,8 @@ fn call_not_existing_function(wasm_method: WasmExecutionMethod) { "\"Trap: Trap { kind: Host(Other(\\\"Function `missing_external` is only a stub. Calling a stub is not allowed.\\\")) }\"" ), #[cfg(feature = "wasmtime")] - WasmExecutionMethod::Compiled => assert_eq!( - &format!("{:?}", e), - "\"Wasm execution trapped: call to a missing function env:missing_external\"" + WasmExecutionMethod::Compiled => assert!( + format!("{:?}", e).contains("Wasm execution trapped: call to a missing function env:missing_external") ), } } @@ -121,9 +121,8 @@ fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) { "\"Trap: Trap { kind: Host(Other(\\\"Function `yet_another_missing_external` is only a stub. Calling a stub is not allowed.\\\")) }\"" ), #[cfg(feature = "wasmtime")] - WasmExecutionMethod::Compiled => assert_eq!( - &format!("{:?}", e), - "\"Wasm execution trapped: call to a missing function env:yet_another_missing_external\"" + WasmExecutionMethod::Compiled => assert!( + format!("{:?}", e).contains("Wasm execution trapped: call to a missing function env:yet_another_missing_external") ), } } @@ -623,3 +622,39 @@ fn heap_is_reset_between_calls(wasm_method: WasmExecutionMethod) { // Cal it a second time to check that the heap was freed. instance.call("check_and_set_in_heap", ¶ms).unwrap(); } + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn parallel_execution(wasm_method: WasmExecutionMethod) { + let executor = std::sync::Arc::new(crate::WasmExecutor::new( + wasm_method, + Some(1024), + HostFunctions::host_functions(), + 8, + )); + let code_hash = blake2_256(WASM_BINARY).to_vec(); + let threads: Vec<_> = (0..8).map(|_| + { + let executor = executor.clone(); + let code_hash = code_hash.clone(); + std::thread::spawn(move || { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + assert_eq!( + executor.call_in_wasm( + &WASM_BINARY[..], + Some(code_hash.clone()), + "test_twox_128", + &[0], + &mut ext, + sp_core::traits::MissingHostFunctions::Allow, + ).unwrap(), + hex!("99e9d85137db46ef4bbea33613baafd5").to_vec().encode(), + ); + }) + }).collect(); + + for t in threads.into_iter() { + t.join().unwrap(); + } +} diff --git a/client/executor/src/integration_tests/sandbox.rs b/client/executor/src/integration_tests/sandbox.rs index 8e8b7896cf90b5630486fa780af0a3cc94d9b8dd..f84e446b416c06c2f423d71103dbc1597ec85138 100644 --- a/client/executor/src/integration_tests/sandbox.rs +++ b/client/executor/src/integration_tests/sandbox.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use super::{TestExternalities, call_in_wasm}; use crate::WasmExecutionMethod; diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index 3d7db630f04ac74e34538627a2a657af18fceb71..c02568c734b699fc0e4e4fb4f96852048a564d5e 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! A crate that provides means of executing/dispatching calls into the runtime. //! diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index b859b544a3a9b95c44c56f0cd5920a8fd34cab14..b1eb504d5a2b3f28fd154d724f265479eafa8f8a 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::{ RuntimeInfo, error::{Error, Result}, diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml index 3180eebb4f56ce76a1601e4b734a32be4c5fae81..0c16758c190eca0158427725c61525237c3f0609 100644 --- a/client/executor/wasmi/Cargo.toml +++ b/client/executor/wasmi/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-executor-wasmi" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "This crate provides an implementation of `WasmRuntime` that is baked by wasmi." @@ -16,8 +16,8 @@ targets = ["x86_64-unknown-linux-gnu"] log = "0.4.8" wasmi = "0.6.2" codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-executor-common = { version = "0.8.0-dev", path = "../common" } -sp-wasm-interface = { version = "2.0.0-dev", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "2.0.0-dev", path = "../../../primitives/runtime-interface" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-allocator = { version = "2.0.0-dev", path = "../../../primitives/allocator" } +sc-executor-common = { version = "0.8.0-rc2", path = "../common" } +sp-wasm-interface = { version = "2.0.0-rc2", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0-rc2", path = "../../../primitives/runtime-interface" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-allocator = { version = "2.0.0-rc2", path = "../../../primitives/allocator" } diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml index 5b1c3841410b3f03a1e4235a2c5df3b0eb714b27..2e6d33910cf90af32ae6804df6dffc6fbfd2c765 100644 --- a/client/executor/wasmtime/Cargo.toml +++ b/client/executor/wasmtime/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-executor-wasmtime" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Defines a `WasmRuntime` that uses the Wasmtime JIT to execute." @@ -16,16 +16,16 @@ log = "0.4.8" scoped-tls = "1.0" parity-wasm = "0.41.0" codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-executor-common = { version = "0.8.0-dev", path = "../common" } -sp-wasm-interface = { version = "2.0.0-dev", path = "../../../primitives/wasm-interface" } -sp-runtime-interface = { version = "2.0.0-dev", path = "../../../primitives/runtime-interface" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-allocator = { version = "2.0.0-dev", path = "../../../primitives/allocator" } -wasmtime = { package = "substrate-wasmtime", version = "0.13.0-threadsafe.1" } -wasmtime_runtime = { package = "substrate-wasmtime-runtime", version = "0.13.0-threadsafe.1" } -wasmtime-environ = "0.12.0" -cranelift-wasm = "0.59.0" -cranelift-codegen = "0.59.0" +sc-executor-common = { version = "0.8.0-rc2", path = "../common" } +sp-wasm-interface = { version = "2.0.0-rc2", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0-rc2", path = "../../../primitives/runtime-interface" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-allocator = { version = "2.0.0-rc2", path = "../../../primitives/allocator" } +wasmtime = { package = "substrate-wasmtime", version = "0.16.0-threadsafe.4" } +wasmtime-runtime = { package = "substrate-wasmtime-runtime", version = "0.16.0-threadsafe.4" } +wasmtime-environ = "0.16" +cranelift-wasm = "0.63" +cranelift-codegen = "0.63" [dev-dependencies] assert_matches = "1.3.0" diff --git a/client/executor/wasmtime/src/host.rs b/client/executor/wasmtime/src/host.rs index 29187ac66338e87e8694bb89a4dc0fa19c9e534d..8c481e95c43714fa79f704881c07429b998466cb 100644 --- a/client/executor/wasmtime/src/host.rs +++ b/client/executor/wasmtime/src/host.rs @@ -117,7 +117,7 @@ impl<'a> SandboxCapabilities for HostContext<'a> { return Err("Supervisor function returned unexpected result!".into()); } } - Err(err) => Err(err.message().to_string().into()), + Err(err) => Err(err.to_string().into()), } } } diff --git a/client/executor/wasmtime/src/imports.rs b/client/executor/wasmtime/src/imports.rs index 48299ffd62de1caef2e03016d9b8060188548365..36752d72fa02334efc6a99191005da7c9577ce10 100644 --- a/client/executor/wasmtime/src/imports.rs +++ b/client/executor/wasmtime/src/imports.rs @@ -1,26 +1,27 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::state_holder; use sc_executor_common::error::WasmError; use sp_wasm_interface::{Function, Value, ValueType}; use std::any::Any; -use std::rc::Rc; use wasmtime::{ - Callable, Extern, ExternType, Func, FuncType, ImportType, Limits, Memory, MemoryType, Module, + Extern, ExternType, Func, FuncType, ImportType, Limits, Memory, MemoryType, Module, Trap, Val, }; @@ -53,11 +54,11 @@ pub fn resolve_imports( let resolved = match import_ty.name() { "memory" => { memory_import_index = Some(externs.len()); - resolve_memory_import(module, import_ty, heap_pages)? + resolve_memory_import(module, &import_ty, heap_pages)? } _ => resolve_func_import( module, - import_ty, + &import_ty, host_functions, allow_missing_func_imports, )?, @@ -131,7 +132,7 @@ fn resolve_func_import( { Some(host_func) => host_func, None if allow_missing_func_imports => { - return Ok(MissingHostFuncHandler::new(import_ty).into_extern(module, func_ty)); + return Ok(MissingHostFuncHandler::new(import_ty).into_extern(module, &func_ty)); } None => { return Err(WasmError::Other(format!( @@ -163,6 +164,58 @@ struct HostFuncHandler { host_func: &'static dyn Function, } +fn call_static( + static_func: &'static dyn Function, + wasmtime_params: &[Val], + wasmtime_results: &mut [Val], +) -> Result<(), wasmtime::Trap> { + let unwind_result = state_holder::with_context(|host_ctx| { + let mut host_ctx = host_ctx.expect( + "host functions can be called only from wasm instance; + wasm instance is always called initializing context; + therefore host_ctx cannot be None; + qed + ", + ); + // `into_value` panics if it encounters a value that doesn't fit into the values + // available in substrate. + // + // This, however, cannot happen since the signature of this function is created from + // a `dyn Function` signature of which cannot have a non substrate value by definition. + let mut params = wasmtime_params.iter().cloned().map(into_value); + + std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + static_func.execute(&mut host_ctx, &mut params) + })) + }); + + let execution_result = match unwind_result { + Ok(execution_result) => execution_result, + Err(err) => return Err(Trap::new(stringify_panic_payload(err))), + }; + + match execution_result { + Ok(Some(ret_val)) => { + debug_assert!( + wasmtime_results.len() == 1, + "wasmtime function signature, therefore the number of results, should always \ + correspond to the number of results returned by the host function", + ); + wasmtime_results[0] = into_wasmtime_val(ret_val); + Ok(()) + } + Ok(None) => { + debug_assert!( + wasmtime_results.len() == 0, + "wasmtime function signature, therefore the number of results, should always \ + correspond to the number of results returned by the host function", + ); + Ok(()) + } + Err(msg) => Err(Trap::new(msg)), + } +} + impl HostFuncHandler { fn new(host_func: &'static dyn Function) -> Self { Self { @@ -171,63 +224,14 @@ impl HostFuncHandler { } fn into_extern(self, module: &Module) -> Extern { + let host_func = self.host_func; let func_ty = wasmtime_func_sig(self.host_func); - let func = Func::new(module.store(), func_ty, Rc::new(self)); - Extern::Func(func) - } -} - -impl Callable for HostFuncHandler { - fn call( - &self, - wasmtime_params: &[Val], - wasmtime_results: &mut [Val], - ) -> Result<(), wasmtime::Trap> { - let unwind_result = state_holder::with_context(|host_ctx| { - let mut host_ctx = host_ctx.expect( - "host functions can be called only from wasm instance; - wasm instance is always called initializing context; - therefore host_ctx cannot be None; - qed - ", - ); - // `into_value` panics if it encounters a value that doesn't fit into the values - // available in substrate. - // - // This, however, cannot happen since the signature of this function is created from - // a `dyn Function` signature of which cannot have a non substrate value by definition. - let mut params = wasmtime_params.iter().cloned().map(into_value); - - std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - self.host_func.execute(&mut host_ctx, &mut params) - })) - }); - - let execution_result = match unwind_result { - Ok(execution_result) => execution_result, - Err(err) => return Err(Trap::new(stringify_panic_payload(err))), - }; - - match execution_result { - Ok(Some(ret_val)) => { - debug_assert!( - wasmtime_results.len() == 1, - "wasmtime function signature, therefore the number of results, should always \ - correspond to the number of results returned by the host function", - ); - wasmtime_results[0] = into_wasmtime_val(ret_val); - Ok(()) + let func = Func::new(module.store(), func_ty, + move |_, params, result| { + call_static(host_func, params, result) } - Ok(None) => { - debug_assert!( - wasmtime_results.len() == 0, - "wasmtime function signature, therefore the number of results, should always \ - correspond to the number of results returned by the host function", - ); - Ok(()) - } - Err(msg) => Err(Trap::new(msg)), - } + ); + Extern::Func(func) } } @@ -245,25 +249,18 @@ impl MissingHostFuncHandler { } } - fn into_extern(self, module: &Module, func_ty: &FuncType) -> Extern { - let func = Func::new(module.store(), func_ty.clone(), Rc::new(self)); + fn into_extern(self, wasmtime_module: &Module, func_ty: &FuncType) -> Extern { + let Self { module, name } = self; + let func = Func::new(wasmtime_module.store(), func_ty.clone(), + move |_, _, _| Err(Trap::new(format!( + "call to a missing function {}:{}", + module, name + ))) + ); Extern::Func(func) } } -impl Callable for MissingHostFuncHandler { - fn call( - &self, - _wasmtime_params: &[Val], - _wasmtime_results: &mut [Val], - ) -> Result<(), wasmtime::Trap> { - Err(Trap::new(format!( - "call to a missing function {}:{}", - self.module, self.name - ))) - } -} - fn wasmtime_func_sig(func: &dyn Function) -> wasmtime::FuncType { let params = func .signature() diff --git a/client/executor/wasmtime/src/instance_wrapper.rs b/client/executor/wasmtime/src/instance_wrapper.rs index 469668802f18649c80b59715783a3ad784970396..9026b8054e652604d41a7b626c4f09c38f0eebfe 100644 --- a/client/executor/wasmtime/src/instance_wrapper.rs +++ b/client/executor/wasmtime/src/instance_wrapper.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Defines data and logic needed for interaction with an WebAssembly instance of a substrate //! runtime module. @@ -26,7 +28,7 @@ use sc_executor_common::{ util::{WasmModuleInfo, DataSegmentsSnapshot}, }; use sp_wasm_interface::{Pointer, WordSize, Value}; -use wasmtime::{Store, Instance, Module, Memory, Table, Val}; +use wasmtime::{Store, Instance, Module, Memory, Table, Val, Func, Extern, Global}; mod globals_snapshot; @@ -88,6 +90,35 @@ pub struct InstanceWrapper { _not_send_nor_sync: marker::PhantomData<*const ()>, } +fn extern_memory(extern_: &Extern) -> Option<&Memory> { + match extern_ { + Extern::Memory(mem) => Some(mem), + _ => None, + } +} + + +fn extern_global(extern_: &Extern) -> Option<&Global> { + match extern_ { + Extern::Global(glob) => Some(glob), + _ => None, + } +} + +fn extern_table(extern_: &Extern) -> Option<&Table> { + match extern_ { + Extern::Table(table) => Some(table), + _ => None, + } +} + +fn extern_func(extern_: &Extern) -> Option<&Func> { + match extern_ { + Extern::Func(func) => Some(func), + _ => None, + } +} + impl InstanceWrapper { /// Create a new instance wrapper from the given wasm module. pub fn new(module_wrapper: &ModuleWrapper, imports: &Imports, heap_pages: u32) -> Result { @@ -96,8 +127,7 @@ impl InstanceWrapper { let memory = match imports.memory_import_index { Some(memory_idx) => { - imports.externs[memory_idx] - .memory() + extern_memory(&imports.externs[memory_idx]) .expect("only memory can be at the `memory_idx`; qed") .clone() } @@ -130,8 +160,7 @@ impl InstanceWrapper { .instance .get_export(name) .ok_or_else(|| Error::from(format!("Exported method {} is not found", name)))?; - let entrypoint = export - .func() + let entrypoint = extern_func(&export) .ok_or_else(|| Error::from(format!("Export {} is not a function", name)))?; match (entrypoint.ty().params(), entrypoint.ty().results()) { (&[wasmtime::ValType::I32, wasmtime::ValType::I32], &[wasmtime::ValType::I64]) => {} @@ -164,8 +193,7 @@ impl InstanceWrapper { .get_export("__heap_base") .ok_or_else(|| Error::from("__heap_base is not found"))?; - let heap_base_global = heap_base_export - .global() + let heap_base_global = extern_global(&heap_base_export) .ok_or_else(|| Error::from("__heap_base is not a global"))?; let heap_base = heap_base_global @@ -183,7 +211,7 @@ impl InstanceWrapper { None => return Ok(None), }; - let global = global.global().ok_or_else(|| format!("`{}` is not a global", name))?; + let global = extern_global(&global).ok_or_else(|| format!("`{}` is not a global", name))?; match global.get() { Val::I32(val) => Ok(Some(Value::I32(val))), @@ -201,8 +229,7 @@ fn get_linear_memory(instance: &Instance) -> Result { .get_export("memory") .ok_or_else(|| Error::from("memory is not exported under `memory` name"))?; - let memory = memory_export - .memory() + let memory = extern_memory(&memory_export) .ok_or_else(|| Error::from("the `memory` export should have memory type"))? .clone(); @@ -213,7 +240,8 @@ fn get_linear_memory(instance: &Instance) -> Result { fn get_table(instance: &Instance) -> Option { instance .get_export("__indirect_function_table") - .and_then(|export| export.table()) + .as_ref() + .and_then(extern_table) .cloned() } diff --git a/client/executor/wasmtime/src/instance_wrapper/globals_snapshot.rs b/client/executor/wasmtime/src/instance_wrapper/globals_snapshot.rs index a6ab3fed604c43c8569703aba4c79a4484775383..01d82451fcbbb4884df321103a7ee8fc61f10ed0 100644 --- a/client/executor/wasmtime/src/instance_wrapper/globals_snapshot.rs +++ b/client/executor/wasmtime/src/instance_wrapper/globals_snapshot.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use super::InstanceWrapper; use sc_executor_common::{ @@ -21,6 +23,7 @@ use sc_executor_common::{ use sp_wasm_interface::Value; use cranelift_codegen::ir; use cranelift_wasm::GlobalIndex; +use wasmtime_runtime::{ExportGlobal, Export}; /// A snapshot of a global variables values. This snapshot can be used later for restoring the /// values to the preserved state. @@ -37,17 +40,15 @@ impl GlobalsSnapshot { pub fn take(instance_wrapper: &InstanceWrapper) -> Result { // EVIL: // Usage of an undocumented function. - let handle = instance_wrapper.instance.handle().clone(); + let handle = unsafe { instance_wrapper.instance.handle().clone() }; let mut preserved_mut_globals = vec![]; for global_idx in instance_wrapper.imported_globals_count..instance_wrapper.globals_count { let (def, global) = match handle.lookup_by_declaration( - &wasmtime_environ::Export::Global(GlobalIndex::from_u32(global_idx)), + &wasmtime_environ::EntityIndex::Global(GlobalIndex::from_u32(global_idx)), ) { - wasmtime_runtime::Export::Global { - definition, global, .. - } => (definition, global), + Export::Global(ExportGlobal { definition, global, .. }) => (definition, global), _ => unreachable!("only globals can be returned for a global request"), }; diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 0289188ba11fce00d104d21268541167dd68f54a..a2ad3bada4ba0354849515db2f57699836604108 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -158,7 +158,7 @@ fn perform_call( Err(trap) => { return Err(Error::from(format!( "Wasm execution trapped: {}", - trap.message() + trap ))); } } diff --git a/client/executor/wasmtime/src/state_holder.rs b/client/executor/wasmtime/src/state_holder.rs index 42cb79e7a356807176033266dd0a4f22eacb5103..711d3bb735d7c04306525ba451f1e4be84ed9d21 100644 --- a/client/executor/wasmtime/src/state_holder.rs +++ b/client/executor/wasmtime/src/state_holder.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::host::{HostContext, HostState}; diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml index 9b5d787f889a8107ddfa32f6ac554205e1da1454..44c9e0f0f30d052b8ab049a0341b73c040cf15f7 100644 --- a/client/finality-grandpa/Cargo.toml +++ b/client/finality-grandpa/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-finality-grandpa" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Integration of the GRANDPA finality gadget into substrate." @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] derive_more = "0.99.2" -fork-tree = { version = "2.0.0-dev", path = "../../utils/fork-tree" } +fork-tree = { version = "2.0.0-rc2", path = "../../utils/fork-tree" } futures = "0.3.4" futures-timer = "3.0.1" log = "0.4.8" @@ -23,37 +23,37 @@ parking_lot = "0.10.0" rand = "0.7.2" assert_matches = "1.3.0" parity-scale-codec = { version = "1.3.0", features = ["derive"] } -sp-arithmetic = { version = "2.0.0-dev", path = "../../primitives/arithmetic" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" } -sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" } -sc-consensus = { version = "0.8.0-dev", path = "../../client/consensus/common" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } -sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" } -sc-keystore = { version = "2.0.0-dev", path = "../keystore" } +sp-arithmetic = { version = "2.0.0-rc2", path = "../../primitives/arithmetic" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } +sp-consensus = { version = "0.8.0-rc2", path = "../../primitives/consensus/common" } +sc-consensus = { version = "0.8.0-rc2", path = "../../client/consensus/common" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } +sc-telemetry = { version = "2.0.0-rc2", path = "../telemetry" } +sc-keystore = { version = "2.0.0-rc2", path = "../keystore" } serde_json = "1.0.41" -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sp-inherents = { version = "2.0.0-dev", path = "../../primitives/inherents" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sc-network = { version = "0.8.0-dev", path = "../network" } -sc-network-gossip = { version = "0.8.0-dev", path = "../network-gossip" } -sp-finality-tracker = { version = "2.0.0-dev", path = "../../primitives/finality-tracker" } -sp-finality-grandpa = { version = "2.0.0-dev", path = "../../primitives/finality-grandpa" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-dev"} -sc-block-builder = { version = "0.8.0-dev", path = "../block-builder" } -finality-grandpa = { version = "0.12.2", features = ["derive-codec"] } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-inherents = { version = "2.0.0-rc2", path = "../../primitives/inherents" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sc-network-gossip = { version = "0.8.0-rc2", path = "../network-gossip" } +sp-finality-tracker = { version = "2.0.0-rc2", path = "../../primitives/finality-tracker" } +sp-finality-grandpa = { version = "2.0.0-rc2", path = "../../primitives/finality-grandpa" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc2"} +sc-block-builder = { version = "0.8.0-rc2", path = "../block-builder" } +finality-grandpa = { version = "0.12.3", features = ["derive-codec"] } pin-project = "0.4.6" [dev-dependencies] -finality-grandpa = { version = "0.12.2", features = ["derive-codec", "test-helpers"] } -sc-network = { version = "0.8.0-dev", path = "../network" } -sc-network-test = { version = "0.8.0-dev", path = "../network/test" } -sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } -sp-consensus-babe = { version = "0.8.0-dev", path = "../../primitives/consensus/babe" } -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } +finality-grandpa = { version = "0.12.3", features = ["derive-codec", "test-helpers"] } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sc-network-test = { version = "0.8.0-rc2", path = "../network/test" } +sp-keyring = { version = "2.0.0-rc2", path = "../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } +sp-consensus-babe = { version = "0.8.0-rc2", path = "../../primitives/consensus/babe" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } env_logger = "0.7.0" tokio = { version = "0.2", features = ["rt-core"] } tempfile = "3.1.0" -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } diff --git a/client/finality-grandpa/rpc/Cargo.toml b/client/finality-grandpa/rpc/Cargo.toml index 175a4ccfe8edff85b656b2625d633b16661fcea5..e1724c6c4e2925220be68ca85c08986df3db0af4 100644 --- a/client/finality-grandpa/rpc/Cargo.toml +++ b/client/finality-grandpa/rpc/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "sc-finality-grandpa-rpc" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "RPC extensions for the GRANDPA finality gadget" repository = "https://github.com/paritytech/substrate/" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -sc-finality-grandpa = { version = "0.8.0-dev", path = "../" } -finality-grandpa = { version = "0.12.2", features = ["derive-codec"] } +sc-finality-grandpa = { version = "0.8.0-rc2", path = "../" } +finality-grandpa = { version = "0.12.3", features = ["derive-codec"] } jsonrpc-core = "14.0.3" jsonrpc-core-client = "14.0.3" jsonrpc-derive = "14.0.3" @@ -20,4 +20,4 @@ log = "0.4.8" derive_more = "0.99.2" [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } diff --git a/client/finality-grandpa/rpc/src/error.rs b/client/finality-grandpa/rpc/src/error.rs index 2a5e6955e5e484ffd30b7d62322839324858ef21..bfd0596fdf3205d3eda8003a3a0f109b83fe836f 100644 --- a/client/finality-grandpa/rpc/src/error.rs +++ b/client/finality-grandpa/rpc/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::NOT_READY_ERROR_CODE; @@ -33,7 +35,7 @@ pub enum Error { impl From for jsonrpc_core::Error { fn from(error: Error) -> Self { jsonrpc_core::Error { - message: format!("{}", error).into(), + message: format!("{}", error), code: jsonrpc_core::ErrorCode::ServerError(NOT_READY_ERROR_CODE), data: None, } diff --git a/client/finality-grandpa/rpc/src/lib.rs b/client/finality-grandpa/rpc/src/lib.rs index e62bcf85b6818a53d2ad075fcbd8c76d499ad506..1af84b7a84413007be22a8f01be7701648c1d489 100644 --- a/client/finality-grandpa/rpc/src/lib.rs +++ b/client/finality-grandpa/rpc/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! RPC API for GRANDPA. #![warn(missing_docs)] diff --git a/client/finality-grandpa/rpc/src/report.rs b/client/finality-grandpa/rpc/src/report.rs index 029fd4b46df14a33d152db467052ae4ae05f73d7..a635728cb938adf73d4ae94e1db1a63d5fcb9f50 100644 --- a/client/finality-grandpa/rpc/src/report.rs +++ b/client/finality-grandpa/rpc/src/report.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{ collections::{BTreeSet, HashSet}, diff --git a/client/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs index 80c1f4ad3fe3804225b3a7fbe1d318dd6e13ec31..b4cb254864df7f3150451939e5759e7122b68ca6 100644 --- a/client/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Utilities for dealing with authorities, authority sets, and handoffs. @@ -229,8 +231,8 @@ where (&number, &hash), pending.delay); self.pending_standard_changes.import( - hash.clone(), - number.clone(), + hash, + number, pending, is_descendent_of, )?; diff --git a/client/finality-grandpa/src/aux_schema.rs b/client/finality-grandpa/src/aux_schema.rs index e4e8a980420d86cd39e9f07ffbd90efe07acba23..4ed96d058ac6b42941705c046984852fdea0b795 100644 --- a/client/finality-grandpa/src/aux_schema.rs +++ b/client/finality-grandpa/src/aux_schema.rs @@ -328,7 +328,7 @@ pub(crate) fn load_persistent( } Some(other) => return Err(ClientError::Backend( format!("Unsupported GRANDPA DB version: {:?}", other) - ).into()), + )), } // genesis. @@ -336,7 +336,7 @@ pub(crate) fn load_persistent( from genesis on what appears to be first startup."); let genesis_authorities = genesis_authorities()?; - let genesis_set = AuthoritySet::genesis(genesis_authorities.clone()) + let genesis_set = AuthoritySet::genesis(genesis_authorities) .expect("genesis authorities is non-empty; all weights are non-zero; qed."); let state = make_genesis_round(); let base = state.prevote_ghost diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs index 183ffc65e8378b7751e66a7d7594db9c1ae1aeb6..c96301ede8fe8ad58a55cbb725c89f434db84d2e 100644 --- a/client/finality-grandpa/src/communication/gossip.rs +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -110,7 +110,7 @@ const CATCH_UP_THRESHOLD: u64 = 2; const PROPAGATION_ALL: u32 = 4; //in rounds; const PROPAGATION_ALL_AUTHORITIES: u32 = 2; //in rounds; const PROPAGATION_SOME_NON_AUTHORITIES: u32 = 3; //in rounds; -const ROUND_DURATION: u32 = 4; // measured in gossip durations +const ROUND_DURATION: u32 = 2; // measured in gossip durations const MIN_LUCKY: usize = 5; @@ -181,15 +181,27 @@ impl View { } } -/// A local view of protocol state. Only differs from `View` in that we also -/// track the round and set id at which the last commit was observed. +/// A local view of protocol state. Similar to `View` but we additionally track +/// the round and set id at which the last commit was observed, and the instant +/// at which the current round started. struct LocalView { round: Round, set_id: SetId, last_commit: Option<(N, Round, SetId)>, + round_start: Instant, } impl LocalView { + /// Creates a new `LocalView` at the given set id and round. + fn new(set_id: SetId, round: Round) -> LocalView { + LocalView { + set_id, + round, + last_commit: None, + round_start: Instant::now(), + } + } + /// Converts the local view to a `View` discarding round and set id /// information about the last commit. fn as_view(&self) -> View<&N> { @@ -205,9 +217,16 @@ impl LocalView { if set_id != self.set_id { self.set_id = set_id; self.round = Round(1); + self.round_start = Instant::now(); } } + /// Updates the current round. + fn update_round(&mut self, round: Round) { + self.round = round; + self.round_start = Instant::now(); + } + /// Returns the height of the block that the last observed commit finalizes. fn last_commit_height(&self) -> Option<&N> { self.last_commit.as_ref().map(|(number, _, _)| number) @@ -656,7 +675,6 @@ struct Inner { local_view: Option>>, peers: Peers>, live_topics: KeepTopics, - round_start: Instant, authorities: Vec, config: crate::Config, next_rebroadcast: Instant, @@ -689,7 +707,6 @@ impl Inner { local_view: None, peers: Peers::default(), live_topics: KeepTopics::new(), - round_start: Instant::now(), next_rebroadcast: Instant::now() + REBROADCAST_AFTER, authorities: Vec::new(), pending_catch_up: PendingCatchUp::None, @@ -715,10 +732,9 @@ impl Inner { debug!(target: "afg", "Voter {} noting beginning of round {:?} to network.", self.config.name(), (round, set_id)); - local_view.round = round; + local_view.update_round(round); self.live_topics.push(round, set_id); - self.round_start = Instant::now(); self.peers.reshuffle(); } self.multicast_neighbor_packet() @@ -729,11 +745,10 @@ impl Inner { fn note_set(&mut self, set_id: SetId, authorities: Vec) -> MaybeMessage { { let local_view = match self.local_view { - ref mut x @ None => x.get_or_insert(LocalView { - round: Round(1), + ref mut x @ None => x.get_or_insert(LocalView::new( set_id, - last_commit: None, - }), + Round(1), + )), Some(ref mut v) => if v.set_id == set_id { if self.authorities != authorities { debug!(target: "afg", @@ -887,7 +902,7 @@ impl Inner { // any catch up requests until we import this one (either with a // success or failure). self.pending_catch_up = PendingCatchUp::Processing { - instant: instant.clone(), + instant: *instant, }; // always discard catch up messages, they're point-to-point @@ -1121,8 +1136,10 @@ impl Inner { /// underlying gossip layer, which should happen every 30 seconds. fn round_message_allowed(&self, who: &PeerId, peer: &PeerInfo) -> bool { let round_duration = self.config.gossip_duration * ROUND_DURATION; - let round_elapsed = self.round_start.elapsed(); - + let round_elapsed = match self.local_view { + Some(ref local_view) => local_view.round_start.elapsed(), + None => return false, + }; if !self.config.is_authority && round_elapsed < round_duration * PROPAGATION_ALL @@ -1185,7 +1202,10 @@ impl Inner { /// underlying gossip layer, which should happen every 30 seconds. fn global_message_allowed(&self, who: &PeerId, peer: &PeerInfo) -> bool { let round_duration = self.config.gossip_duration * ROUND_DURATION; - let round_elapsed = self.round_start.elapsed(); + let round_elapsed = match self.local_view { + Some(ref local_view) => local_view.round_start.elapsed(), + None => return false, + }; match peer.roles { ObservedRole::OurSentry | ObservedRole::OurGuardedAuthority => true, @@ -1281,7 +1301,7 @@ impl GossipValidator { inner: parking_lot::RwLock::new(Inner::new(config)), set_state, report_sender: tx, - metrics: metrics, + metrics, }; (val, rx) @@ -2320,7 +2340,8 @@ mod tests { let test = |num_round, peers| { // rewind n round durations - val.inner.write().round_start = Instant::now() - round_duration * num_round; + val.inner.write().local_view.as_mut().unwrap().round_start = + Instant::now() - round_duration * num_round; let mut message_allowed = val.message_allowed(); move || { @@ -2448,7 +2469,8 @@ mod tests { } { - val.inner.write().round_start = Instant::now() - round_duration * 4; + val.inner.write().local_view.as_mut().unwrap().round_start = + Instant::now() - round_duration * 4; let mut message_allowed = val.message_allowed(); // on the fourth round duration we should allow messages to authorities // (on the second we would do `sqrt(authorities)`) diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs index 16af54986a02a082339251b08739aca1eea8f5a7..abd1c27983a6d37ec4416f84efae8ed7366cc5b3 100644 --- a/client/finality-grandpa/src/communication/mod.rs +++ b/client/finality-grandpa/src/communication/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Communication streams for the polite-grandpa networking protocol. //! @@ -236,16 +238,14 @@ impl> NetworkBridge { let (neighbor_packet_worker, neighbor_packet_sender) = periodic::NeighborPacketWorker::new(); - let bridge = NetworkBridge { + NetworkBridge { service, gossip_engine, validator, neighbor_sender: neighbor_packet_sender, neighbor_packet_worker: Arc::new(Mutex::new(neighbor_packet_worker)), gossip_validator_report_stream: Arc::new(Mutex::new(report_stream)), - }; - - bridge + } } /// Note the beginning of a new round to the `GossipValidator`. @@ -304,7 +304,7 @@ impl> NetworkBridge { match decoded { Err(ref e) => { debug!(target: "afg", "Skipping malformed message {:?}: {}", notification, e); - return future::ready(None); + future::ready(None) } Ok(GossipMessage::Vote(msg)) => { // check signature. @@ -343,7 +343,7 @@ impl> NetworkBridge { } _ => { debug!(target: "afg", "Skipping unknown message type"); - return future::ready(None); + future::ready(None) } } }); @@ -666,7 +666,7 @@ impl Sink> for OutgoingMessages // when locals exist, sign messages on import if let Some((ref pair, _)) = self.locals { - let target_hash = msg.target().0.clone(); + let target_hash = *(msg.target().0); let signed = sp_finality_grandpa::sign_message( msg, pair, diff --git a/client/finality-grandpa/src/communication/periodic.rs b/client/finality-grandpa/src/communication/periodic.rs index f894624bdf79e6e000f7a113c804517633301cb9..dadd7deb57fca1d34dd01baf0d434533f1a99fbe 100644 --- a/client/finality-grandpa/src/communication/periodic.rs +++ b/client/finality-grandpa/src/communication/periodic.rs @@ -86,7 +86,7 @@ impl Stream for NeighborPacketWorker { this.delay.reset(REBROADCAST_AFTER); this.last = Some((to.clone(), packet.clone())); - return Poll::Ready(Some((to, GossipMessage::::from(packet.clone())))); + return Poll::Ready(Some((to, GossipMessage::::from(packet)))); } // Don't return yet, maybe the timer fired. Poll::Pending => {}, @@ -108,6 +108,6 @@ impl Stream for NeighborPacketWorker { return Poll::Ready(Some((to.clone(), GossipMessage::::from(packet.clone())))); } - return Poll::Pending; + Poll::Pending } } diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index 1db1bcbb8d4a5826e032cfdc8a262c5dc42849be..afcc3891ac39f6ec0499da9a7066bf7075eb0065 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::collections::BTreeMap; use std::iter::FromIterator; @@ -108,7 +110,7 @@ impl Decode for CompletedRounds { fn decode(value: &mut I) -> Result { <(Vec>, SetId, Vec)>::decode(value) .map(|(rounds, set_id, voters)| CompletedRounds { - rounds: rounds.into(), + rounds, set_id, voters, }) @@ -248,14 +250,14 @@ impl VoterSetState { { if let VoterSetState::Live { completed_rounds, current_rounds } = self { if current_rounds.contains_key(&round) { - return Ok((completed_rounds, current_rounds)); + Ok((completed_rounds, current_rounds)) } else { let msg = "Voter acting on a live round we are not tracking."; - return Err(Error::Safety(msg.to_string())); + Err(Error::Safety(msg.to_string())) } } else { let msg = "Voter acting while in paused state."; - return Err(Error::Safety(msg.to_string())); + Err(Error::Safety(msg.to_string())) } } } @@ -622,7 +624,7 @@ where restricted_number >= base_header.number() && restricted_number < target_header.number() }) - .or(Some((target_header.hash(), *target_header.number()))) + .or_else(|| Some((target_header.hash(), *target_header.number()))) }, Ok(None) => { debug!(target: "afg", "Encountered error finding best chain containing {:?}: couldn't find target block", block); diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index bf3662aba36af2b79076ec62d4cc603a5a42d563..55f6376579db4ced0e554293d3fabf569d221b94 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! GRANDPA block finality proof generation and check. //! @@ -183,7 +185,7 @@ impl sc_network::config::FinalityProofProvider for FinalityProo let request: FinalityProofRequest = Decode::decode(&mut &request[..]) .map_err(|e| { warn!(target: "afg", "Unable to decode finality proof request: {}", e.what()); - ClientError::Backend(format!("Invalid finality proof request")) + ClientError::Backend("Invalid finality proof request".to_string()) })?; match request { FinalityProofRequest::Original(request) => prove_finality::<_, _, GrandpaJustification>( @@ -397,7 +399,7 @@ pub(crate) fn prove_finality, J>( } // else search for the next justification - current_number = current_number + One::one(); + current_number += One::one(); } if finality_proof.is_empty() { @@ -513,7 +515,7 @@ fn check_finality_proof_fragment( new_authorities_proof, )?; - current_set_id = current_set_id + 1; + current_set_id += 1; } Ok(AuthoritiesOrEffects::Effects(FinalityEffects { diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index c1e32dfa6cc9e3847c18030f6f88c666d182a611..7e3799b1e25e1f4a25ff97e99f44d29d32065b55 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{sync::Arc, collections::HashMap}; @@ -294,7 +296,7 @@ where } } - let number = block.header.number().clone(); + let number = *(block.header.number()); let maybe_change = self.check_new_change( &block.header, hash, @@ -326,7 +328,7 @@ where guard.as_mut().add_pending_change( change, &is_descendent_of, - ).map_err(|e| ConsensusError::from(ConsensusError::ClientImport(e.to_string())))?; + ).map_err(|e| ConsensusError::ClientImport(e.to_string()))?; } let applied_changes = { @@ -417,14 +419,14 @@ impl BlockImport new_cache: HashMap>, ) -> Result { let hash = block.post_hash(); - let number = block.header.number().clone(); + let number = *block.header.number(); // early exit if block already in chain, otherwise the check for // authority changes will error when trying to re-import a change block match self.inner.status(BlockId::Hash(hash)) { Ok(BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), Ok(BlockStatus::Unknown) => {}, - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), + Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), } // on initial sync we will restrict logging under info to avoid spam. @@ -456,7 +458,7 @@ impl BlockImport e, ); pending_changes.revert(); - return Err(ConsensusError::ClientImport(e.to_string()).into()); + return Err(ConsensusError::ClientImport(e.to_string())); }, } }; @@ -466,7 +468,7 @@ impl BlockImport // Send the pause signal after import but BEFORE sending a `ChangeAuthorities` message. if do_pause { let _ = self.send_voter_commands.unbounded_send( - VoterCommand::Pause(format!("Forced change scheduled after inactivity")) + VoterCommand::Pause("Forced change scheduled after inactivity".to_string()) ); } @@ -633,7 +635,7 @@ where ); let justification = match justification { - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), + Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), Ok(justification) => justification, }; @@ -668,7 +670,7 @@ where Error::Client(error) => ConsensusError::ClientImport(error.to_string()), Error::Safety(error) => ConsensusError::ClientImport(error), Error::Timer(error) => ConsensusError::ClientImport(error.to_string()), - }.into()); + }); }, Ok(_) => { assert!(!enacts_change, "returns Ok when no authority set change should be enacted; qed;"); diff --git a/client/finality-grandpa/src/justification.rs b/client/finality-grandpa/src/justification.rs index cbaa2cb4415b87cbdeb3d7d3888cca2e011ec288..b4db81f8a42bf701e98134a265768c9387f12b24 100644 --- a/client/finality-grandpa/src/justification.rs +++ b/client/finality-grandpa/src/justification.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::collections::{HashMap, HashSet}; use std::sync::Arc; @@ -61,7 +63,7 @@ impl GrandpaJustification { }; for signed in commit.precommits.iter() { - let mut current_hash = signed.precommit.target_hash.clone(); + let mut current_hash = signed.precommit.target_hash; loop { if current_hash == commit.target_hash { break; } @@ -71,7 +73,7 @@ impl GrandpaJustification { return error(); } - let parent_hash = current_header.parent_hash().clone(); + let parent_hash = *current_header.parent_hash(); if votes_ancestries_hashes.insert(current_hash) { votes_ancestries.push(current_header); } @@ -131,16 +133,16 @@ impl GrandpaJustification { let mut buf = Vec::new(); let mut visited_hashes = HashSet::new(); for signed in self.commit.precommits.iter() { - if let Err(_) = sp_finality_grandpa::check_message_signature_with_buffer( + if sp_finality_grandpa::check_message_signature_with_buffer( &finality_grandpa::Message::Precommit(signed.precommit.clone()), &signed.id, &signed.signature, self.round, set_id, &mut buf, - ) { + ).is_err() { return Err(ClientError::BadJustification( - "invalid signature for precommit in grandpa justification".to_string()).into()); + "invalid signature for precommit in grandpa justification".to_string())); } if self.commit.target_hash == signed.precommit.target_hash { @@ -157,7 +159,7 @@ impl GrandpaJustification { }, _ => { return Err(ClientError::BadJustification( - "invalid precommit ancestry proof in grandpa justification".to_string()).into()); + "invalid precommit ancestry proof in grandpa justification".to_string())); }, } } @@ -169,7 +171,7 @@ impl GrandpaJustification { if visited_hashes != ancestry_hashes { return Err(ClientError::BadJustification( - "invalid precommit ancestries in grandpa justification with unused headers".to_string()).into()); + "invalid precommit ancestries in grandpa justification with unused headers".to_string())); } Ok(()) diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index ac677bf3f32d2ca1a32c4296da1b9fe7b8b3999f..7b20d082a01ab77892832772082e6338243086b1 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Integration of the GRANDPA finality gadget into substrate. //! @@ -74,11 +76,8 @@ use sp_consensus::{SelectChain, BlockImport}; use sp_core::Pair; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver}; use sc_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG}; -use serde_json; use parking_lot::RwLock; -use sp_finality_tracker; - use finality_grandpa::Error as GrandpaError; use finality_grandpa::{voter, BlockNumberOps, voter_set::VoterSet}; @@ -120,6 +119,7 @@ mod voting_rule; pub use authorities::SharedAuthoritySet; pub use finality_proof::{FinalityProofProvider, StorageAndProofProvider}; +pub use import::GrandpaBlockImport; pub use justification::GrandpaJustification; pub use light_import::light_block_import; pub use voting_rule::{ @@ -129,7 +129,6 @@ pub use finality_grandpa::voter::report; use aux_schema::PersistentData; use environment::{Environment, VoterSetState}; -use import::GrandpaBlockImport; use until_imported::UntilGlobalMessageBlocksImported; use communication::{NetworkBridge, Network as NetworkT}; use sp_finality_grandpa::{AuthorityList, AuthorityPair, AuthoritySignature, SetId}; @@ -474,7 +473,7 @@ impl GenesisAuthoritySetProvider for Arc( Ok(info.finalized_number) } })) - .map_err(|err| sp_consensus::Error::InherentData(err.into())) + .map_err(|err| sp_consensus::Error::InherentData(err)) } else { Ok(()) } @@ -731,7 +730,7 @@ pub fn run_grandpa_voter( let curr = authorities.current_authorities(); let mut auths = curr.iter().map(|(p, _)| p); let maybe_authority_id = authority_id(&mut auths, &conf.keystore) - .unwrap_or(Default::default()); + .unwrap_or_default(); telemetry!(CONSENSUS_INFO; "afg.authority_set"; "authority_id" => maybe_authority_id.to_string(), @@ -841,7 +840,7 @@ where set_id: persistent_data.authority_set.set_id(), authority_set: persistent_data.authority_set.clone(), consensus_changes: persistent_data.consensus_changes.clone(), - voter_set_state: persistent_data.set_state.clone(), + voter_set_state: persistent_data.set_state, metrics: metrics.as_ref().map(|m| m.environment.clone()), _phantom: PhantomData, }); @@ -868,7 +867,7 @@ where let authority_id = is_voter(&self.env.voters, &self.env.config.keystore) .map(|ap| ap.public()) - .unwrap_or(Default::default()); + .unwrap_or_default(); telemetry!(CONSENSUS_DEBUG; "afg.starting_new_voter"; "name" => ?self.env.config.name(), @@ -914,12 +913,12 @@ where global_comms, last_completed_round.number, last_completed_round.votes.clone(), - last_completed_round.base.clone(), + last_completed_round.base, last_finalized, ); // Repoint shared_voter_state so that the RPC endpoint can query the state - if let None = self.shared_voter_state.reset(voter.voter_state()) { + if self.shared_voter_state.reset(voter.voter_state()).is_none() { info!(target: "afg", "Timed out trying to update shared GRANDPA voter state. \ RPC endpoints may return stale data." diff --git a/client/finality-grandpa/src/light_import.rs b/client/finality-grandpa/src/light_import.rs index e9ca94ce9824fd2a411185597f1af60fe0fee513..b63c6f0bd7c1d1ad3033ba4ab849ea408369f043 100644 --- a/client/finality-grandpa/src/light_import.rs +++ b/client/finality-grandpa/src/light_import.rs @@ -169,7 +169,7 @@ impl FinalityProofImport if *pending_number > chain_info.finalized_number && *pending_number <= chain_info.best_number { - out.push((pending_hash.clone(), *pending_number)); + out.push((*pending_hash, *pending_number)); } } @@ -253,7 +253,7 @@ fn do_import_block( J: ProvableJustification, { let hash = block.post_hash(); - let number = block.header.number().clone(); + let number = *block.header.number(); // we don't want to finalize on `inner.import_block` let justification = block.justification.take(); @@ -263,7 +263,7 @@ fn do_import_block( let mut imported_aux = match import_result { Ok(ImportResult::Imported(aux)) => aux, Ok(r) => return Ok(r), - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), + Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), }; match justification { @@ -435,7 +435,7 @@ fn do_import_justification( hash, ); - return Err(ConsensusError::ClientImport(e.to_string()).into()); + return Err(ConsensusError::ClientImport(e.to_string())); }, Ok(justification) => { trace!( diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index ab06f06280c83ba16f55a07b9f19b8f898bf3e5c..cd678b3bb45427e24fd17d14b3e2f3c5f47874b9 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::pin::Pin; use std::sync::Arc; @@ -111,7 +113,7 @@ fn grandpa_observer( Err(e) => return future::err(e.into()), }; - if let Some(_) = validation_result.ghost() { + if validation_result.ghost().is_some() { let finalized_hash = commit.target_hash; let finalized_number = commit.target_number; @@ -189,7 +191,7 @@ where client, network, persistent_data, - config.keystore.clone(), + config.keystore, voter_commands_rx ); diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index 64e5b0545b546a4f4b8b4a26634480428a105b10..25e625365200166d796db2ae842a6b41d094797d 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Tests and test helpers for GRANDPA. diff --git a/client/finality-grandpa/src/until_imported.rs b/client/finality-grandpa/src/until_imported.rs index 737c8c6a774e8e6917aa1216441a102d8680eb86..6a39c2637eb7b8b173ae7881a8d97406e87b43e0 100644 --- a/client/finality-grandpa/src/until_imported.rs +++ b/client/finality-grandpa/src/until_imported.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Helper stream for waiting until one or more blocks are imported before //! passing through inner items. This is done in a generic way to support @@ -31,7 +33,7 @@ use super::{ use log::{debug, warn}; use sp_utils::mpsc::TracingUnboundedReceiver; use futures::prelude::*; -use futures::stream::Fuse; +use futures::stream::{Fuse, StreamExt}; use futures_timer::Delay; use finality_grandpa::voter; use parking_lot::Mutex; @@ -137,14 +139,16 @@ impl Drop for Metrics { } } -/// Buffering imported messages until blocks with given hashes are imported. -#[pin_project::pin_project] -pub(crate) struct UntilImported> { +/// Buffering incoming messages until blocks with given hashes are imported. +pub(crate) struct UntilImported where + Block: BlockT, + I: Stream + Unpin, + M: BlockUntilImported, +{ import_notifications: Fuse>>, block_sync_requester: BlockSyncRequester, status_check: BlockStatus, - #[pin] - inner: Fuse, + incoming_messages: Fuse, ready: VecDeque, /// Interval at which to check status of each awaited block. check_pending: Pin> + Send + Sync>>, @@ -159,11 +163,17 @@ pub(crate) struct UntilImported, } +impl Unpin for UntilImported where + Block: BlockT, + I: Stream + Unpin, + M: BlockUntilImported, +{} + impl UntilImported where Block: BlockT, BlockStatus: BlockStatusT, BlockSyncRequester: BlockSyncRequesterT, - I: Stream, + I: Stream + Unpin, M: BlockUntilImported, { /// Create a new `UntilImported` wrapper. @@ -171,7 +181,7 @@ impl UntilImported, block_sync_requester: BlockSyncRequester, status_check: BlockStatus, - stream: I, + incoming_messages: I, identifier: &'static str, metrics: Option, ) -> Self { @@ -192,7 +202,7 @@ impl UntilImported Stream for UntilImported, BSyncRequester: BlockSyncRequesterT, - I: Stream, + I: Stream + Unpin, M: BlockUntilImported, { type Item = Result; - fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - // We are using a `this` variable in order to allow multiple simultaneous mutable borrow - // to `self`. - let mut this = self.project(); + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + // We are using a `this` variable in order to allow multiple simultaneous mutable borrow to + // `self`. + let this = &mut *self; loop { - match Stream::poll_next(Pin::new(&mut this.inner), cx) { + match StreamExt::poll_next_unpin(&mut this.incoming_messages, cx) { Poll::Ready(None) => return Poll::Ready(None), Poll::Ready(Some(input)) => { // new input: schedule wait of any parts which require // blocks to be known. - match M::needs_waiting(input, this.status_check)? { + match M::needs_waiting(input, &this.status_check)? { DiscardWaitOrReady::Discard => {}, DiscardWaitOrReady::Wait(items) => { for (target_hash, target_number, wait) in items { @@ -245,12 +255,12 @@ impl Stream for UntilImported return Poll::Ready(None), Poll::Ready(Some(notification)) => { // new block imported. queue up all messages tied to that hash. if let Some((_, _, messages)) = this.pending.remove(¬ification.hash) { - let canon_number = notification.header.number().clone(); + let canon_number = *notification.header.number(); let ready_messages = messages.into_iter() .filter_map(|m| m.wait_completed(canon_number)); @@ -315,7 +325,7 @@ impl Stream for UntilImported BlockUntilImported for SignedMessage { } } - return Ok(DiscardWaitOrReady::Wait(vec![(target_hash, target_number, msg)])) + Ok(DiscardWaitOrReady::Wait(vec![(target_hash, target_number, msg)])) } fn wait_completed(self, canon_number: NumberFor) -> Option { @@ -422,7 +432,7 @@ impl BlockUntilImported for BlockGlobalMessage { let mut query_known = |target_hash, perceived_number| -> Result { // check integrity: all votes for same hash have same number. let canon_number = match checked_hashes.entry(target_hash) { - Entry::Occupied(entry) => entry.get().number().clone(), + Entry::Occupied(entry) => *entry.get().number(), Entry::Vacant(entry) => { if let Some(number) = status_check.block_number(target_hash)? { entry.insert(KnownOrUnknown::Known(number)); diff --git a/client/finality-grandpa/src/voting_rule.rs b/client/finality-grandpa/src/voting_rule.rs index bcf17039a89b614980959666a4fb7f2055139bd8..60493867ce1f4c4e9c50e662857ef1ffcd842cba 100644 --- a/client/finality-grandpa/src/voting_rule.rs +++ b/client/finality-grandpa/src/voting_rule.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Handling custom voting rules for GRANDPA. //! diff --git a/client/informant/Cargo.toml b/client/informant/Cargo.toml index f8e6ca85f95b8347934df26254b9999294efe879..cd24fa6958684aabeee2c9fa8b36ab8bbdd8edef 100644 --- a/client/informant/Cargo.toml +++ b/client/informant/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-informant" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Substrate informant." edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -17,8 +17,8 @@ futures = "0.3.4" log = "0.4.8" parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] } wasm-timer = "0.2" -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sc-network = { version = "0.8.0-dev", path = "../network" } -sc-service = { version = "0.8.0-dev", default-features = false, path = "../service" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sc-service = { version = "0.8.0-rc2", default-features = false, path = "../service" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } diff --git a/client/informant/src/lib.rs b/client/informant/src/lib.rs index 090282a982092db6ec98e504b546268dd272bb56..6eea9c1d0434ca3eb93ab8f2a0e69929be1894dc 100644 --- a/client/informant/src/lib.rs +++ b/client/informant/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Console informant. Prints sync progress and block events. Runs on the calling thread. diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml index f3419f55e1dc3207db64bcee0544d65568f114e1..f02869762d52fd094f8d52f62f2bab1572b956f3 100644 --- a/client/keystore/Cargo.toml +++ b/client/keystore/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-keystore" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Keystore (and session key management) for ed25519 based chains like Polkadot." @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] derive_more = "0.99.2" -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-application-crypto = { version = "2.0.0-dev", path = "../../primitives/application-crypto" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-application-crypto = { version = "2.0.0-rc2", path = "../../primitives/application-crypto" } hex = "0.4.0" rand = "0.7.2" serde_json = "1.0.41" diff --git a/client/keystore/src/lib.rs b/client/keystore/src/lib.rs index f8bc93097113b300bc85373918021da742700221..6510bb82327b1ef87a6b1de350382536f0184653 100644 --- a/client/keystore/src/lib.rs +++ b/client/keystore/src/lib.rs @@ -23,7 +23,7 @@ use sp_core::{ traits::{BareCryptoStore, BareCryptoStoreError as TraitError}, Encode, }; -use sp_application_crypto::{AppKey, AppPublic, AppPair, ed25519, sr25519}; +use sp_application_crypto::{AppKey, AppPublic, AppPair, ed25519, sr25519, ecdsa}; use parking_lot::RwLock; /// Keystore pointer @@ -308,6 +308,7 @@ impl BareCryptoStore for Store { .fold(Vec::new(), |mut v, k| { v.push(CryptoTypePublicPair(sr25519::CRYPTO_ID, k.clone())); v.push(CryptoTypePublicPair(ed25519::CRYPTO_ID, k.clone())); + v.push(CryptoTypePublicPair(ecdsa::CRYPTO_ID, k.clone())); v })) } @@ -343,6 +344,13 @@ impl BareCryptoStore for Store { .key_pair_by_type::(&pub_key, id) .map_err(|e| TraitError::from(e))?; Ok(key_pair.sign(msg).encode()) + }, + ecdsa::CRYPTO_ID => { + let pub_key = ecdsa::Public::from_slice(key.1.as_slice()); + let key_pair: ecdsa::Pair = self + .key_pair_by_type::(&pub_key, id) + .map_err(|e| TraitError::from(e))?; + Ok(key_pair.sign(msg).encode()) } _ => Err(TraitError::KeyNotSupported(id)) } @@ -394,6 +402,29 @@ impl BareCryptoStore for Store { Ok(pair.public()) } + fn ecdsa_public_keys(&self, key_type: KeyTypeId) -> Vec { + self.raw_public_keys(key_type) + .map(|v| { + v.into_iter() + .map(|k| ecdsa::Public::from_slice(k.as_slice())) + .collect() + }) + .unwrap_or_default() + } + + fn ecdsa_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> std::result::Result { + let pair = match seed { + Some(seed) => self.insert_ephemeral_from_seed_by_type::(seed, id), + None => self.generate_by_type::(id), + }.map_err(|e| -> TraitError { e.into() })?; + + Ok(pair.public()) + } + fn insert_unknown(&mut self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> std::result::Result<(), ()> { diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml index 4b02a6f70e8b56ab5b295333168e6a8872f920d9..e6dc57dc9cf476246b1f983c06b3c4eac4114f52 100644 --- a/client/network-gossip/Cargo.toml +++ b/client/network-gossip/Cargo.toml @@ -1,8 +1,8 @@ [package] description = "Gossiping for the Substrate network protocol" name = "sc-network-gossip" -version = "0.8.0-dev" -license = "GPL-3.0" +version = "0.8.0-rc2" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" @@ -16,15 +16,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] futures = "0.3.4" futures-timer = "3.0.1" -libp2p = { version = "0.18.1", default-features = false, features = ["websocket"] } +libp2p = { version = "0.19.1", default-features = false, features = ["websocket"] } log = "0.4.8" lru = "0.4.3" -sc-network = { version = "0.8.0-dev", path = "../network" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } wasm-timer = "0.2" [dev-dependencies] async-std = "1.5" quickcheck = "0.9.0" rand = "0.7.2" -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } diff --git a/client/network-gossip/src/state_machine.rs b/client/network-gossip/src/state_machine.rs index 433457afe748e422c78c0a2d5bde7c2af54c173c..da07bde3e7d1ad97f10f65a8c1204e2fc291c9c5 100644 --- a/client/network-gossip/src/state_machine.rs +++ b/client/network-gossip/src/state_machine.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::{Network, MessageIntent, Validator, ValidatorContext, ValidationResult}; diff --git a/client/network-gossip/src/validator.rs b/client/network-gossip/src/validator.rs index 6b330d7b618c0e702e52cc330ed2bd77b3ffdbdd..fd29aaddafe6dcd89f2e722bdcfa07854fc04225 100644 --- a/client/network-gossip/src/validator.rs +++ b/client/network-gossip/src/validator.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use sc_network::{ObservedRole, PeerId}; use sp_runtime::traits::Block as BlockT; diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml index e31e0f3113236abcd58af3029a077ce763c4b033..6c6579a858f6e242ac0d76533b7f0a2d8ac4a527 100644 --- a/client/network/Cargo.toml +++ b/client/network/Cargo.toml @@ -1,8 +1,8 @@ [package] description = "Substrate network protocol" name = "sc-network" -version = "0.8.0-dev" -license = "GPL-3.0" +version = "0.8.0-rc2" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" @@ -19,13 +19,14 @@ prost-build = "0.6.1" [dependencies] bitflags = "1.2.0" +bs58 = "0.3.1" bytes = "0.5.0" codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } derive_more = "0.99.2" either = "1.5.3" erased-serde = "0.3.9" fnv = "1.0.6" -fork-tree = { version = "2.0.0-dev", path = "../../utils/fork-tree" } +fork-tree = { version = "2.0.0-rc2", path = "../../utils/fork-tree" } futures = "0.3.4" futures-timer = "3.0.1" futures_codec = "0.3.3" @@ -38,23 +39,23 @@ lru = "0.4.0" nohash-hasher = "0.2.0" parking_lot = "0.10.0" pin-project = "0.4.6" -prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-dev", path = "../../utils/prometheus" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.8.0-rc2", path = "../../utils/prometheus" } prost = "0.6.1" rand = "0.7.2" -sc-block-builder = { version = "0.8.0-dev", path = "../block-builder" } -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sc-peerset = { version = "2.0.0-dev", path = "../peerset" } +sc-block-builder = { version = "0.8.0-rc2", path = "../block-builder" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sc-peerset = { version = "2.0.0-rc2", path = "../peerset" } serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" slog = { version = "2.5.2", features = ["nested-values"] } slog_derive = "0.2.0" smallvec = "0.6.10" -sp-arithmetic = { version = "2.0.0-dev", path = "../../primitives/arithmetic" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" } +sp-arithmetic = { version = "2.0.0-rc2", path = "../../primitives/arithmetic" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sp-consensus = { version = "0.8.0-rc2", path = "../../primitives/consensus/common" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } thiserror = "1" unsigned-varint = { version = "0.3.1", features = ["futures", "futures-codec"] } void = "1.0.2" @@ -62,21 +63,21 @@ wasm-timer = "0.2" zeroize = "1.0.0" [dependencies.libp2p] -version = "0.18.1" +version = "0.19.1" default-features = false -features = ["websocket", "kad", "mdns", "ping", "identify", "mplex", "yamux", "noise"] +features = ["websocket", "kad", "mdns", "ping", "identify", "mplex", "yamux", "noise", "tcp-async-std"] [dev-dependencies] async-std = "1.5" assert_matches = "1.3" env_logger = "0.7.0" -libp2p = { version = "0.18.1", default-features = false, features = ["secio"] } +libp2p = { version = "0.19.1", default-features = false, features = ["secio"] } quickcheck = "0.9.0" rand = "0.7.2" -sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" } -sp-test-primitives = { version = "2.0.0-dev", path = "../../primitives/test-primitives" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../test-utils/runtime" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sp-keyring = { version = "2.0.0-rc2", path = "../../primitives/keyring" } +sp-test-primitives = { version = "2.0.0-rc2", path = "../../primitives/test-primitives" } +substrate-test-runtime = { version = "2.0.0-rc2", path = "../../test-utils/runtime" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } tempfile = "3.1.0" [features] diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs index 5a5dd83803130f76fd0751deb02e0176603b157e..dec8788f3f4dc570413fcbf429edfb703fd5230b 100644 --- a/client/network/src/behaviour.rs +++ b/client/network/src/behaviour.rs @@ -113,7 +113,7 @@ impl Behaviour { ) -> Self { Behaviour { substrate, - debug_info: debug_info::DebugInfoBehaviour::new(user_agent, local_public_key.clone()), + debug_info: debug_info::DebugInfoBehaviour::new(user_agent, local_public_key), discovery: disco_config.finish(), block_requests, finality_proof_requests, @@ -311,13 +311,13 @@ impl NetworkBehaviourEventProcess { + block_requests::Event::Response { peer, original_request: _, response, request_duration } => { self.events.push_back(BehaviourOut::RequestFinished { peer: peer.clone(), protocol: self.block_requests.protocol_name().to_vec(), request_duration, }); - let ev = self.substrate.on_block_response(peer, original_request, response); + let ev = self.substrate.on_block_response(peer, response); self.inject_event(ev); } block_requests::Event::RequestCancelled { peer, request_duration, .. } | @@ -329,7 +329,7 @@ impl NetworkBehaviourEventProcess NetworkBehaviourEventProcess. +// along with this program. If not, see . //! Blockchain access trait diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 66800aeeaf8d23ec01bf101179f99e3a0e67b8e1..6c9bd3adb9fd78a0859871f9bbfba1b919998230 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Configuration of the networking layer. //! @@ -28,14 +30,14 @@ pub use libp2p::{identity, core::PublicKey, wasm_ext::ExtTransport, build_multia #[doc(hidden)] pub use crate::protocol::ProtocolConfig; -use crate::{ExHashT, ReportHandle}; +use crate::ExHashT; use core::{fmt, iter}; +use futures::future; use libp2p::identity::{ed25519, Keypair}; use libp2p::wasm_ext; use libp2p::{multiaddr, Multiaddr, PeerId}; use prometheus_endpoint::Registry; -use sc_peerset::ReputationChange; use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; use std::{borrow::Cow, convert::TryFrom, future::Future, pin::Pin, str::FromStr}; @@ -167,6 +169,22 @@ impl FinalityProofRequestBuilder for DummyFinalityProofRequestBuil /// Shared finality proof request builder struct used by the queue. pub type BoxFinalityProofRequestBuilder = Box + Send + Sync>; +/// Result of the transaction import. +#[derive(Clone, Copy, Debug)] +pub enum TransactionImport { + /// Transaction is good but already known by the transaction pool. + KnownGood, + /// Transaction is good and not yet known. + NewGood, + /// Transaction is invalid. + Bad, + /// Transaction import was not performed. + None, +} + +/// Fuure resolving to transaction import result. +pub type TransactionImportFuture = Pin + Send>>; + /// Transaction pool interface pub trait TransactionPool: Send + Sync { /// Get transactions from the pool that are ready to be propagated. @@ -175,15 +193,11 @@ pub trait TransactionPool: Send + Sync { fn hash_of(&self, transaction: &B::Extrinsic) -> H; /// Import a transaction into the pool. /// - /// Peer reputation is changed by reputation_change if transaction is accepted by the pool. + /// This will return future. fn import( &self, - report_handle: ReportHandle, - who: PeerId, - reputation_change_good: ReputationChange, - reputation_change_bad: ReputationChange, transaction: B::Extrinsic, - ); + ) -> TransactionImportFuture; /// Notify the pool about transactions broadcast. fn on_broadcasted(&self, propagations: HashMap>); /// Get transaction by hash. @@ -209,12 +223,10 @@ impl TransactionPool for EmptyTransaction fn import( &self, - _report_handle: ReportHandle, - _who: PeerId, - _rep_change_good: ReputationChange, - _rep_change_bad: ReputationChange, _transaction: B::Extrinsic - ) {} + ) -> TransactionImportFuture { + Box::pin(future::ready(TransactionImport::KnownGood)) + } fn on_broadcasted(&self, _: HashMap>) {} @@ -260,8 +272,21 @@ pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> { /// Splits a Multiaddress into a Multiaddress and PeerId. pub fn parse_addr(mut addr: Multiaddr)-> Result<(PeerId, Multiaddr), ParseErr> { let who = match addr.pop() { - Some(multiaddr::Protocol::P2p(key)) => PeerId::from_multihash(key) - .map_err(|_| ParseErr::InvalidPeerId)?, + Some(multiaddr::Protocol::P2p(key)) => { + if !matches!(key.algorithm(), multiaddr::multihash::Code::Identity) { + // (note: this is the "person bowing" emoji) + log::warn!( + "🙇 You are using the peer ID {}. This peer ID uses a legacy, deprecated \ + representation that will no longer be supported in the future. \ + Please refresh it by performing a RPC query to the appropriate node, \ + by looking at its logs, or by using `subkey inspect-node-key` on its \ + private key.", + bs58::encode(key.as_bytes()).into_string() + ); + } + + PeerId::from_multihash(key).map_err(|_| ParseErr::InvalidPeerId)? + }, _ => return Err(ParseErr::PeerIdMissing), }; diff --git a/client/network/src/debug_info.rs b/client/network/src/debug_info.rs index e2803cde35a772e5e094919ef31b364af640c487..a11262caa59200c1a295ca6e6a1b157e75cd5c34 100644 --- a/client/network/src/debug_info.rs +++ b/client/network/src/debug_info.rs @@ -86,7 +86,7 @@ impl DebugInfoBehaviour { ) -> Self { let identify = { let proto_version = "/substrate/1.0".to_string(); - Identify::new(proto_version, user_agent, local_public_key.clone()) + Identify::new(proto_version, user_agent, local_public_key) }; DebugInfoBehaviour { diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index 56c08cc56cf1b0cd5b8a58ef2f447f7ae56f9036..f5c293b25128a8ece0bc22373981bdb0c7ba7c23 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -26,12 +26,12 @@ //! //! - mDNS. Discovers nodes on the local network by broadcasting UDP packets. //! -//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests in -//! order for nodes to propagate to us their view of the network. This is performed automatically -//! by the `DiscoveryBehaviour`. +//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests on the +//! configured Kademlia DHTs in order for nodes to propagate to us their view of the network. This +//! is performed automatically by the `DiscoveryBehaviour`. //! //! Additionally, the `DiscoveryBehaviour` is also capable of storing and loading value in the -//! network-wide DHT. +//! configured DHTs. //! //! ## Usage //! @@ -52,7 +52,7 @@ use ip_network::IpNetwork; use libp2p::core::{connection::{ConnectionId, ListenerId}, ConnectedPoint, Multiaddr, PeerId, PublicKey}; use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters, ProtocolsHandler}; use libp2p::swarm::protocols_handler::multi::MultiHandler; -use libp2p::kad::{Kademlia, KademliaConfig, KademliaEvent, Quorum, Record}; +use libp2p::kad::{Kademlia, KademliaConfig, KademliaEvent, QueryResult, Quorum, Record}; use libp2p::kad::GetClosestPeersError; use libp2p::kad::handler::KademliaHandler; use libp2p::kad::QueryId; @@ -62,12 +62,15 @@ use libp2p::swarm::toggle::Toggle; #[cfg(not(target_os = "unknown"))] use libp2p::mdns::{Mdns, MdnsEvent}; use libp2p::multiaddr::Protocol; -use log::{debug, info, trace, warn, error}; +use log::{debug, info, trace, warn}; use std::{cmp, collections::{HashMap, HashSet, VecDeque}, io, time::Duration}; use std::task::{Context, Poll}; use sp_core::hexdisplay::HexDisplay; /// `DiscoveryBehaviour` configuration. +/// +/// Note: In order to discover nodes or load and store values via Kademlia one has to add at least +/// one protocol via [`DiscoveryConfig::add_protocol`]. pub struct DiscoveryConfig { local_peer_id: PeerId, user_defined: Vec<(PeerId, Multiaddr)>, @@ -81,7 +84,7 @@ pub struct DiscoveryConfig { impl DiscoveryConfig { /// Create a default configuration with the given public key. pub fn new(local_public_key: PublicKey) -> Self { - let mut this = DiscoveryConfig { + DiscoveryConfig { local_peer_id: local_public_key.into_peer_id(), user_defined: Vec::new(), allow_private_ipv4: true, @@ -89,15 +92,7 @@ impl DiscoveryConfig { discovery_only_if_under_num: std::u64::MAX, enable_mdns: false, kademlias: HashMap::new() - }; - - // Temporary hack to retain backwards compatibility. - // We should eventually remove the special handling of DEFAULT_PROTO_NAME. - let proto_id = ProtocolId::from(libp2p::kad::protocol::DEFAULT_PROTO_NAME); - let proto_name = Vec::from(proto_id.as_bytes()); - this.add_kademlia(proto_id, proto_name); - - this + } } /// Set the number of active connections at which we pause discovery. @@ -182,7 +177,7 @@ impl DiscoveryConfig { kademlias: self.kademlias, next_kad_random_query: Delay::new(Duration::new(0, 0)), duration_to_next_kad: Duration::from_secs(1), - discoveries: VecDeque::new(), + pending_events: VecDeque::new(), local_peer_id: self.local_peer_id, num_connections: 0, allow_private_ipv4: self.allow_private_ipv4, @@ -218,8 +213,8 @@ pub struct DiscoveryBehaviour { next_kad_random_query: Delay, /// After `next_kad_random_query` triggers, the next one triggers after this duration. duration_to_next_kad: Duration, - /// Discovered nodes to return. - discoveries: VecDeque, + /// Events to return in priority when polled. + pending_events: VecDeque, /// Identity of our local node. local_peer_id: PeerId, /// Number of nodes we're currently connected to. @@ -253,7 +248,7 @@ impl DiscoveryBehaviour { for k in self.kademlias.values_mut() { k.add_address(&peer_id, addr.clone()) } - self.discoveries.push_back(peer_id.clone()); + self.pending_events.push_back(DiscoveryOut::Discovered(peer_id.clone())); self.user_defined.push((peer_id, addr)); } } @@ -277,7 +272,7 @@ impl DiscoveryBehaviour { /// A corresponding `ValueFound` or `ValueNotFound` event will later be generated. pub fn get_value(&mut self, key: &record::Key) { for k in self.kademlias.values_mut() { - k.get_record(key, Quorum::One) + k.get_record(key, Quorum::One); } } @@ -287,7 +282,10 @@ impl DiscoveryBehaviour { /// A corresponding `ValuePut` or `ValuePutFailed` event will later be generated. pub fn put_value(&mut self, key: record::Key, value: Vec) { for k in self.kademlias.values_mut() { - k.put_record(Record::new(key.clone(), value.clone()), Quorum::All) + if let Err(e) = k.put_record(Record::new(key.clone(), value.clone()), Quorum::All) { + warn!(target: "sub-libp2p", "Libp2p => Failed to put record: {:?}", e); + self.pending_events.push_back(DiscoveryOut::ValuePutFailed(key.clone())); + } } } @@ -490,7 +488,6 @@ impl NetworkBehaviour for DiscoveryBehaviour { } fn inject_expired_listen_addr(&mut self, addr: &Multiaddr) { - info!(target: "sub-libp2p", "No longer listening on {}", addr); for k in self.kademlias.values_mut() { NetworkBehaviour::inject_expired_listen_addr(k, addr) } @@ -509,14 +506,12 @@ impl NetworkBehaviour for DiscoveryBehaviour { } fn inject_listener_error(&mut self, id: ListenerId, err: &(dyn std::error::Error + 'static)) { - error!(target: "sub-libp2p", "Error on libp2p listener {:?}: {}", id, err); for k in self.kademlias.values_mut() { NetworkBehaviour::inject_listener_error(k, id, err) } } fn inject_listener_closed(&mut self, id: ListenerId, reason: Result<(), &io::Error>) { - error!(target: "sub-libp2p", "Libp2p listener {:?} closed", id); for k in self.kademlias.values_mut() { NetworkBehaviour::inject_listener_closed(k, id, reason) } @@ -533,8 +528,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { >, > { // Immediately process the content of `discovered`. - if let Some(peer_id) = self.discoveries.pop_front() { - let ev = DiscoveryOut::Discovered(peer_id); + if let Some(ev) = self.pending_events.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } @@ -546,7 +540,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { "Libp2p <= Starting random Kademlia request for {:?}", random_peer_id); for k in self.kademlias.values_mut() { - k.get_closest_peers(random_peer_id.clone()) + k.get_closest_peers(random_peer_id.clone()); } true } else { @@ -583,7 +577,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { let ev = DiscoveryOut::Discovered(peer); return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } - KademliaEvent::GetClosestPeersResult(res) => { + KademliaEvent::QueryResult { result: QueryResult::GetClosestPeers(res), .. } => { match res { Err(GetClosestPeersError::Timeout { key, peers }) => { debug!(target: "sub-libp2p", @@ -601,7 +595,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { } } } - KademliaEvent::GetRecordResult(res) => { + KademliaEvent::QueryResult { result: QueryResult::GetRecord(res), .. } => { let ev = match res { Ok(ok) => { let results = ok.records @@ -624,7 +618,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { }; return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } - KademliaEvent::PutRecordResult(res) => { + KademliaEvent::QueryResult { result: QueryResult::PutRecord(res), .. } => { let ev = match res { Ok(ok) => DiscoveryOut::ValuePut(ok.key), Err(e) => { @@ -635,7 +629,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { }; return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } - KademliaEvent::RepublishRecordResult(res) => { + KademliaEvent::QueryResult { result: QueryResult::RepublishRecord(res), .. } => { match res { Ok(ok) => debug!(target: "sub-libp2p", "Libp2p => Record republished: {:?}", @@ -680,9 +674,8 @@ impl NetworkBehaviour for DiscoveryBehaviour { continue; } - self.discoveries.extend(list.into_iter().map(|(peer_id, _)| peer_id)); - if let Some(peer_id) = self.discoveries.pop_front() { - let ev = DiscoveryOut::Discovered(peer_id); + self.pending_events.extend(list.map(|(peer_id, _)| DiscoveryOut::Discovered(peer_id))); + if let Some(ev) = self.pending_events.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } }, @@ -706,6 +699,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { #[cfg(test)] mod tests { + use crate::config::ProtocolId; use futures::prelude::*; use libp2p::identity::Keypair; use libp2p::Multiaddr; @@ -744,11 +738,15 @@ mod tests { }); let behaviour = { + let protocol_id: &[u8] = b"/test/kad/1.0.0"; + let mut config = DiscoveryConfig::new(keypair.public()); config.with_user_defined(user_defined.clone()) .allow_private_ipv4(true) .allow_non_globals_in_dht(true) - .discovery_limit(50); + .discovery_limit(50) + .add_protocol(ProtocolId::from(protocol_id)); + config.finish() }; diff --git a/client/network/src/error.rs b/client/network/src/error.rs index 158e75fcf1d721551a3f8cfb51f4a3d8b93b73f4..fed7a331da93c383707bbe83e082f76880bff828 100644 --- a/client/network/src/error.rs +++ b/client/network/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate network possible errors. diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs index 1ed0b905409061efc56dd43823eab96ebbb1df84..7cc5e8537159ebd4cc0baefaacb1b78a4282732e 100644 --- a/client/network/src/lib.rs +++ b/client/network/src/lib.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . #![warn(unused_extern_crates)] #![warn(missing_docs)] @@ -53,9 +54,10 @@ //! - mDNS. We perform a UDP broadcast on the local network. Nodes that listen may respond with //! their identity. More info [here](https://github.com/libp2p/specs/blob/master/discovery/mdns.md). //! mDNS can be disabled in the network configuration. -//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests in -//! order for nodes to propagate to us their view of the network. More information about Kademlia -//! can be found [on Wikipedia](https://en.wikipedia.org/wiki/Kademlia). +//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests on the +//! configured Kademlia DHTs (one per configured chain protocol) in order for nodes to propagate to +//! us their view of the network. More information about Kademlia can be found [on +//! Wikipedia](https://en.wikipedia.org/wiki/Kademlia). //! //! ## Connection establishment //! @@ -77,6 +79,7 @@ //! frames. Encryption and multiplexing are additionally negotiated again inside this channel. //! - DNS for addresses of the form `/dns4/example.com/tcp/5` or `/dns4/example.com/tcp/5/ws`. A //! node's address can contain a domain name. +//! - (All of the above using IPv6 instead of IPv4.) //! //! On top of the base-layer protocol, the [Noise](https://noiseprotocol.org/) protocol is //! negotiated and applied. The exact handshake protocol is experimental and is subject to change. @@ -109,7 +112,7 @@ //! to a disconnection. //! - **[`/ipfs/id/1.0.0`](https://github.com/libp2p/specs/tree/master/identify)**. We //! periodically open an ephemeral substream in order to ask information from the remote. -//! - **[`/ipfs/kad/1.0.0`](https://github.com/libp2p/specs/pull/108)**. We periodically open +//! - **[`//kad`](https://github.com/libp2p/specs/pull/108)**. We periodically open //! ephemeral substreams for Kademlia random walk queries. Each Kademlia query is done in a //! separate substream. //! diff --git a/client/network/src/light_client_handler.rs b/client/network/src/light_client_handler.rs index 5080d16ead68a80a0acde58aa43d8a618fe64a62..236ae817474ab943812a107ce1059191ad8df7d0 100644 --- a/client/network/src/light_client_handler.rs +++ b/client/network/src/light_client_handler.rs @@ -980,7 +980,9 @@ where let handler = request.connection.map_or(NotifyHandler::Any, NotifyHandler::One); let request_id = self.next_request_id(); - self.peers.get_mut(&peer).map(|p| p.status = PeerStatus::BusyWith(request_id)); + if let Some(p) = self.peers.get_mut(&peer) { + p.status = PeerStatus::BusyWith(request_id); + } self.outstanding.insert(request_id, request); let event = OutboundProtocol { diff --git a/client/network/src/network_state.rs b/client/network/src/network_state.rs index 00d53976ae8fc8960e9045b1dbab7d1621429f26..970a63faed4ea7ac8167bb8b4d987380f39f3861 100644 --- a/client/network/src/network_state.rs +++ b/client/network/src/network_state.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Information about the networking, for diagnostic purposes. //! diff --git a/client/network/src/on_demand_layer.rs b/client/network/src/on_demand_layer.rs index c8bd7f286778d0d531fc98c13342894df6382189..084172ee57c4f002c66c27e22bbe6dfc42f750fa 100644 --- a/client/network/src/on_demand_layer.rs +++ b/client/network/src/on_demand_layer.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! On-demand requests service. @@ -219,7 +221,7 @@ impl Future for RemoteResponse { fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { match self.receiver.poll_unpin(cx) { Poll::Ready(Ok(res)) => Poll::Ready(res), - Poll::Ready(Err(_)) => Poll::Ready(Err(From::from(ClientError::RemoteFetchCancelled))), + Poll::Ready(Err(_)) => Poll::Ready(Err(ClientError::RemoteFetchCancelled)), Poll::Pending => Poll::Pending, } } diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index 895624f08de6ae56d57615604388d52708f4c200..b3c08320f956b5a1adfb85d50c71320376047f63 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -1,29 +1,31 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::{ ExHashT, chain::{Client, FinalityProofProvider}, - config::{BoxFinalityProofRequestBuilder, ProtocolId, TransactionPool}, + config::{BoxFinalityProofRequestBuilder, ProtocolId, TransactionPool, TransactionImportFuture, TransactionImport}, error, utils::interval }; use bytes::{Bytes, BytesMut}; -use futures::prelude::*; +use futures::{prelude::*, stream::FuturesUnordered}; use generic_proto::{GenericProto, GenericProtoOut}; use libp2p::{Multiaddr, PeerId}; use libp2p::core::{ConnectedPoint, connection::{ConnectionId, ListenerId}}; @@ -78,6 +80,9 @@ const MAX_KNOWN_BLOCKS: usize = 1024; // ~32kb per peer + LruHashSet overhead /// Maximim number of known extrinsic hashes to keep for a peer. const MAX_KNOWN_EXTRINSICS: usize = 4096; // ~128kb per peer + overhead +/// Maximim number of transaction validation request we keep at any moment. +const MAX_PENDING_TRANSACTIONS: usize = 8192; + /// Current protocol version. pub(crate) const CURRENT_VERSION: u32 = 6; /// Lowest version we support @@ -101,6 +106,13 @@ mod rep { pub const UNEXPECTED_STATUS: Rep = Rep::new(-(1 << 20), "Unexpected status message"); /// Reputation change when we are a light client and a peer is behind us. pub const PEER_BEHIND_US_LIGHT: Rep = Rep::new(-(1 << 8), "Useless for a light peer"); + /// Reputation change when a peer sends us any extrinsic. + /// + /// This forces node to verify it, thus the negative value here. Once extrinsic is verified, + /// reputation change should be refunded with `ANY_EXTRINSIC_REFUND` + pub const ANY_EXTRINSIC: Rep = Rep::new(-(1 << 4), "Any extrinsic"); + /// Reputation change when a peer sends us any extrinsic that is not invalid. + pub const ANY_EXTRINSIC_REFUND: Rep = Rep::new(1 << 4, "Any extrinsic (refund)"); /// Reputation change when a peer sends us an extrinsic that we didn't know about. pub const GOOD_EXTRINSIC: Rep = Rep::new(1 << 7, "Good extrinsic"); /// Reputation change when a peer sends us a bad extrinsic. @@ -182,6 +194,24 @@ impl Metrics { } } +struct PendingTransaction { + validation: TransactionImportFuture, + peer_id: PeerId, +} + +impl Future for PendingTransaction { + type Output = (PeerId, TransactionImport); + + fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { + let this = Pin::into_inner(self); + if let Poll::Ready(import_result) = this.validation.poll_unpin(cx) { + return Poll::Ready((this.peer_id.clone(), import_result)); + } + + Poll::Pending + } +} + // Lock must always be taken in order declared here. pub struct Protocol { /// Interval at which we call `tick`. @@ -190,6 +220,8 @@ pub struct Protocol { propagate_timeout: Pin + Send>>, /// Pending list of messages to return from `poll` as a priority. pending_messages: VecDeque>, + /// Pending extrinsic verification tasks. + pending_transactions: FuturesUnordered, config: ProtocolConfig, genesis_hash: B::Hash, sync: ChainSync, @@ -310,7 +342,7 @@ impl BlockAnnouncesHandshake { let info = chain.info(); BlockAnnouncesHandshake { genesis_hash: info.genesis_hash, - roles: protocol_config.roles.into(), + roles: protocol_config.roles, best_number: info.best_number, best_hash: info.best_hash, } @@ -332,6 +364,7 @@ impl Protocol { /// Create a new instance. pub fn new( config: ProtocolConfig, + local_peer_id: PeerId, chain: Arc>, transaction_pool: Arc>, finality_proof_provider: Option>>, @@ -365,7 +398,13 @@ impl Protocol { let (peerset, peerset_handle) = sc_peerset::Peerset::from_config(peerset_config); let versions = &((MIN_VERSION as u8)..=(CURRENT_VERSION as u8)).collect::>(); - let mut behaviour = GenericProto::new(protocol_id.clone(), versions, peerset, queue_size_report); + let mut behaviour = GenericProto::new( + local_peer_id, + protocol_id.clone(), + versions, + peerset, + queue_size_report + ); let mut legacy_equiv_by_name = HashMap::new(); @@ -394,6 +433,7 @@ impl Protocol { tick_timeout: Box::pin(interval(TICK_TIMEOUT)), propagate_timeout: Box::pin(interval(PROPAGATE_TIMEOUT)), pending_messages: VecDeque::new(), + pending_transactions: FuturesUnordered::new(), config, context_data: ContextData { peers: HashMap::new(), @@ -503,28 +543,10 @@ impl Protocol { self.sync.num_sync_requests() } - /// Accepts a response from the legacy substream and determines what the corresponding - /// request was. - 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); - return None; - } - // Clear the request. If the response is invalid peer will be disconnected anyway. - let request = peer.block_request.take(); - if request.as_ref().map_or(false, |(_, r)| r.id == response.id) { - return request.map(|(_, r)| r) - } - trace!(target: "sync", "Unexpected response packet from {} ({})", who, response.id); - self.peerset_handle.report_peer(who.clone(), rep::UNEXPECTED_RESPONSE); - self.behaviour.disconnect_peer(&who); - } - None + /// Sync local state with the blockchain state. + pub fn update_chain(&mut self) { + let info = self.context_data.chain.info(); + self.sync.update_chain_info(&info.best_hash, info.best_number); } fn update_peer_info(&mut self, who: &PeerId) { @@ -551,7 +573,7 @@ impl Protocol { Ok(message) => message, Err(err) => { debug!(target: "sync", "Couldn't decode packet sent by {}: {:?}: {}", who, data, err.what()); - self.peerset_handle.report_peer(who.clone(), rep::BAD_MESSAGE); + self.peerset_handle.report_peer(who, rep::BAD_MESSAGE); return CustomMessageOutcome::None; } }; @@ -564,11 +586,9 @@ impl Protocol { GenericMessage::Status(s) => return 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.clone(), &r) { - let outcome = self.on_block_response(who.clone(), request, r); - self.update_peer_info(&who); - return outcome - } + let outcome = self.on_block_response(who.clone(), r); + self.update_peer_info(&who); + return outcome }, GenericMessage::BlockAnnounce(announce) => { let outcome = self.on_block_announce(who.clone(), announce); @@ -601,7 +621,7 @@ impl Protocol { GenericMessage::Consensus(msg) => return if self.protocol_name_by_engine.contains_key(&msg.engine_id) { CustomMessageOutcome::NotificationsReceived { - remote: who.clone(), + remote: who, messages: vec![(msg.engine_id, From::from(msg.data))], } } else { @@ -623,7 +643,7 @@ impl Protocol { return if !messages.is_empty() { CustomMessageOutcome::NotificationsReceived { - remote: who.clone(), + remote: who, messages, } } else { @@ -660,6 +680,10 @@ impl Protocol { ); } + fn update_peer_request(&mut self, who: &PeerId, request: &mut message::BlockRequest) { + update_peer_request::(&mut self.context_data.peers, who, request) + } + /// Called when a new peer is connected pub fn on_peer_connected(&mut self, who: PeerId) { trace!(target: "sync", "Connecting {}", who); @@ -681,7 +705,7 @@ impl Protocol { self.context_data.peers.remove(&peer) }; if let Some(_peer_data) = removed { - self.sync.peer_disconnected(peer.clone()); + self.sync.peer_disconnected(&peer); // Notify all the notification protocols as closed. CustomMessageOutcome::NotificationStreamClosed { @@ -742,9 +766,9 @@ impl Protocol { if blocks.len() >= max { break; } - let number = header.number().clone(); + let number = *header.number(); let hash = header.hash(); - let parent_hash = header.parent_hash().clone(); + let parent_hash = *header.parent_hash(); let justification = if get_justification { self.context_data.chain.justification(&BlockId::Hash(hash)).unwrap_or(None) } else { @@ -799,9 +823,34 @@ impl Protocol { pub fn on_block_response( &mut self, peer: PeerId, - request: message::BlockRequest, response: message::BlockResponse, ) -> CustomMessageOutcome { + let request = if let Some(ref mut p) = self.context_data.peers.get_mut(&peer) { + if p.obsolete_requests.remove(&response.id).is_some() { + trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", peer, response.id); + return CustomMessageOutcome::None; + } + // Clear the request. If the response is invalid peer will be disconnected anyway. + match p.block_request.take() { + Some((_, request)) if request.id == response.id => request, + Some(_) => { + trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", peer, response.id); + return CustomMessageOutcome::None; + } + None => { + trace!(target: "sync", "Unexpected response packet from unknown peer {}", peer); + self.behaviour.disconnect_peer(&peer); + self.peerset_handle.report_peer(peer, rep::UNEXPECTED_RESPONSE); + return CustomMessageOutcome::None; + } + } + } else { + trace!(target: "sync", "Unexpected response packet from unknown peer {}", peer); + self.behaviour.disconnect_peer(&peer); + self.peerset_handle.report_peer(peer, rep::UNEXPECTED_RESPONSE); + return CustomMessageOutcome::None; + }; + let blocks_range = || match ( response.blocks.first().and_then(|b| b.header.as_ref().map(|h| h.number())), response.blocks.last().and_then(|b| b.header.as_ref().map(|h| h.number())), @@ -843,11 +892,12 @@ impl Protocol { return CustomMessageOutcome::None } - match self.sync.on_block_data(peer, Some(request), response) { + match self.sync.on_block_data(&peer, Some(request), response) { Ok(sync::OnBlockData::Import(origin, blocks)) => CustomMessageOutcome::BlockImport(origin, blocks), - Ok(sync::OnBlockData::Request(peer, req)) => { + Ok(sync::OnBlockData::Request(peer, mut req)) => { if self.use_new_block_requests_protocol { + self.update_peer_request(&peer, &mut req); CustomMessageOutcome::BlockRequest { target: peer, request: req, @@ -866,6 +916,15 @@ impl Protocol { } } + /// Must be called in response to a [`CustomMessageOutcome::BlockRequest`] if it has failed. + pub fn on_block_request_failed( + &mut self, + peer: &PeerId, + ) { + self.peerset_handle.report_peer(peer.clone(), rep::TIMEOUT); + self.behaviour.disconnect_peer(peer); + } + /// Perform time based maintenance. /// /// > **Note**: This method normally doesn't have to be called except for testing purposes. @@ -1022,8 +1081,9 @@ impl Protocol { if info.roles.is_full() { match self.sync.new_peer(who.clone(), info.best_hash, info.best_number) { Ok(None) => (), - Ok(Some(req)) => { + Ok(Some(mut req)) => { if self.use_new_block_requests_protocol { + self.update_peer_request(&who, &mut req); self.pending_messages.push_back(CustomMessageOutcome::BlockRequest { target: who.clone(), request: req, @@ -1118,20 +1178,37 @@ impl Protocol { trace!(target: "sync", "Received {} extrinsics from {}", extrinsics.len(), who); if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { for t in extrinsics { + if self.pending_transactions.len() > MAX_PENDING_TRANSACTIONS { + debug!( + target: "sync", + "Ignoring any further transactions that exceed `MAX_PENDING_TRANSACTIONS`({}) limit", + MAX_PENDING_TRANSACTIONS, + ); + break; + } + let hash = self.transaction_pool.hash_of(&t); peer.known_extrinsics.insert(hash); - self.transaction_pool.import( - self.peerset_handle.clone().into(), - who.clone(), - rep::GOOD_EXTRINSIC, - rep::BAD_EXTRINSIC, - t, - ); + self.peerset_handle.report_peer(who.clone(), rep::ANY_EXTRINSIC); + + self.pending_transactions.push(PendingTransaction { + peer_id: who.clone(), + validation: self.transaction_pool.import(t), + }); } } } + fn on_handle_extrinsic_import(&mut self, who: PeerId, import: TransactionImport) { + match import { + TransactionImport::KnownGood => self.peerset_handle.report_peer(who, rep::ANY_EXTRINSIC_REFUND), + TransactionImport::NewGood => self.peerset_handle.report_peer(who, rep::GOOD_EXTRINSIC), + TransactionImport::Bad => self.peerset_handle.report_peer(who, rep::BAD_EXTRINSIC), + TransactionImport::None => {}, + } + } + /// Propagate one extrinsic. pub fn propagate_extrinsic( &mut self, @@ -1271,7 +1348,7 @@ impl Protocol { version: CURRENT_VERSION, min_supported_version: MIN_VERSION, genesis_hash: info.genesis_hash, - roles: self.config.roles.into(), + roles: self.config.roles, best_number: info.best_number, best_hash: info.best_hash, chain_status: Vec::new(), // TODO: find a way to make this backwards-compatible @@ -1297,7 +1374,7 @@ impl Protocol { message::BlockState::Normal => false, }; - match self.sync.on_block_announce(who.clone(), hash, &announce, is_their_best) { + match self.sync.on_block_announce(&who, hash, &announce, is_their_best) { sync::OnBlockAnnounce::Nothing => { // `on_block_announce` returns `OnBlockAnnounce::ImportHeader` // when we have all data required to import the block @@ -1317,7 +1394,7 @@ impl Protocol { // to import header from announced block let's construct response to request that normally would have // been sent over network (but it is not in our case) let blocks_to_import = self.sync.on_block_data( - who.clone(), + &who, None, message::generic::BlockResponse { id: 0, @@ -1342,8 +1419,9 @@ impl Protocol { Ok(sync::OnBlockData::Import(origin, blocks)) => { CustomMessageOutcome::BlockImport(origin, blocks) }, - Ok(sync::OnBlockData::Request(peer, req)) => { + Ok(sync::OnBlockData::Request(peer, mut req)) => { if self.use_new_block_requests_protocol { + self.update_peer_request(&peer, &mut req); CustomMessageOutcome::BlockRequest { target: peer, request: req, @@ -1361,17 +1439,6 @@ impl Protocol { } } - /// Call this when a block has been imported in the import queue - pub fn on_block_imported(&mut self, header: &B::Header, is_best: bool) { - if is_best { - self.sync.update_chain_info(header); - self.behaviour.set_notif_protocol_handshake( - &self.block_announces_protocol, - BlockAnnouncesHandshake::build(&self.config, &self.context_data.chain).encode() - ); - } - } - /// Call this when a block has been finalized. The sync layer may have some additional /// requesting to perform. pub fn on_block_finalized(&mut self, hash: B::Hash, header: &B::Header) { @@ -1436,12 +1503,23 @@ impl Protocol { /// A batch of blocks have been processed, with or without errors. /// Call this when a batch of blocks have been processed by the importqueue, with or without /// errors. - pub fn blocks_processed( + pub fn on_blocks_processed( &mut self, imported: usize, count: usize, results: Vec<(Result>, BlockImportError>, B::Hash)> ) { + let new_best = results.iter().rev().find_map(|r| match r { + (Ok(BlockImportResult::ImportedUnknown(n, aux, _)), hash) if aux.is_new_best => Some((*n, hash.clone())), + _ => None, + }); + if let Some((best_num, best_hash)) = new_best { + self.sync.update_chain_info(&best_hash, best_num); + self.behaviour.set_notif_protocol_handshake( + &self.block_announces_protocol, + BlockAnnouncesHandshake::build(&self.config, &self.context_data.chain).encode() + ); + } let results = self.sync.on_blocks_processed( imported, count, @@ -1449,8 +1527,9 @@ impl Protocol { ); for result in results { match result { - Ok((id, req)) => { + Ok((id, mut req)) => { if self.use_new_block_requests_protocol { + update_peer_request(&mut self.context_data.peers, &id, &mut req); self.pending_messages.push_back(CustomMessageOutcome::BlockRequest { target: id, request: req, @@ -1826,10 +1905,11 @@ pub enum CustomMessageOutcome { /// Messages have been received on one or more notifications protocols. NotificationsReceived { remote: PeerId, messages: Vec<(ConsensusEngineId, Bytes)> }, /// A new block request must be emitted. - /// Once you have the response, you must call `Protocol::on_block_response`. + /// You must later call either [`Protocol::on_block_response`] or + /// [`Protocol::on_block_request_failed`]. + /// Each peer can only have one active request. If a request already exists for this peer, it + /// must be silently discarded. /// It is the responsibility of the handler to ensure that a timeout exists. - /// If the request times out, or the peer responds in an invalid way, the peer has to be - /// disconnect. This will inform the state machine that the request it has emitted is stale. BlockRequest { target: PeerId, request: message::BlockRequest }, /// A new finality proof request must be emitted. /// Once you have the response, you must call `Protocol::on_finality_proof_response`. @@ -1852,7 +1932,7 @@ fn send_request( if let GenericMessage::BlockRequest(ref mut r) = message { if let Some(ref mut peer) = peers.get_mut(who) { r.id = peer.next_request_id; - peer.next_request_id = peer.next_request_id + 1; + peer.next_request_id += 1; if let Some((timestamp, request)) = peer.block_request.take() { trace!(target: "sync", "Request {} for {} is now obsolete.", request.id, who); peer.obsolete_requests.insert(request.id, timestamp); @@ -1863,6 +1943,22 @@ fn send_request( send_message::(behaviour, stats, who, None, message) } +fn update_peer_request( + peers: &mut HashMap>, + who: &PeerId, + request: &mut message::BlockRequest, +) { + if let Some(ref mut peer) = peers.get_mut(who) { + request.id = peer.next_request_id; + peer.next_request_id += 1; + if let Some((timestamp, request)) = peer.block_request.take() { + trace!(target: "sync", "Request {} for {} is now obsolete.", request.id, who); + peer.obsolete_requests.insert(request.id, timestamp); + } + peer.block_request = Some((Instant::now(), request.clone())); + } +} + fn send_message( behaviour: &mut GenericProto, stats: &mut HashMap<&'static str, PacketStats>, @@ -1940,10 +2036,11 @@ impl NetworkBehaviour for Protocol { self.propagate_extrinsics(); } - for (id, r) in self.sync.block_requests() { + for (id, mut r) in self.sync.block_requests() { if self.use_new_block_requests_protocol { + update_peer_request(&mut self.context_data.peers, &id, &mut r); let event = CustomMessageOutcome::BlockRequest { - target: id, + target: id.clone(), request: r, }; self.pending_messages.push_back(event); @@ -1953,12 +2050,13 @@ impl NetworkBehaviour for Protocol { &mut self.context_data.stats, &mut self.context_data.peers, &id, - GenericMessage::BlockRequest(r) + GenericMessage::BlockRequest(r), ) } } - for (id, r) in self.sync.justification_requests() { + for (id, mut r) in self.sync.justification_requests() { if self.use_new_block_requests_protocol { + update_peer_request(&mut self.context_data.peers, &id, &mut r); let event = CustomMessageOutcome::BlockRequest { target: id, request: r, @@ -1970,7 +2068,7 @@ impl NetworkBehaviour for Protocol { &mut self.context_data.stats, &mut self.context_data.peers, &id, - GenericMessage::BlockRequest(r) + GenericMessage::BlockRequest(r), ) } } @@ -1988,9 +2086,13 @@ impl NetworkBehaviour for Protocol { &mut self.context_data.stats, &mut self.context_data.peers, &id, - GenericMessage::FinalityProofRequest(r)) + GenericMessage::FinalityProofRequest(r), + ) } } + if let Poll::Ready(Some((peer_id, result))) = self.pending_transactions.poll_next_unpin(cx) { + self.on_handle_extrinsic_import(peer_id, result); + } if let Some(message) = self.pending_messages.pop_front() { return Poll::Ready(NetworkBehaviourAction::GenerateEvent(message)); } @@ -2010,11 +2112,11 @@ impl NetworkBehaviour for Protocol { let outcome = match event { GenericProtoOut::CustomProtocolOpen { peer_id, .. } => { - self.on_peer_connected(peer_id.clone()); + self.on_peer_connected(peer_id); CustomMessageOutcome::None } GenericProtoOut::CustomProtocolClosed { peer_id, .. } => { - self.on_peer_disconnected(peer_id.clone()) + self.on_peer_disconnected(peer_id) }, GenericProtoOut::LegacyMessage { peer_id, message } => self.on_custom_message(peer_id, message), @@ -2124,6 +2226,7 @@ mod tests { let (mut protocol, _) = Protocol::::new( ProtocolConfig::default(), + PeerId::random(), client.clone(), Arc::new(EmptyTransactionPool), None, diff --git a/client/network/src/protocol/generic_proto/behaviour.rs b/client/network/src/protocol/generic_proto/behaviour.rs index 3ce98dc11ed3c5c675f697ed520bf8e01667647b..cf6188726daae6f6a17d6741e7cbd4418cdbf031 100644 --- a/client/network/src/protocol/generic_proto/behaviour.rs +++ b/client/network/src/protocol/generic_proto/behaviour.rs @@ -34,7 +34,7 @@ use prometheus_endpoint::HistogramVec; use rand::distributions::{Distribution as _, Uniform}; use smallvec::SmallVec; use std::task::{Context, Poll}; -use std::{borrow::Cow, cmp, collections::hash_map::Entry}; +use std::{borrow::Cow, cmp, collections::{hash_map::Entry, VecDeque}}; use std::{error, mem, pin::Pin, str, time::Duration}; use wasm_timer::Instant; @@ -109,6 +109,9 @@ use wasm_timer::Instant; /// tries to connect, the connection is accepted. A ban only delays dialing attempts. /// pub struct GenericProto { + /// `PeerId` of the local node. + local_peer_id: PeerId, + /// Legacy protocol to open with peers. Never modified. legacy_protocol: RegisteredProtocol, @@ -123,6 +126,18 @@ pub struct GenericProto { /// List of peers in our state. peers: FnvHashMap, + /// The elements in `peers` occasionally contain `Delay` objects that we would normally have + /// to be polled one by one. In order to avoid doing so, as an optimization, every `Delay` is + /// instead put inside of `delays` and reference by a [`DelayId`]. This stream + /// yields `PeerId`s whose `DelayId` is potentially ready. + /// + /// By design, we never remove elements from this list. Elements are removed only when the + /// `Delay` triggers. As such, this stream may produce obsolete elements. + delays: stream::FuturesUnordered + Send>>>, + + /// [`DelayId`] to assign to the next delay. + next_delay_id: DelayId, + /// List of incoming messages we have sent to the peer set manager and that are waiting for an /// answer. incoming: SmallVec<[IncomingPeer; 6]>, @@ -132,12 +147,16 @@ pub struct GenericProto { next_incoming_index: sc_peerset::IncomingIndex, /// Events to produce from `poll()`. - events: SmallVec<[NetworkBehaviourAction; 4]>, + events: VecDeque>, /// If `Some`, report the message queue sizes on this `Histogram`. queue_size_report: Option, } +/// Identifier for a delay firing. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct DelayId(u64); + /// State of a peer we're connected to. #[derive(Debug)] enum PeerState { @@ -155,8 +174,8 @@ enum PeerState { /// The peerset requested that we connect to this peer. We are currently not connected. PendingRequest { - /// When to actually start dialing. - timer: futures_timer::Delay, + /// When to actually start dialing. References an entry in `delays`. + timer: DelayId, /// When the `timer` will trigger. timer_deadline: Instant, }, @@ -180,8 +199,8 @@ enum PeerState { DisabledPendingEnable { /// The connections that are currently open for custom protocol traffic. open: SmallVec<[ConnectionId; crate::MAX_CONNECTIONS_PER_PEER]>, - /// When to enable this remote. - timer: futures_timer::Delay, + /// When to enable this remote. References an entry in `delays`. + timer: DelayId, /// When the `timer` will trigger. timer_deadline: Instant, }, @@ -321,6 +340,7 @@ impl GenericProto { /// The `queue_size_report` is an optional Prometheus metric that can report the size of the /// messages queue. If passed, it must have one label for the protocol name. pub fn new( + local_peer_id: PeerId, protocol: impl Into, versions: &[u8], peerset: sc_peerset::Peerset, @@ -329,13 +349,16 @@ impl GenericProto { let legacy_protocol = RegisteredProtocol::new(protocol, versions); GenericProto { + local_peer_id, legacy_protocol, notif_protocols: Vec::new(), peerset, peers: FnvHashMap::default(), + delays: Default::default(), + next_delay_id: DelayId(0), incoming: SmallVec::new(), next_incoming_index: sc_peerset::IncomingIndex(0), - events: SmallVec::new(), + events: VecDeque::new(), queue_size_report, } } @@ -369,7 +392,7 @@ impl GenericProto { // Send an event to all the peers we're connected to, updating the handshake message. for (peer_id, _) in self.peers.iter().filter(|(_, state)| state.is_connected()) { - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), handler: NotifyHandler::All, event: NotifsHandlerIn::UpdateHandshake { @@ -441,7 +464,7 @@ impl GenericProto { debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); self.peerset.dropped(peer_id.clone()); debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, @@ -466,7 +489,7 @@ impl GenericProto { inc.alive = false; debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, @@ -507,9 +530,18 @@ impl GenericProto { /// /// Can be called multiple times with the same `PeerId`s. pub fn add_discovered_nodes(&mut self, peer_ids: impl Iterator) { - self.peerset.discovered(peer_ids.into_iter().map(|peer_id| { + let local_peer_id = &self.local_peer_id; + self.peerset.discovered(peer_ids.filter_map(|peer_id| { + if peer_id == *local_peer_id { + error!( + target: "sub-libp2p", + "Discovered our own identity. This is a minor inconsequential bug." + ); + return None; + } + debug!(target: "sub-libp2p", "PSM <= Discovered({:?})", peer_id); - peer_id + Some(peer_id) })); } @@ -548,7 +580,7 @@ impl GenericProto { ); trace!(target: "sub-libp2p", "Handler({:?}) <= Packet", target); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: target.clone(), handler: NotifyHandler::One(conn), event: NotifsHandlerIn::SendNotification { @@ -578,7 +610,7 @@ impl GenericProto { trace!(target: "sub-libp2p", "External API => Packet for {:?}", target); trace!(target: "sub-libp2p", "Handler({:?}) <= Packet", target); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: target.clone(), handler: NotifyHandler::One(conn), event: NotifsHandlerIn::SendLegacy { @@ -600,7 +632,7 @@ impl GenericProto { // 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 { + self.events.push_back(NetworkBehaviourAction::DialPeer { peer_id: entry.key().clone(), condition: DialPeerCondition::Disconnected }); @@ -613,18 +645,28 @@ impl GenericProto { match mem::replace(occ_entry.get_mut(), PeerState::Poisoned) { PeerState::Banned { ref until } if *until > now => { + let peer_id = occ_entry.key().clone(); debug!(target: "sub-libp2p", "PSM => Connect({:?}): Will start to connect at \ - until {:?}", occ_entry.key(), until); + until {:?}", peer_id, until); + + let delay_id = self.next_delay_id; + self.next_delay_id.0 += 1; + let delay = futures_timer::Delay::new(*until - now); + self.delays.push(async move { + delay.await; + (delay_id, peer_id) + }.boxed()); + *occ_entry.into_mut() = PeerState::PendingRequest { - timer: futures_timer::Delay::new(until.clone() - now), - timer_deadline: until.clone(), + timer: delay_id, + timer_deadline: *until, }; }, 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 { + self.events.push_back(NetworkBehaviourAction::DialPeer { peer_id: occ_entry.key().clone(), condition: DialPeerCondition::Disconnected }); @@ -635,12 +677,22 @@ impl GenericProto { open, banned_until: Some(ref banned) } if *banned > now => { + let peer_id = occ_entry.key().clone(); debug!(target: "sub-libp2p", "PSM => Connect({:?}): But peer is banned until {:?}", - occ_entry.key(), banned); + peer_id, banned); + + let delay_id = self.next_delay_id; + self.next_delay_id.0 += 1; + let delay = futures_timer::Delay::new(*banned - now); + self.delays.push(async move { + delay.await; + (delay_id, peer_id) + }.boxed()); + *occ_entry.into_mut() = PeerState::DisabledPendingEnable { open, - timer: futures_timer::Delay::new(banned.clone() - now), - timer_deadline: banned.clone(), + timer: delay_id, + timer_deadline: *banned, }; }, @@ -648,7 +700,7 @@ impl GenericProto { debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling connections.", occ_entry.key()); debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: occ_entry.key().clone(), handler: NotifyHandler::All, event: NotifsHandlerIn::Enable, @@ -667,7 +719,7 @@ impl GenericProto { incoming for incoming peer") } debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: occ_entry.key().clone(), handler: NotifyHandler::All, event: NotifsHandlerIn::Enable, @@ -732,7 +784,7 @@ impl GenericProto { PeerState::Enabled { open } => { debug!(target: "sub-libp2p", "PSM => Drop({:?}): Disabling connections.", entry.key()); debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", entry.key()); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: entry.key().clone(), handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, @@ -787,7 +839,7 @@ impl GenericProto { debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Enabling connections.", index, incoming.peer_id); debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", incoming.peer_id); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: incoming.peer_id, handler: NotifyHandler::All, event: NotifsHandlerIn::Enable, @@ -810,7 +862,7 @@ impl GenericProto { }; if !incoming.alive { - error!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Obsolete incoming, \ + debug!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Obsolete incoming, \ ignoring", index, incoming.peer_id); return } @@ -820,7 +872,7 @@ impl GenericProto { debug!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Rejecting connections.", index, incoming.peer_id); debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", incoming.peer_id); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: incoming.peer_id, handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, @@ -867,7 +919,7 @@ impl NetworkBehaviour for GenericProto { peer_id, endpoint ); *st = PeerState::Enabled { open: SmallVec::new() }; - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), handler: NotifyHandler::One(*conn), event: NotifsHandlerIn::Enable @@ -879,7 +931,7 @@ impl NetworkBehaviour for GenericProto { // this peer", and not "banned" in the sense that we would refuse the peer altogether. (st @ &mut PeerState::Poisoned, endpoint @ ConnectedPoint::Listener { .. }) | (st @ &mut PeerState::Banned { .. }, endpoint @ ConnectedPoint::Listener { .. }) => { - let incoming_id = self.next_incoming_index.clone(); + let incoming_id = self.next_incoming_index; self.next_incoming_index.0 = match self.next_incoming_index.0.checked_add(1) { Some(v) => v, None => { @@ -911,7 +963,7 @@ impl NetworkBehaviour for GenericProto { "Libp2p => Connected({},{:?}): Not requested by PSM, disabling.", peer_id, endpoint); *st = PeerState::Disabled { open: SmallVec::new(), banned_until }; - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), handler: NotifyHandler::One(*conn), event: NotifsHandlerIn::Disable @@ -927,7 +979,7 @@ impl NetworkBehaviour for GenericProto { (PeerState::Enabled { .. }, _) => { debug!(target: "sub-libp2p", "Handler({},{:?}) <= Enable secondary connection", peer_id, conn); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), handler: NotifyHandler::One(*conn), event: NotifsHandlerIn::Enable @@ -937,7 +989,7 @@ impl NetworkBehaviour for GenericProto { (PeerState::Disabled { .. }, _) | (PeerState::DisabledPendingEnable { .. }, _) => { debug!(target: "sub-libp2p", "Handler({},{:?}) <= Disable secondary connection", peer_id, conn); - self.events.push(NetworkBehaviourAction::NotifyHandler { + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: peer_id.clone(), handler: NotifyHandler::One(*conn), event: NotifsHandlerIn::Disable @@ -965,7 +1017,7 @@ impl NetworkBehaviour for GenericProto { reason: "Disconnected by libp2p".into(), }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); } } _ => {} @@ -981,14 +1033,30 @@ impl NetworkBehaviour for GenericProto { "`inject_disconnected` called for unknown peer {}", peer_id), - Some(PeerState::Disabled { banned_until, .. }) => { + Some(PeerState::Disabled { open, banned_until, .. }) => { + if !open.is_empty() { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch: disconnected from {} with non-empty list of connections", + peer_id + ); + } debug!(target: "sub-libp2p", "Libp2p => Disconnected({}): Was disabled.", peer_id); if let Some(until) = banned_until { self.peers.insert(peer_id.clone(), PeerState::Banned { until }); } } - Some(PeerState::DisabledPendingEnable { timer_deadline, .. }) => { + Some(PeerState::DisabledPendingEnable { open, timer_deadline, .. }) => { + if !open.is_empty() { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch: disconnected from {} with non-empty list of connections", + peer_id + ); + } debug!(target: "sub-libp2p", "Libp2p => Disconnected({}): Was disabled but pending enable.", peer_id); @@ -997,7 +1065,15 @@ impl NetworkBehaviour for GenericProto { self.peers.insert(peer_id.clone(), PeerState::Banned { until: timer_deadline }); } - Some(PeerState::Enabled { .. }) => { + Some(PeerState::Enabled { open, .. }) => { + if !open.is_empty() { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch: disconnected from {} with non-empty list of connections", + peer_id + ); + } debug!(target: "sub-libp2p", "Libp2p => Disconnected({}): Was enabled.", peer_id); debug!(target: "sub-libp2p", "PSM <= Dropped({})", peer_id); self.peerset.dropped(peer_id.clone()); @@ -1088,34 +1164,51 @@ impl NetworkBehaviour for GenericProto { let last = match mem::replace(entry.get_mut(), PeerState::Poisoned) { PeerState::Enabled { mut open } => { - debug_assert!(open.iter().any(|c| c == &connection)); - open.retain(|c| c != &connection); + if let Some(pos) = open.iter().position(|c| c == &connection) { + open.remove(pos); + } else { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch with {}: unknown closed connection", + source + ); + } + // TODO: We switch the entire peer state to "disabled" because of possible + // race conditions involving the legacy substream. + // Once https://github.com/paritytech/substrate/issues/5670 is done, this + // should be changed to stay in the `Enabled` state. debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", source); - self.events.push(NetworkBehaviourAction::NotifyHandler { + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", source); + self.peerset.dropped(source.clone()); + self.events.push_back(NetworkBehaviourAction::NotifyHandler { peer_id: source.clone(), - handler: NotifyHandler::One(connection), + handler: NotifyHandler::All, event: NotifsHandlerIn::Disable, }); let last = open.is_empty(); - if last { - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", source); - self.peerset.dropped(source.clone()); - *entry.into_mut() = PeerState::Disabled { - open, - banned_until: None - }; - } else { - *entry.into_mut() = PeerState::Enabled { open }; - } + *entry.into_mut() = PeerState::Disabled { + open, + banned_until: None + }; last }, PeerState::Disabled { mut open, banned_until } => { - debug_assert!(open.iter().any(|c| c == &connection)); - open.retain(|c| c != &connection); + if let Some(pos) = open.iter().position(|c| c == &connection) { + open.remove(pos); + } else { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch with {}: unknown closed connection", + source + ); + } + let last = open.is_empty(); *entry.into_mut() = PeerState::Disabled { open, @@ -1128,8 +1221,17 @@ impl NetworkBehaviour for GenericProto { timer, timer_deadline } => { - debug_assert!(open.iter().any(|c| c == &connection)); - open.retain(|c| c != &connection); + if let Some(pos) = open.iter().position(|c| c == &connection) { + open.remove(pos); + } else { + debug_assert!(false); + error!( + target: "sub-libp2p", + "State mismatch with {}: unknown closed connection", + source + ); + } + let last = open.is_empty(); *entry.into_mut() = PeerState::DisabledPendingEnable { open, @@ -1150,9 +1252,9 @@ impl NetworkBehaviour for GenericProto { debug!(target: "sub-libp2p", "External API <= Closed({:?})", source); let event = GenericProtoOut::CustomProtocolClosed { reason, - peer_id: source.clone(), + peer_id: source, }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); } else { debug!(target: "sub-libp2p", "Secondary connection closed custom protocol."); } @@ -1168,7 +1270,15 @@ impl NetworkBehaviour for GenericProto { Some(PeerState::DisabledPendingEnable { ref mut open, .. }) | Some(PeerState::Disabled { ref mut open, .. }) => { let first = open.is_empty(); - open.push(connection); + if !open.iter().any(|c| *c == connection) { + open.push(connection); + } else { + error!( + target: "sub-libp2p", + "State mismatch: connection with {} opened a second time", + source + ); + } first } state => { @@ -1182,7 +1292,7 @@ impl NetworkBehaviour for GenericProto { if first { debug!(target: "sub-libp2p", "External API <= Open({:?})", source); let event = GenericProtoOut::CustomProtocolOpen { peer_id: source }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); } else { debug!(target: "sub-libp2p", "Secondary connection opened custom protocol."); } @@ -1197,7 +1307,7 @@ impl NetworkBehaviour for GenericProto { message, }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); } NotifsHandlerOut::Notification { protocol_name, message } => { @@ -1215,7 +1325,7 @@ impl NetworkBehaviour for GenericProto { message, }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + self.events.push_back(NetworkBehaviourAction::GenerateEvent(event)); } NotifsHandlerOut::Clogged { messages } => { @@ -1224,7 +1334,7 @@ impl NetworkBehaviour for GenericProto { 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(GenericProtoOut::Clogged { + self.events.push_back(NetworkBehaviourAction::GenerateEvent(GenericProtoOut::Clogged { peer_id: source, messages, })); @@ -1263,6 +1373,10 @@ impl NetworkBehaviour for GenericProto { Self::OutEvent, >, > { + if let Some(event) = self.events.pop_front() { + return Poll::Ready(event); + } + // Poll for instructions from the peerset. // Note that the peerset is a *best effort* crate, and we have to use defensive programming. loop { @@ -1287,51 +1401,43 @@ impl NetworkBehaviour for GenericProto { } } - for (peer_id, peer_state) in self.peers.iter_mut() { - match mem::replace(peer_state, PeerState::Poisoned) { - PeerState::PendingRequest { mut timer, timer_deadline } => { - if let Poll::Pending = Pin::new(&mut timer).poll(cx) { - *peer_state = PeerState::PendingRequest { timer, timer_deadline }; - continue; - } - + while let Poll::Ready(Some((delay_id, peer_id))) = + Pin::new(&mut self.delays).poll_next(cx) { + let peer_state = match self.peers.get_mut(&peer_id) { + Some(s) => s, + // We intentionally never remove elements from `delays`, and it may + // thus contain peers which are now gone. This is a normal situation. + None => continue, + }; + + match peer_state { + PeerState::PendingRequest { timer, .. } if *timer == delay_id => { debug!(target: "sub-libp2p", "Libp2p <= Dial {:?} now that ban has expired", peer_id); - self.events.push(NetworkBehaviourAction::DialPeer { - peer_id: peer_id.clone(), + self.events.push_back(NetworkBehaviourAction::DialPeer { + peer_id, condition: DialPeerCondition::Disconnected }); *peer_state = PeerState::Requested; } - PeerState::DisabledPendingEnable { - mut timer, - open, - timer_deadline - } => { - if let Poll::Pending = Pin::new(&mut timer).poll(cx) { - *peer_state = PeerState::DisabledPendingEnable { - timer, - open, - timer_deadline - }; - continue; - } - + PeerState::DisabledPendingEnable { timer, open, .. } if *timer == delay_id => { debug!(target: "sub-libp2p", "Handler({:?}) <= Enable (ban expired)", peer_id); - self.events.push(NetworkBehaviourAction::NotifyHandler { - peer_id: peer_id.clone(), + self.events.push_back(NetworkBehaviourAction::NotifyHandler { + peer_id, handler: NotifyHandler::All, event: NotifsHandlerIn::Enable, }); - *peer_state = PeerState::Enabled { open }; + *peer_state = PeerState::Enabled { open: mem::replace(open, Default::default()) }; } - st @ _ => *peer_state = st, + // We intentionally never remove elements from `delays`, and it may + // thus contain obsolete entries. This is a normal situation. + _ => {}, } } - if !self.events.is_empty() { - return Poll::Ready(self.events.remove(0)) + if let Some(event) = self.events.pop_front() { + return Poll::Ready(event); } Poll::Pending diff --git a/client/network/src/protocol/generic_proto/handler.rs b/client/network/src/protocol/generic_proto/handler.rs index f0e2fc4bb8a8d70af5ef58298fa6d45be07228d8..3b4469a872598f6f0b9c26b7647020a70ab5acc8 100644 --- a/client/network/src/protocol/generic_proto/handler.rs +++ b/client/network/src/protocol/generic_proto/handler.rs @@ -1,19 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . pub use self::group::{NotifsHandlerProto, NotifsHandler, NotifsHandlerIn, NotifsHandlerOut}; pub use self::legacy::ConnectionKillError as LegacyConnectionKillError; diff --git a/client/network/src/protocol/generic_proto/handler/group.rs b/client/network/src/protocol/generic_proto/handler/group.rs index 0e453a368c222c38795439d8510240aa3fd93268..625916a05e4a4aa624361c1d596ed84d12165232 100644 --- a/client/network/src/protocol/generic_proto/handler/group.rs +++ b/client/network/src/protocol/generic_proto/handler/group.rs @@ -483,35 +483,35 @@ impl ProtocolsHandler for NotifsHandler { ) -> Poll< ProtocolsHandlerEvent > { - while let Poll::Ready(ev) = self.legacy.poll(cx) { - match ev { + if let Poll::Ready(ev) = self.legacy.poll(cx) { + return match ev { ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol, info: () } => - return Poll::Ready(ProtocolsHandlerEvent::OutboundSubstreamRequest { + Poll::Ready(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: protocol.map_upgrade(EitherUpgrade::B), info: None, }), ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomProtocolOpen { endpoint, .. }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( + Poll::Ready(ProtocolsHandlerEvent::Custom( NotifsHandlerOut::Open { endpoint } )), ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomProtocolClosed { endpoint, reason }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( + Poll::Ready(ProtocolsHandlerEvent::Custom( NotifsHandlerOut::Closed { endpoint, reason } )), ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::CustomMessage { message }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( + Poll::Ready(ProtocolsHandlerEvent::Custom( NotifsHandlerOut::CustomMessage { message } )), ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::Clogged { messages }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( + Poll::Ready(ProtocolsHandlerEvent::Custom( NotifsHandlerOut::Clogged { messages } )), ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::ProtocolError { is_severe, error }) => - return Poll::Ready(ProtocolsHandlerEvent::Custom( + Poll::Ready(ProtocolsHandlerEvent::Custom( NotifsHandlerOut::ProtocolError { is_severe, error } )), ProtocolsHandlerEvent::Close(err) => - return Poll::Ready(ProtocolsHandlerEvent::Close(EitherError::B(err))), + Poll::Ready(ProtocolsHandlerEvent::Close(EitherError::B(err))), } } diff --git a/client/network/src/protocol/generic_proto/handler/legacy.rs b/client/network/src/protocol/generic_proto/handler/legacy.rs index bc84fd847c9c4ba44dbffcf5a7735c18c39f7776..c7de2d265e96fdf66f567366bd10fd6cf8ece265 100644 --- a/client/network/src/protocol/generic_proto/handler/legacy.rs +++ b/client/network/src/protocol/generic_proto/handler/legacy.rs @@ -30,7 +30,7 @@ use libp2p::swarm::{ }; use log::{debug, error}; use smallvec::{smallvec, SmallVec}; -use std::{borrow::Cow, error, fmt, io, mem, time::Duration}; +use std::{borrow::Cow, collections::VecDeque, error, fmt, io, mem, time::Duration}; use std::{pin::Pin, task::{Context, Poll}}; /// Implements the `IntoProtocolsHandler` trait of libp2p. @@ -115,9 +115,9 @@ impl IntoProtocolsHandler for LegacyProtoHandlerProto { remote_peer_id: remote_peer_id.clone(), state: ProtocolState::Init { substreams: SmallVec::new(), - init_deadline: Delay::new(Duration::from_secs(5)) + init_deadline: Delay::new(Duration::from_secs(20)) }, - events_queue: SmallVec::new(), + events_queue: VecDeque::new(), } } } @@ -142,7 +142,7 @@ pub struct LegacyProtoHandler { /// /// This queue must only ever be modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent; 16]>, + events_queue: VecDeque>, } /// State of the handler. @@ -277,7 +277,7 @@ impl LegacyProtoHandler { ProtocolState::Init { substreams: incoming, .. } => { if incoming.is_empty() { if let ConnectedPoint::Dialer { .. } = self.endpoint { - self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + self.events_queue.push_back(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(self.protocol.clone()), info: (), }); @@ -290,7 +290,7 @@ impl LegacyProtoHandler { version: incoming[0].protocol_version(), endpoint: self.endpoint.clone() }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(event)); ProtocolState::Normal { substreams: incoming.into_iter().collect(), shutdown: SmallVec::new() @@ -353,26 +353,26 @@ impl LegacyProtoHandler { ProtocolState::Init { substreams, mut init_deadline } => { match Pin::new(&mut init_deadline).poll(cx) { Poll::Ready(()) => { - init_deadline = Delay::new(Duration::from_secs(60)); error!(target: "sub-libp2p", "Handler initialization process is too long \ - with {:?}", self.remote_peer_id) + with {:?}", self.remote_peer_id); + self.state = ProtocolState::KillAsap; }, - Poll::Pending => {} + Poll::Pending => { + self.state = ProtocolState::Init { substreams, init_deadline }; + } } - self.state = ProtocolState::Init { substreams, init_deadline }; None } ProtocolState::Opening { mut deadline } => { match Pin::new(&mut deadline).poll(cx) { Poll::Ready(()) => { - deadline = Delay::new(Duration::from_secs(60)); let event = LegacyProtoHandlerOut::ProtocolError { is_severe: true, error: "Timeout when opening protocol".to_string().into(), }; - self.state = ProtocolState::Opening { deadline }; + self.state = ProtocolState::KillAsap; Some(ProtocolsHandlerEvent::Custom(event)) }, Poll::Pending => { @@ -488,7 +488,7 @@ impl LegacyProtoHandler { version: substream.protocol_version(), endpoint: self.endpoint.clone() }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(event)); ProtocolState::Normal { substreams: smallvec![substream], shutdown: SmallVec::new() @@ -565,7 +565,7 @@ impl ProtocolsHandler for LegacyProtoHandler { _ => false, }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::ProtocolError { + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(LegacyProtoHandlerOut::ProtocolError { is_severe, error: Box::new(err), })); @@ -587,8 +587,7 @@ impl ProtocolsHandler for LegacyProtoHandler { ProtocolsHandlerEvent > { // Flush the events queue if necessary. - if !self.events_queue.is_empty() { - let event = self.events_queue.remove(0); + if let Some(event) = self.events_queue.pop_front() { return Poll::Ready(event) } diff --git a/client/network/src/protocol/generic_proto/handler/notif_in.rs b/client/network/src/protocol/generic_proto/handler/notif_in.rs index 83923154bd6256de3bb4e983796807093f7019ad..be78fb970e90b2524fd1478f48462e159dd1b28d 100644 --- a/client/network/src/protocol/generic_proto/handler/notif_in.rs +++ b/client/network/src/protocol/generic_proto/handler/notif_in.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Implementations of the `IntoProtocolsHandler` and `ProtocolsHandler` traits for ingoing //! substreams for a single gossiping protocol. @@ -35,8 +37,7 @@ use libp2p::swarm::{ NegotiatedSubstream, }; use log::{error, warn}; -use smallvec::SmallVec; -use std::{borrow::Cow, fmt, pin::Pin, task::{Context, Poll}}; +use std::{borrow::Cow, collections::VecDeque, fmt, pin::Pin, task::{Context, Poll}}; /// Implements the `IntoProtocolsHandler` trait of libp2p. /// @@ -68,7 +69,7 @@ pub struct NotifsInHandler { /// /// This queue is only ever modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent; 16]>, + events_queue: VecDeque>, } /// Event that can be received by a `NotifsInHandler`. @@ -128,7 +129,7 @@ impl IntoProtocolsHandler for NotifsInHandlerProto { in_protocol: self.in_protocol, substream: None, pending_accept_refuses: 0, - events_queue: SmallVec::new(), + events_queue: VecDeque::new(), } } } @@ -158,7 +159,7 @@ impl ProtocolsHandler for NotifsInHandler { ) { // If a substream already exists, we drop it and replace it with the new incoming one. if self.substream.is_some() { - self.events_queue.push(ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::Closed)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::Closed)); } // Note that we drop the existing substream, which will send an equivalent to a TCP "RST" @@ -169,7 +170,7 @@ impl ProtocolsHandler for NotifsInHandler { // and we can't close "more" than that anyway. self.substream = Some(proto); - self.events_queue.push(ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::OpenRequest(msg))); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(NotifsInHandlerOut::OpenRequest(msg))); self.pending_accept_refuses = self.pending_accept_refuses .checked_add(1) .unwrap_or_else(|| { @@ -231,8 +232,7 @@ impl ProtocolsHandler for NotifsInHandler { ProtocolsHandlerEvent > { // Flush the events queue if necessary. - if !self.events_queue.is_empty() { - let event = self.events_queue.remove(0); + if let Some(event) = self.events_queue.pop_front() { return Poll::Ready(event) } diff --git a/client/network/src/protocol/generic_proto/handler/notif_out.rs b/client/network/src/protocol/generic_proto/handler/notif_out.rs index b5d6cd61ada2a9e54bfa5873e0f7992ab1dfcfcb..6b97ad67e34c696f58996a8c13f983f0486b84fa 100644 --- a/client/network/src/protocol/generic_proto/handler/notif_out.rs +++ b/client/network/src/protocol/generic_proto/handler/notif_out.rs @@ -35,8 +35,7 @@ use libp2p::swarm::{ }; use log::{debug, warn, error}; use prometheus_endpoint::Histogram; -use smallvec::SmallVec; -use std::{borrow::Cow, fmt, mem, pin::Pin, task::{Context, Poll}, time::Duration}; +use std::{borrow::Cow, collections::VecDeque, fmt, mem, pin::Pin, task::{Context, Poll}, time::Duration}; use wasm_timer::Instant; /// Maximum duration to open a substream and receive the handshake message. After that, we @@ -85,7 +84,7 @@ impl IntoProtocolsHandler for NotifsOutHandlerProto { when_connection_open: Instant::now(), queue_size_report: self.queue_size_report, state: State::Disabled, - events_queue: SmallVec::new(), + events_queue: VecDeque::new(), peer_id: peer_id.clone(), } } @@ -116,7 +115,7 @@ pub struct NotifsOutHandler { /// /// This queue must only ever be modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent; 16]>, + events_queue: VecDeque>, /// Who we are connected to. peer_id: PeerId, @@ -247,7 +246,7 @@ impl ProtocolsHandler for NotifsOutHandler { match mem::replace(&mut self.state, State::Poisoned) { State::Opening { initial_message } => { let ev = NotifsOutHandlerOut::Open { handshake: handshake_msg }; - self.events_queue.push(ProtocolsHandlerEvent::Custom(ev)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(ev)); self.state = State::Open { substream, initial_message }; }, // If the handler was disabled while we were negotiating the protocol, immediately @@ -267,7 +266,7 @@ impl ProtocolsHandler for NotifsOutHandler { match mem::replace(&mut self.state, State::Poisoned) { State::Disabled => { let proto = NotificationsOut::new(self.protocol_name.clone(), initial_message.clone()); - self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + self.events_queue.push_back(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(proto).with_timeout(OPEN_TIMEOUT), info: (), }); @@ -287,7 +286,7 @@ impl ProtocolsHandler for NotifsOutHandler { } let proto = NotificationsOut::new(self.protocol_name.clone(), initial_message.clone()); - self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + self.events_queue.push_back(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(proto).with_timeout(OPEN_TIMEOUT), info: (), }); @@ -347,7 +346,7 @@ impl ProtocolsHandler for NotifsOutHandler { State::Opening { .. } => { self.state = State::Refused; let ev = NotifsOutHandlerOut::Refused; - self.events_queue.push(ProtocolsHandlerEvent::Custom(ev)); + self.events_queue.push_back(ProtocolsHandlerEvent::Custom(ev)); }, State::DisabledOpening => self.state = State::Disabled, State::Poisoned => error!("☎️ Notifications handler in a poisoned state"), @@ -371,9 +370,8 @@ impl ProtocolsHandler for NotifsOutHandler { cx: &mut Context, ) -> Poll> { // Flush the events queue if necessary. - if !self.events_queue.is_empty() { - let event = self.events_queue.remove(0); - return Poll::Ready(event); + if let Some(event) = self.events_queue.pop_front() { + return Poll::Ready(event) } match &mut self.state { @@ -385,7 +383,7 @@ impl ProtocolsHandler for NotifsOutHandler { let initial_message = mem::replace(initial_message, Vec::new()); self.state = State::Opening { initial_message: initial_message.clone() }; let proto = NotificationsOut::new(self.protocol_name.clone(), initial_message); - self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + self.events_queue.push_back(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(proto).with_timeout(OPEN_TIMEOUT), info: (), }); diff --git a/client/network/src/protocol/generic_proto/tests.rs b/client/network/src/protocol/generic_proto/tests.rs index 1bc6e745f887685af41a6c9cfdfc05da84af7918..de02ac5f3468d20bd3e9bfabd13597c5b33614a1 100644 --- a/client/network/src/protocol/generic_proto/tests.rs +++ b/client/network/src/protocol/generic_proto/tests.rs @@ -42,6 +42,7 @@ fn build_nodes() -> (Swarm, Swarm) { for index in 0 .. 2 { let keypair = keypairs[index].clone(); + let local_peer_id = keypair.public().into_peer_id(); let transport = libp2p::core::transport::MemoryTransport .and_then(move |out, endpoint| { let secio = libp2p::secio::SecioConfig::new(keypair); @@ -82,7 +83,7 @@ fn build_nodes() -> (Swarm, Swarm) { }); let behaviour = CustomProtoWithAddr { - inner: GenericProto::new(&b"test"[..], &[1], peerset, None), + inner: GenericProto::new(local_peer_id, &b"test"[..], &[1], peerset, None), addrs: addrs .iter() .enumerate() diff --git a/client/network/src/protocol/generic_proto/upgrade.rs b/client/network/src/protocol/generic_proto/upgrade.rs index 36f826336532619479b94876776c65e8636f8c57..6322a10b572a9fa1e9d60566343e513fc2a6f15a 100644 --- a/client/network/src/protocol/generic_proto/upgrade.rs +++ b/client/network/src/protocol/generic_proto/upgrade.rs @@ -1,19 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . pub use self::collec::UpgradeCollec; pub use self::legacy::{ RegisteredProtocol, diff --git a/client/network/src/protocol/generic_proto/upgrade/legacy.rs b/client/network/src/protocol/generic_proto/upgrade/legacy.rs index 311e0b04f9724072535cad8dc429d2c1989c4c5d..13560113bb1a22bc75344c29bc76712a57d4cf99 100644 --- a/client/network/src/protocol/generic_proto/upgrade/legacy.rs +++ b/client/network/src/protocol/generic_proto/upgrade/legacy.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::config::ProtocolId; use bytes::BytesMut; diff --git a/client/network/src/protocol/generic_proto/upgrade/notifications.rs b/client/network/src/protocol/generic_proto/upgrade/notifications.rs index cf271016e728adec53b7e56ffc86fc71281b7f59..efcd0a4c8fb7d3fcdc3479eb43ea99f965d14e63 100644 --- a/client/network/src/protocol/generic_proto/upgrade/notifications.rs +++ b/client/network/src/protocol/generic_proto/upgrade/notifications.rs @@ -390,8 +390,8 @@ pub enum NotificationsOutError { /// Remote doesn't process our messages quickly enough. /// /// > **Note**: This is not necessarily the remote's fault, and could also be caused by the - /// > local node sending data too quickly. Properly doing back-pressure, however, - /// > would require a deep refactoring effort in Substrate as a whole. + /// > local node sending data too quickly. Properly doing back-pressure, however, + /// > would require a deep refactoring effort in Substrate as a whole. Clogged, } diff --git a/client/network/src/protocol/message.rs b/client/network/src/protocol/message.rs index 8638e9afc59b93fc134b53d71e01770fdecd01d3..bb2253b733864bd216b7a51c1b426648a4552510 100644 --- a/client/network/src/protocol/message.rs +++ b/client/network/src/protocol/message.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Network packet message types. These get serialized and put into the lower level protocol payload. diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index b720ba0aefe4bd8d9cfb9f1dd8703200bc6ef2d6..e08fcf4e9b580297d455dc6663758d10968c6831 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -513,10 +513,10 @@ impl ChainSync { } } - /// Signal that `best_header` has been queued for import and update the + /// Signal that a new best block has been imported. /// `ChainSync` state with that information. - pub fn update_chain_info(&mut self, best_header: &B::Header) { - self.on_block_queued(&best_header.hash(), *best_header.number()) + pub fn update_chain_info(&mut self, best_hash: &B::Hash, best_number: NumberFor) { + self.on_block_queued(best_hash, best_number); } /// Schedule a justification request for the given block. @@ -574,7 +574,7 @@ impl ChainSync { if number > peer.best_number { peer.best_number = number; - peer.best_hash = hash.clone(); + peer.best_hash = *hash; } self.pending_requests.add(peer_id); } @@ -639,7 +639,7 @@ impl ChainSync { } /// Get an iterator over all block requests of all peers. - pub fn block_requests(&mut self) -> impl Iterator)> + '_ { + pub fn block_requests(&mut self) -> impl Iterator)> + '_ { if self.pending_requests.is_empty() { return Either::Left(std::iter::empty()) } @@ -682,7 +682,7 @@ impl ChainSync { req, ); have_requests = true; - Some((id.clone(), req)) + Some((id, req)) } else if let Some((hash, req)) = fork_sync_request( id, fork_targets, @@ -698,7 +698,7 @@ impl ChainSync { trace!(target: "sync", "Downloading fork {:?} from {}", hash, id); peer.state = PeerSyncState::DownloadingStale(hash); have_requests = true; - Some((id.clone(), req)) + Some((id, req)) } else { None } @@ -713,24 +713,27 @@ impl ChainSync { /// /// If this corresponds to a valid block, this outputs the block that /// must be imported in the import queue. - pub fn on_block_data - (&mut self, who: PeerId, request: Option>, response: BlockResponse) -> Result, BadPeer> - { + pub fn on_block_data( + &mut self, + who: &PeerId, + request: Option>, + response: BlockResponse + ) -> Result, BadPeer> { let mut new_blocks: Vec> = - if let Some(peer) = self.peers.get_mut(&who) { + if let Some(peer) = self.peers.get_mut(who) { let mut blocks = response.blocks; if request.as_ref().map_or(false, |r| r.direction == message::Direction::Descending) { trace!(target: "sync", "Reversing incoming block list"); blocks.reverse() } - self.pending_requests.add(&who); + self.pending_requests.add(who); if request.is_some() { match &mut peer.state { PeerSyncState::DownloadingNew(start_block) => { - self.blocks.clear_peer_download(&who); + self.blocks.clear_peer_download(who); let start_block = *start_block; peer.state = PeerSyncState::Available; - validate_blocks::(&blocks, &who)?; + validate_blocks::(&blocks, who)?; self.blocks.insert(start_block, blocks, who.clone()); self.blocks .drain(self.best_queued_number + One::one()) @@ -751,9 +754,9 @@ impl ChainSync { peer.state = PeerSyncState::Available; if blocks.is_empty() { debug!(target: "sync", "Empty block response from {}", who); - return Err(BadPeer(who, rep::NO_BLOCK)); + return Err(BadPeer(who.clone(), rep::NO_BLOCK)); } - validate_blocks::(&blocks, &who)?; + validate_blocks::(&blocks, who)?; blocks.into_iter().map(|b| { IncomingBlock { hash: b.hash, @@ -774,11 +777,11 @@ impl ChainSync { }, (None, _) => { debug!(target: "sync", "Invalid response when searching for ancestor from {}", who); - return Err(BadPeer(who, rep::UNKNOWN_ANCESTOR)) + return Err(BadPeer(who.clone(), rep::UNKNOWN_ANCESTOR)) }, (_, Err(e)) => { info!("❌ Error answering legitimate blockchain query: {:?}", e); - return Err(BadPeer(who, rep::BLOCKCHAIN_READ_ERROR)) + return Err(BadPeer(who.clone(), rep::BLOCKCHAIN_READ_ERROR)) } }; if matching_hash.is_some() { @@ -794,7 +797,7 @@ impl ChainSync { } if matching_hash.is_none() && current.is_zero() { trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); - return Err(BadPeer(who, rep::GENESIS_MISMATCH)) + return Err(BadPeer(who.clone(), rep::GENESIS_MISMATCH)) } if let Some((next_state, next_num)) = handle_ancestor_search_state(state, *current, matching_hash.is_some()) { peer.state = PeerSyncState::AncestorSearch { @@ -802,7 +805,7 @@ impl ChainSync { start: *start, state: next_state, }; - return Ok(OnBlockData::Request(who, ancestry_request::(next_num))) + return Ok(OnBlockData::Request(who.clone(), ancestry_request::(next_num))) } else { // Ancestry search is complete. Check if peer is on a stale fork unknown to us and // add it to sync targets if necessary. @@ -838,7 +841,7 @@ impl ChainSync { } } else { // When request.is_none() this is a block announcement. Just accept blocks. - validate_blocks::(&blocks, &who)?; + validate_blocks::(&blocks, who)?; blocks.into_iter().map(|b| { IncomingBlock { hash: b.hash, @@ -869,7 +872,7 @@ impl ChainSync { // So the only way this can happen is when peers lie about the // common block. debug!(target: "sync", "Ignoring known blocks from {}", who); - return Err(BadPeer(who, rep::KNOWN_BLOCK)); + return Err(BadPeer(who.clone(), rep::KNOWN_BLOCK)); } let orig_len = new_blocks.len(); new_blocks.retain(|b| !self.queue_blocks.contains(&b.hash)); @@ -1124,7 +1127,7 @@ impl ChainSync { /// Updates our internal state for best queued block and then goes /// through all peers to update our view of their state as well. fn on_block_queued(&mut self, hash: &B::Hash, number: NumberFor) { - if let Some(_) = self.fork_targets.remove(&hash) { + if self.fork_targets.remove(&hash).is_some() { trace!(target: "sync", "Completed fork sync {:?}", hash); } if number > self.best_queued_number { @@ -1162,7 +1165,7 @@ impl ChainSync { /// header (call `on_block_data`). The network request isn't sent /// in this case. Both hash and header is passed as an optimization /// to avoid rehashing the header. - pub fn on_block_announce(&mut self, who: PeerId, hash: B::Hash, announce: &BlockAnnounce, is_best: bool) + pub fn on_block_announce(&mut self, who: &PeerId, hash: B::Hash, announce: &BlockAnnounce, is_best: bool) -> OnBlockAnnounce { let header = &announce.header; @@ -1177,7 +1180,7 @@ impl ChainSync { let ancient_parent = parent_status == BlockStatus::InChainPruned; let known = self.is_known(&hash); - let peer = if let Some(peer) = self.peers.get_mut(&who) { + let peer = if let Some(peer) = self.peers.get_mut(who) { peer } else { error!(target: "sync", "💔 Called on_block_announce with a bad peer ID"); @@ -1206,13 +1209,13 @@ impl ChainSync { peer.common_number = number - One::one(); } } - self.pending_requests.add(&who); + self.pending_requests.add(who); // known block case if known || self.is_already_downloading(&hash) { trace!(target: "sync", "Known block announce from {}: {}", who, hash); if let Some(target) = self.fork_targets.get_mut(&hash) { - target.peers.insert(who); + target.peers.insert(who.clone()); } return OnBlockAnnounce::Nothing } @@ -1251,21 +1254,21 @@ impl ChainSync { .entry(hash.clone()) .or_insert_with(|| ForkTarget { number, - parent_hash: Some(header.parent_hash().clone()), + parent_hash: Some(*header.parent_hash()), peers: Default::default(), }) - .peers.insert(who); + .peers.insert(who.clone()); } OnBlockAnnounce::Nothing } /// Call when a peer has disconnected. - pub fn peer_disconnected(&mut self, who: PeerId) { - self.blocks.clear_peer_download(&who); - self.peers.remove(&who); - self.extra_justifications.peer_disconnected(&who); - self.extra_finality_proofs.peer_disconnected(&who); + pub fn peer_disconnected(&mut self, who: &PeerId) { + self.blocks.clear_peer_download(who); + self.peers.remove(who); + self.extra_justifications.peer_disconnected(who); + self.extra_finality_proofs.peer_disconnected(who); self.pending_requests.set_all(); } @@ -1471,11 +1474,12 @@ fn fork_sync_request( } if r.number <= best_num { let parent_status = r.parent_hash.as_ref().map_or(BlockStatus::Unknown, check_block); - let mut count = (r.number - finalized).saturated_into::(); // up to the last finalized block - if parent_status != BlockStatus::Unknown { + let count = if parent_status == BlockStatus::Unknown { + (r.number - finalized).saturated_into::() // up to the last finalized block + } else { // request only single block - count = 1; - } + 1 + }; trace!(target: "sync", "Downloading requested fork {:?} from {}, {} blocks", hash, id, count); return Some((hash.clone(), message::generic::BlockRequest { id: 0, diff --git a/client/network/src/protocol/sync/blocks.rs b/client/network/src/protocol/sync/blocks.rs index 359287701e66e5b95b9561bbd5982fd50e77e08d..b64c9e053e97b3018562beca4f439d71f17c8edb 100644 --- a/client/network/src/protocol/sync/blocks.rs +++ b/client/network/src/protocol/sync/blocks.rs @@ -1,23 +1,24 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::cmp; use std::ops::Range; use std::collections::{HashMap, BTreeMap}; -use std::collections::hash_map::Entry; use log::trace; use libp2p::PeerId; use sp_runtime::traits::{Block as BlockT, NumberFor, One}; @@ -116,17 +117,17 @@ impl BlockCollection { let mut prev: Option<(&NumberFor, &BlockRangeState)> = None; loop { let next = downloading_iter.next(); - break match &(prev, next) { - &(Some((start, &BlockRangeState::Downloading { ref len, downloading })), _) + break match (prev, next) { + (Some((start, &BlockRangeState::Downloading { ref len, downloading })), _) if downloading < max_parallel => (*start .. *start + *len, downloading), - &(Some((start, r)), Some((next_start, _))) if *start + r.len() < *next_start => + (Some((start, r)), Some((next_start, _))) if *start + r.len() < *next_start => (*start + r.len() .. cmp::min(*next_start, *start + r.len() + count), 0), // gap - &(Some((start, r)), None) => + (Some((start, r)), None) => (*start + r.len() .. *start + r.len() + count, 0), // last range - &(None, None) => + (None, None) => (first_different .. first_different + count, 0), // empty - &(None, Some((start, _))) if *start > first_different => + (None, Some((start, _))) if *start > first_different => (first_different .. cmp::min(first_different + count, *start), 0), // gap at the start _ => { prev = next; @@ -167,7 +168,7 @@ impl BlockCollection { let mut prev = from; for (start, range_data) in &mut self.blocks { match range_data { - &mut BlockRangeState::Complete(ref mut blocks) if *start <= prev => { + BlockRangeState::Complete(blocks) if *start <= prev => { prev = *start + (blocks.len() as u32).into(); // Remove all elements from `blocks` and add them to `drained` drained.append(blocks); @@ -185,26 +186,22 @@ impl BlockCollection { } 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) { - Some(&mut BlockRangeState::Downloading { ref mut downloading, .. }) if *downloading > 1 => { - *downloading = *downloading - 1; - false - }, - Some(&mut BlockRangeState::Downloading { .. }) => { - true - }, - _ => { - false - } - }; - if remove { - self.blocks.remove(&start); + if let Some(start) = self.peer_requests.remove(who) { + let remove = match self.blocks.get_mut(&start) { + Some(&mut BlockRangeState::Downloading { ref mut downloading, .. }) if *downloading > 1 => { + *downloading -= 1; + false + }, + Some(&mut BlockRangeState::Downloading { .. }) => { + true + }, + _ => { + false } - }, - _ => (), + }; + if remove { + self.blocks.remove(&start); + } } } } diff --git a/client/network/src/protocol/sync/extra_requests.rs b/client/network/src/protocol/sync/extra_requests.rs index 3d854b574b01fc26aaf6d1d39e15bed2b46551c2..6d688c130fafdec413e3ff905f3e33802cb85aeb 100644 --- a/client/network/src/protocol/sync/extra_requests.rs +++ b/client/network/src/protocol/sync/extra_requests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use sp_blockchain::Error as ClientError; use crate::protocol::sync::{PeerSync, PeerSyncState}; @@ -102,11 +104,9 @@ impl ExtraRequests { // we have finalized further than the given request, presumably // by some other part of the system (not sync). we can safely // ignore the `Revert` error. - return; }, Err(err) => { debug!(target: "sync", "Failed to insert request {:?} into tree: {:?}", request, err); - return; } _ => () } diff --git a/client/network/src/schema.rs b/client/network/src/schema.rs index 0c8a650e69394d0568ca322a33d4296a840b75d7..44fbbffd25406d5b985707f46f8c2e9123ca992a 100644 --- a/client/network/src/schema.rs +++ b/client/network/src/schema.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Include sources generated from protobuf definitions. diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 64b3d3b5b22f4123db98d248a833bb2187e808c0..6256cdd64da4de06356c0b09f3bfa333ee50e901 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Main entry point of the sc-network crate. //! @@ -58,10 +60,11 @@ use sp_runtime::{ }; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use std::{ - borrow::Cow, + borrow::{Borrow, Cow}, collections::HashSet, fs, io, marker::PhantomData, + num:: NonZeroUsize, pin::Pin, str, sync::{ @@ -184,7 +187,13 @@ impl NetworkWorker { let local_identity = params.network_config.node_key.clone().into_keypair()?; let local_public = local_identity.public(); let local_peer_id = local_public.clone().into_peer_id(); - info!(target: "sub-libp2p", "🏷 Local node identity is: {}", local_peer_id.to_base58()); + let local_peer_id_legacy = bs58::encode(Borrow::<[u8]>::borrow(&local_peer_id)).into_string(); + info!( + target: "sub-libp2p", + "🏷 Local node identity is: {} (legacy representation: {})", + local_peer_id.to_base58(), + local_peer_id_legacy + ); // Initialize the metrics. let metrics = match ¶ms.metrics_registry { @@ -194,7 +203,7 @@ impl NetworkWorker { let checker = params.on_demand.as_ref() .map(|od| od.checker().clone()) - .unwrap_or(Arc::new(AlwaysBadChecker)); + .unwrap_or_else(|| Arc::new(AlwaysBadChecker)); let num_connected = Arc::new(AtomicUsize::new(0)); let is_major_syncing = Arc::new(AtomicBool::new(false)); @@ -203,6 +212,7 @@ impl NetworkWorker { roles: From::from(¶ms.role), max_parallel_downloads: params.network_config.max_parallel_downloads, }, + local_peer_id.clone(), params.chain.clone(), params.transaction_pool, params.finality_proof_provider.clone(), @@ -285,7 +295,9 @@ impl NetworkWorker { transport::build_transport(local_identity, config_mem, config_wasm, flowctrl) }; let mut builder = SwarmBuilder::new(transport, behaviour, local_peer_id.clone()) - .peer_connection_limit(crate::MAX_CONNECTIONS_PER_PEER); + .peer_connection_limit(crate::MAX_CONNECTIONS_PER_PEER) + .notify_handler_buffer_size(NonZeroUsize::new(16).expect("16 != 0; qed")) + .connection_event_buffer_size(128); if let Some(spawner) = params.executor { struct SpawnImpl(F); impl + Send>>)> Executor for SpawnImpl { @@ -319,7 +331,7 @@ impl NetworkWorker { is_major_syncing: is_major_syncing.clone(), peerset: peerset_handle, local_peer_id, - to_worker: to_worker.clone(), + to_worker, _marker: PhantomData, }); @@ -399,16 +411,18 @@ impl NetworkWorker { &self.service } - /// You must call this when a new block is imported by the client. - pub fn on_block_imported(&mut self, header: B::Header, is_best: bool) { - self.network_service.user_protocol_mut().on_block_imported(&header, is_best); - } - /// You must call this when a new block is finalized by the client. pub fn on_block_finalized(&mut self, hash: B::Hash, header: B::Header) { self.network_service.user_protocol_mut().on_block_finalized(hash, &header); } + /// This should be called when blocks are added to the + /// chain by something other than the import queue. + /// Currently this is only useful for tests. + pub fn update_chain(&mut self) { + self.network_service.user_protocol_mut().update_chain(); + } + /// Returns the local `PeerId`. pub fn local_peer_id(&self) -> &PeerId { Swarm::::local_peer_id(&self.network_service) @@ -446,7 +460,7 @@ impl NetworkWorker { Some((peer_id.to_base58(), NetworkStatePeer { endpoint, version_string: swarm.node(peer_id) - .and_then(|i| i.client_version().map(|s| s.to_owned())).clone(), + .and_then(|i| i.client_version().map(|s| s.to_owned())), latest_ping_time: swarm.node(peer_id).and_then(|i| i.latest_ping()), enabled: swarm.user_protocol().is_enabled(&peer_id), open: swarm.user_protocol().is_open(&peer_id), @@ -462,7 +476,7 @@ impl NetworkWorker { list.into_iter().map(move |peer_id| { (peer_id.to_base58(), NetworkStateNotConnectedPeer { version_string: swarm.node(&peer_id) - .and_then(|i| i.client_version().map(|s| s.to_owned())).clone(), + .and_then(|i| i.client_version().map(|s| s.to_owned())), latest_ping_time: swarm.node(&peer_id).and_then(|i| i.latest_ping()), known_addresses: NetworkBehaviour::addresses_of_peer(&mut **swarm, &peer_id) .into_iter().collect(), @@ -545,13 +559,17 @@ impl NetworkService { /// Registers a new notifications protocol. /// - /// After that, you can call `write_notifications`. + /// After a protocol has been registered, you can call `write_notifications`. + /// + /// **Important**: This method is a work-around, and you are instead strongly encouraged to + /// pass the protocol in the `NetworkConfiguration::notifications_protocols` list instead. + /// If you have no other choice but to use this method, you are very strongly encouraged to + /// call it very early on. Any connection open will retain the protocols that were registered + /// then, and not any new one. /// /// Please call `event_stream` before registering a protocol, otherwise you may miss events /// about the protocol that you have registered. - /// - /// You are very strongly encouraged to call this method very early on. Any connection open - /// will retain the protocols that were registered then, and not any new one. + // TODO: remove this method after https://github.com/paritytech/substrate/issues/4587 pub fn register_notifications_protocol( &self, engine_id: ConsensusEngineId, @@ -607,7 +625,7 @@ impl NetworkService { pub fn request_justification(&self, hash: &B::Hash, number: NumberFor) { let _ = self .to_worker - .unbounded_send(ServiceToWorkerMsg::RequestJustification(hash.clone(), number)); + .unbounded_send(ServiceToWorkerMsg::RequestJustification(*hash, number)); } /// Are we in the process of downloading the chain? @@ -1195,7 +1213,7 @@ impl Future for NetworkWorker { } }, Poll::Ready(SwarmEvent::ExpiredListenAddr(addr)) => { - trace!(target: "sub-libp2p", "Libp2p => ExpiredListenAddr({})", addr); + info!(target: "sub-libp2p", "📪 No longer listening on {}", addr); if let Some(metrics) = this.metrics.as_ref() { metrics.listeners_local_addresses.dec(); } @@ -1263,10 +1281,23 @@ impl Future for NetworkWorker { trace!(target: "sub-libp2p", "Libp2p => UnknownPeerUnreachableAddr({}): {}", address, error), Poll::Ready(SwarmEvent::ListenerClosed { reason, addresses }) => { - warn!(target: "sub-libp2p", "Libp2p => ListenerClosed: {:?}", reason); if let Some(metrics) = this.metrics.as_ref() { metrics.listeners_local_addresses.sub(addresses.len() as u64); } + let addrs = addresses.into_iter().map(|a| a.to_string()) + .collect::>().join(", "); + match reason { + Ok(()) => error!( + target: "sub-libp2p", + "📪 Libp2p listener ({}) closed gracefully", + addrs + ), + Err(e) => error!( + target: "sub-libp2p", + "📪 Libp2p listener ({}) closed: {}", + addrs, e + ), + } }, Poll::Ready(SwarmEvent::ListenerError { error }) => { trace!(target: "sub-libp2p", "Libp2p => ListenerError: {}", error); @@ -1348,7 +1379,7 @@ impl<'a, B: BlockT, H: ExHashT> Link for NetworkLink<'a, B, H> { count: usize, results: Vec<(Result>, BlockImportError>, B::Hash)> ) { - self.protocol.user_protocol_mut().blocks_processed(imported, count, results) + self.protocol.user_protocol_mut().on_blocks_processed(imported, count, results) } fn justification_imported(&mut self, who: PeerId, hash: &B::Hash, number: NumberFor, success: bool) { self.protocol.user_protocol_mut().justification_import_result(hash.clone(), number, success); diff --git a/client/network/src/service/out_events.rs b/client/network/src/service/out_events.rs index 2d4d7ded213e57578daf2433ec48c9e009470bb5..4a631601a669eeb79818f40058ea56ea0076dc0e 100644 --- a/client/network/src/service/out_events.rs +++ b/client/network/src/service/out_events.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Registering events streams. //! diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs index 3bed660851b1a663dd7a0bf15cb68f883400fb23..8eaa98449213c8577eb0059439a73d5e074cd21e 100644 --- a/client/network/src/service/tests.rs +++ b/client/network/src/service/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::{config, Event, NetworkService, NetworkWorker}; @@ -86,6 +88,7 @@ fn build_test_full_node(config: config::NetworkConfiguration) None, None, &sp_core::testing::SpawnBlockingExecutor::new(), + None, )); let worker = NetworkWorker::new(config::Params { diff --git a/client/network/src/transport.rs b/client/network/src/transport.rs index 75ee2d5db89b9c64569c23a70c7384080819ef36..0c9a809384e4cf6dc8aaf218cbfc610973d67fe5 100644 --- a/client/network/src/transport.rs +++ b/client/network/src/transport.rs @@ -1,27 +1,32 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use futures::prelude::*; use libp2p::{ InboundUpgradeExt, OutboundUpgradeExt, PeerId, Transport, + core::{ + self, either::{EitherError, EitherOutput}, muxing::StreamMuxerBox, + transport::{boxed::Boxed, OptionalTransport}, upgrade + }, mplex, identity, bandwidth, wasm_ext, noise }; #[cfg(not(target_os = "unknown"))] use libp2p::{tcp, dns, websocket}; -use libp2p::core::{self, upgrade, transport::boxed::Boxed, transport::OptionalTransport, muxing::StreamMuxerBox}; use std::{io, sync::Arc, time::Duration, usize}; pub use self::bandwidth::BandwidthSinks; @@ -41,14 +46,22 @@ pub fn build_transport( ) -> (Boxed<(PeerId, StreamMuxerBox), io::Error>, Arc) { // Build configuration objects for encryption mechanisms. let noise_config = { - let noise_keypair = noise::Keypair::new().into_authentic(&keypair) - // For more information about this panic, see in "On the Importance of Checking - // Cryptographic Protocols for Faults" by Dan Boneh, Richard A. DeMillo, - // and Richard J. Lipton. + // For more information about these two panics, see in "On the Importance of + // Checking Cryptographic Protocols for Faults" by Dan Boneh, Richard A. DeMillo, + // and Richard J. Lipton. + let noise_keypair_legacy = noise::Keypair::::new().into_authentic(&keypair) + .expect("can only fail in case of a hardware bug; since this signing is performed only \ + once and at initialization, we're taking the bet that the inconvenience of a very \ + rare panic here is basically zero"); + let noise_keypair_spec = noise::Keypair::::new().into_authentic(&keypair) .expect("can only fail in case of a hardware bug; since this signing is performed only \ once and at initialization, we're taking the bet that the inconvenience of a very \ rare panic here is basically zero"); - noise::NoiseConfig::ix(noise_keypair) + + core::upgrade::SelectUpgrade::new( + noise::NoiseConfig::xx(noise_keypair_spec), + noise::NoiseConfig::ix(noise_keypair_legacy) + ) }; // Build configuration objects for multiplexing mechanisms. @@ -96,11 +109,22 @@ pub fn build_transport( // Encryption let transport = transport.and_then(move |stream, endpoint| { core::upgrade::apply(stream, noise_config, endpoint, upgrade::Version::V1) - .and_then(|(remote_id, out)| async move { - let remote_key = match remote_id { - noise::RemoteIdentity::IdentityKey(key) => key, + .map_err(|err| + err.map_err(|err| match err { + EitherError::A(err) => err, + EitherError::B(err) => err, + }) + ) + .and_then(|result| async move { + let remote_key = match &result { + EitherOutput::First((noise::RemoteIdentity::IdentityKey(key), _)) => key.clone(), + EitherOutput::Second((noise::RemoteIdentity::IdentityKey(key), _)) => key.clone(), _ => return Err(upgrade::UpgradeError::Apply(noise::NoiseError::InvalidKey)) }; + let out = match result { + EitherOutput::First((_, o)) => o, + EitherOutput::Second((_, o)) => o, + }; Ok((out, remote_key.into_peer_id())) }) }); diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml index 154694c692adbb786c397529bf397509cee9bc08..8695d30a6805a07ac42f78ac86cd968e71ea6287 100644 --- a/client/network/test/Cargo.toml +++ b/client/network/test/Cargo.toml @@ -1,8 +1,8 @@ [package] description = "Integration tests for Substrate network protocol" name = "sc-network-test" -version = "0.8.0-dev" -license = "GPL-3.0" +version = "0.8.0-rc2" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" publish = false @@ -13,23 +13,23 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sc-network = { version = "0.8.0-dev", path = "../" } +sc-network = { version = "0.8.0-rc2", path = "../" } log = "0.4.8" parking_lot = "0.10.0" futures = "0.3.4" futures-timer = "3.0.1" rand = "0.7.2" -libp2p = { version = "0.18.1", default-features = false, features = ["libp2p-websocket"] } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sc-consensus = { version = "0.8.0-dev", path = "../../../client/consensus/common" } -sc-client-api = { version = "2.0.0-dev", path = "../../api" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sc-block-builder = { version = "0.8.0-dev", path = "../../block-builder" } -sp-consensus-babe = { version = "0.8.0-dev", path = "../../../primitives/consensus/babe" } +libp2p = { version = "0.19.1", default-features = false, features = ["libp2p-websocket"] } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sc-consensus = { version = "0.8.0-rc2", path = "../../../client/consensus/common" } +sc-client-api = { version = "2.0.0-rc2", path = "../../api" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sc-block-builder = { version = "0.8.0-rc2", path = "../../block-builder" } +sp-consensus-babe = { version = "0.8.0-rc2", path = "../../../primitives/consensus/babe" } env_logger = "0.7.0" -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../../test-utils/runtime" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../test-utils/runtime/client" } +substrate-test-runtime = { version = "2.0.0-rc2", path = "../../../test-utils/runtime" } tempfile = "3.1.0" -sc-service = { version = "0.8.0-dev", default-features = false, features = ["test-helpers"], path = "../../service" } +sc-service = { version = "0.8.0-rc2", default-features = false, features = ["test-helpers"], path = "../../service" } diff --git a/client/network/test/src/block_import.rs b/client/network/test/src/block_import.rs index a77dec629b28256ad59f58e647cb6b122f0f7997..8636cfbc21ac52f5c47e5d487d55351574947f8c 100644 --- a/client/network/test/src/block_import.rs +++ b/client/network/test/src/block_import.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Testing block import logic. @@ -53,7 +55,11 @@ fn import_single_good_block_works() { let mut expected_aux = ImportedAux::default(); expected_aux.is_new_best = true; - match import_single_block(&mut substrate_test_runtime_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + match import_single_block( + &mut substrate_test_runtime_client::new(), + BlockOrigin::File, block, + &mut PassThroughVerifier(true), + ) { Ok(BlockImportResult::ImportedUnknown(ref num, ref aux, ref org)) if *num == number && *aux == expected_aux && *org == Some(peer_id) => {} r @ _ => panic!("{:?}", r) @@ -63,7 +69,11 @@ fn import_single_good_block_works() { #[test] fn import_single_good_known_block_is_ignored() { let (mut client, _hash, number, _, block) = prepare_good_block(); - match import_single_block(&mut client, BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + match import_single_block( + &mut client, BlockOrigin::File, + block, + &mut PassThroughVerifier(true) + ) { Ok(BlockImportResult::ImportedKnown(ref n)) if *n == number => {} _ => panic!() } @@ -73,7 +83,11 @@ fn import_single_good_known_block_is_ignored() { fn import_single_good_block_without_header_fails() { let (_, _, _, peer_id, mut block) = prepare_good_block(); block.header = None; - match import_single_block(&mut substrate_test_runtime_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + match import_single_block( + &mut substrate_test_runtime_client::new(), + BlockOrigin::File, block, + &mut PassThroughVerifier(true), + ) { Err(BlockImportError::IncompleteHeader(ref org)) if *org == Some(peer_id) => {} _ => panic!() } @@ -92,6 +106,7 @@ fn async_import_queue_drops() { None, None, &executor, + None, ); drop(queue); } diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 999c99f64a1d4acf400359650542ba0ea28c8285..3ce28c261f4e2e310a6e3ae011266cfb660941d5 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . #![allow(missing_docs)] #[cfg(test)] @@ -294,11 +295,11 @@ impl Peer { Default::default() }; self.block_import.import_block(import_block, cache).expect("block_import failed"); - self.network.on_block_imported(header, true); self.network.service().announce_block(hash, Vec::new()); at = hash; } + self.network.update_chain(); self.network.service().announce_block(at.clone(), Vec::new()); at } @@ -612,6 +613,7 @@ pub trait TestNetFactory: Sized { justification_import, finality_proof_import, &sp_core::testing::SpawnBlockingExecutor::new(), + None, )); let listen_addr = build_multiaddr![Memory(rand::random::())]; @@ -690,6 +692,7 @@ pub trait TestNetFactory: Sized { justification_import, finality_proof_import, &sp_core::testing::SpawnBlockingExecutor::new(), + None, )); let listen_addr = build_multiaddr![Memory(rand::random::())]; @@ -810,10 +813,6 @@ pub trait TestNetFactory: Sized { // We poll `imported_blocks_stream`. while let Poll::Ready(Some(notification)) = peer.imported_blocks_stream.as_mut().poll_next(cx) { - peer.network.on_block_imported( - notification.header, - true, - ); peer.network.service().announce_block(notification.hash, Vec::new()); } diff --git a/client/network/test/src/sync.rs b/client/network/test/src/sync.rs index 60e9e558c5fffafd0863ce47202b6129d8e2dd47..13d04a8c4e81e9854fb762a2c2905c32a8482cf3 100644 --- a/client/network/test/src/sync.rs +++ b/client/network/test/src/sync.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use sp_consensus::BlockOrigin; use std::time::Duration; diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml index ac3a71ad0d9c8f89745817d926481b71cecba196..99f4ad66f31f881b48a10f9334a056898e74512d 100644 --- a/client/offchain/Cargo.toml +++ b/client/offchain/Cargo.toml @@ -1,8 +1,8 @@ [package] description = "Substrate offchain workers" name = "sc-offchain" -version = "2.0.0-dev" -license = "GPL-3.0" +version = "2.0.0-rc2" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" @@ -13,23 +13,23 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] bytes = "0.5" -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } fnv = "1.0.6" futures = "0.3.4" futures-timer = "3.0.1" log = "0.4.8" threadpool = "1.7" num_cpus = "1.10" -sp-offchain = { version = "2.0.0-dev", path = "../../primitives/offchain" } +sp-offchain = { version = "2.0.0-rc2", path = "../../primitives/offchain" } codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } parking_lot = "0.10.0" -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } rand = "0.7.2" -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" } -sc-network = { version = "0.8.0-dev", path = "../network" } -sc-keystore = { version = "2.0.0-dev", path = "../keystore" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sc-keystore = { version = "2.0.0-rc2", path = "../keystore" } [target.'cfg(not(target_os = "unknown"))'.dependencies] hyper = "0.13.2" @@ -38,10 +38,10 @@ hyper-rustls = "0.20" [dev-dependencies] env_logger = "0.7.0" fdlimit = "0.1.4" -sc-client-db = { version = "0.8.0-dev", default-features = true, path = "../db/" } -sc-transaction-pool = { version = "2.0.0-dev", path = "../../client/transaction-pool" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transaction-pool" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sc-client-db = { version = "0.8.0-rc2", default-features = true, path = "../db/" } +sc-transaction-pool = { version = "2.0.0-rc2", path = "../../client/transaction-pool" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../primitives/transaction-pool" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } tokio = "0.2" [features] diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs index 45a82d230c11a6dd6d6c8ce03635d1c49c6d7ce7..a7f4ecbc5825e8ceef875b94009d29097d1669f4 100644 --- a/client/offchain/src/api.rs +++ b/client/offchain/src/api.rs @@ -100,6 +100,13 @@ impl OffchainExt for Api { } } + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + match kind { + StorageKind::PERSISTENT => self.db.remove(STORAGE_PREFIX, key), + StorageKind::LOCAL => unavailable_yet(LOCAL_DB), + } + } + fn local_storage_compare_and_set( &mut self, kind: StorageKind, diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs index a64fe0389706c1098eda9f1c2fbd2294843d7597..91a673872fc7cfc27e18c13110b05b84cb3ed84e 100644 --- a/client/offchain/src/api/http.rs +++ b/client/offchain/src/api/http.rs @@ -31,7 +31,7 @@ use fnv::FnvHashMap; use futures::{prelude::*, future, channel::mpsc}; use log::error; use sp_core::offchain::{HttpRequestId, Timestamp, HttpRequestStatus, HttpError}; -use std::{fmt, io::Read as _, mem, pin::Pin, task::Context, task::Poll}; +use std::{convert::TryFrom, fmt, io::Read as _, pin::Pin, task::{Context, Poll}}; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender, TracingUnboundedReceiver}; /// Creates a pair of [`HttpApi`] and [`HttpWorker`]. @@ -151,8 +151,8 @@ impl HttpApi { _ => return Err(()) }; - let name = hyper::header::HeaderName::from_bytes(name.as_bytes()).map_err(|_| ())?; - let value = hyper::header::HeaderValue::from_str(value).map_err(|_| ())?; + let name = hyper::header::HeaderName::try_from(name).map_err(drop)?; + let value = hyper::header::HeaderValue::try_from(value).map_err(drop)?; // Note that we're always appending headers and never replacing old values. // We assume here that the user knows what they're doing. request.headers_mut().append(name, value); @@ -185,7 +185,7 @@ impl HttpApi { future::MaybeDone::Done(Err(_)) => return Err(HttpError::IoError), future::MaybeDone::Future(_) | future::MaybeDone::Gone => { - debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); + debug_assert!(matches!(deadline, future::MaybeDone::Done(..))); return Err(HttpError::DeadlineReached) } }; @@ -347,7 +347,7 @@ impl HttpApi { if let future::MaybeDone::Done(msg) = next_msg { msg } else { - debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); + debug_assert!(matches!(deadline, future::MaybeDone::Done(..))); continue } }; @@ -585,25 +585,21 @@ impl Future for HttpWorker { match request { HttpWorkerRequest::Dispatched(mut future) => { // Check for an HTTP response from the Internet. - let mut response = match Future::poll(Pin::new(&mut future), cx) { + let response = match Future::poll(Pin::new(&mut future), cx) { Poll::Pending => { me.requests.push((id, HttpWorkerRequest::Dispatched(future))); continue }, Poll::Ready(Ok(response)) => response, - Poll::Ready(Err(err)) => { - let _ = me.to_api.unbounded_send(WorkerToApi::Fail { - id, - error: err, - }); + Poll::Ready(Err(error)) => { + let _ = me.to_api.unbounded_send(WorkerToApi::Fail { id, error }); continue; // don't insert the request back } }; // We received a response! Decompose it into its parts. - let status_code = response.status(); - let headers = mem::replace(response.headers_mut(), hyper::HeaderMap::new()); - let body = response.into_body(); + let (head, body) = response.into_parts(); + let (status_code, headers) = (head.status, head.headers); let (body_tx, body_rx) = mpsc::channel(3); let _ = me.to_api.unbounded_send(WorkerToApi::Response { @@ -691,15 +687,12 @@ mod tests { use crate::api::timestamp; use super::http; use sp_core::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Duration}; + use futures::future; // Returns an `HttpApi` whose worker is ran in the background, and a `SocketAddr` to an HTTP // server that runs in the background as well. macro_rules! build_api_server { () => {{ - fn tokio_run(future: impl std::future::Future) { - let _ = tokio::runtime::Runtime::new().unwrap().block_on(future); - } - // We spawn quite a bit of HTTP servers here due to how async API // works for offchain workers, so be sure to raise the FD limit // (particularly useful for macOS where the default soft limit may @@ -707,11 +700,12 @@ mod tests { fdlimit::raise_fd_limit(); let (api, worker) = http(); - std::thread::spawn(move || tokio_run(worker)); let (addr_tx, addr_rx) = std::sync::mpsc::channel(); std::thread::spawn(move || { - tokio_run(async move { + let mut rt = tokio::runtime::Runtime::new().unwrap(); + let worker = rt.spawn(worker); + let server = rt.spawn(async move { let server = hyper::Server::bind(&"127.0.0.1:0".parse().unwrap()) .serve(hyper::service::make_service_fn(|_| { async move { Ok::<_, Infallible>(hyper::service::service_fn(move |_req| async move { @@ -721,8 +715,9 @@ mod tests { })) }})); let _ = addr_tx.send(server.local_addr()); - server.await + server.await.map_err(drop) }); + let _ = rt.block_on(future::join(worker, server)); }); (api, addr_rx.recv().unwrap()) }}; @@ -891,10 +886,10 @@ mod tests { #[test] fn response_headers_invalid_call() { let (mut api, addr) = build_api_server!(); - assert!(api.response_headers(HttpRequestId(0xdead)).is_empty()); + assert_eq!(api.response_headers(HttpRequestId(0xdead)), &[]); let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - assert!(api.response_headers(id).is_empty()); + assert_eq!(api.response_headers(id), &[]); let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); api.request_write_body(id, &[], None).unwrap(); @@ -904,12 +899,12 @@ mod tests { let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); api.response_wait(&[id], None); - assert!(!api.response_headers(id).is_empty()); + assert_ne!(api.response_headers(id), &[]); let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); let mut buf = [0; 128]; while api.response_read_body(id, &mut buf, None).unwrap() != 0 {} - assert!(api.response_headers(id).is_empty()); + assert_eq!(api.response_headers(id), &[]); } #[test] @@ -917,11 +912,11 @@ mod tests { let (mut api, addr) = build_api_server!(); let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - assert!(api.response_headers(id).is_empty()); + assert_eq!(api.response_headers(id), &[]); let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); api.request_add_header(id, "Foo", "Bar").unwrap(); - assert!(api.response_headers(id).is_empty()); + assert_eq!(api.response_headers(id), &[]); let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); api.request_add_header(id, "Foo", "Bar").unwrap(); @@ -930,7 +925,7 @@ mod tests { // where we haven't received any response yet. This test can theoretically fail if the // HTTP response comes back faster than the kernel schedules our thread, but that is highly // unlikely. - assert!(api.response_headers(id).is_empty()); + assert_eq!(api.response_headers(id), &[]); } #[test] diff --git a/client/offchain/src/api/timestamp.rs b/client/offchain/src/api/timestamp.rs index e5494fe70d784bca20917a38a530ef37c06b3393..222d3273cb355fa64ac4f52f8dcb568b69be25b8 100644 --- a/client/offchain/src/api/timestamp.rs +++ b/client/offchain/src/api/timestamp.rs @@ -51,12 +51,14 @@ pub fn timestamp_from_now(timestamp: Timestamp) -> Duration { pub fn deadline_to_future( deadline: Option, ) -> futures::future::MaybeDone { - use futures::future; + use futures::future::{self, Either}; - future::maybe_done(match deadline { - Some(deadline) => future::Either::Left( - futures_timer::Delay::new(timestamp_from_now(deadline)) - ), - None => future::Either::Right(future::pending()) + future::maybe_done(match deadline.map(timestamp_from_now) { + None => Either::Left(future::pending()), + // Only apply delay if we need to wait a non-zero duration + Some(duration) if duration <= Duration::from_secs(0) => + Either::Right(Either::Left(future::ready(()))), + Some(duration) => + Either::Right(Either::Right(futures_timer::Delay::new(duration))), }) } diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml index d5aa08f2f4981203b4c94b8299b174c771b25459..60ec0a39eff9a0c4463e5b7da229b118cfbef515 100644 --- a/client/peerset/Cargo.toml +++ b/client/peerset/Cargo.toml @@ -1,9 +1,9 @@ [package] description = "Connectivity manager based on reputation" homepage = "http://parity.io" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" name = "sc-peerset" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" repository = "https://github.com/paritytech/substrate/" @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] futures = "0.3.4" -libp2p = { version = "0.18.1", default-features = false } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils"} +libp2p = { version = "0.19.1", default-features = false } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils"} log = "0.4.8" serde_json = "1.0.41" wasm-timer = "0.2" diff --git a/client/peerset/src/lib.rs b/client/peerset/src/lib.rs index 9376e9594b4b702dc3746661196065e4851c78b9..a224965035fb582bdbdcc588b56156c9c7eac306 100644 --- a/client/peerset/src/lib.rs +++ b/client/peerset/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Peer Set Manager (PSM). Contains the strategy for choosing which nodes the network should be //! connected to. @@ -180,9 +182,13 @@ pub struct PeersetConfig { /// errors. #[derive(Debug)] pub struct Peerset { + /// Underlying data structure for the nodes's states. data: peersstate::PeersState, /// If true, we only accept reserved nodes. reserved_only: bool, + /// Lists of nodes that don't occupy slots and that we should try to always be connected to. + /// Is kept in sync with the list of reserved nodes in [`Peerset::data`]. + priority_groups: HashMap>, /// Receiver for messages from the `PeersetHandle` and from `tx`. rx: TracingUnboundedReceiver, /// Sending side of `rx`. @@ -207,17 +213,18 @@ impl Peerset { let now = Instant::now(); let mut peerset = Peerset { - data: peersstate::PeersState::new(config.in_peers, config.out_peers, config.reserved_only), + data: peersstate::PeersState::new(config.in_peers, config.out_peers), tx, rx, reserved_only: config.reserved_only, + priority_groups: config.priority_groups.clone().into_iter().collect(), message_queue: VecDeque::new(), created: now, latest_time_update: now, }; - for (group, nodes) in config.priority_groups { - peerset.data.set_priority_group(&group, nodes); + for node in config.priority_groups.into_iter().flat_map(|(_, l)| l) { + peerset.data.add_no_slot_node(node); } for peer_id in config.bootnodes { @@ -233,61 +240,92 @@ impl Peerset { } fn on_add_reserved_peer(&mut self, peer_id: PeerId) { - let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); - reserved.insert(peer_id); - self.data.set_priority_group(RESERVED_NODES, reserved); - self.alloc_slots(); + self.on_add_to_priority_group(RESERVED_NODES, peer_id); } fn on_remove_reserved_peer(&mut self, peer_id: PeerId) { - let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); - reserved.remove(&peer_id); - self.data.set_priority_group(RESERVED_NODES, reserved); - match self.data.peer(&peer_id) { - peersstate::Peer::Connected(peer) => { - if self.reserved_only { - peer.disconnect(); - self.message_queue.push_back(Message::Drop(peer_id)); - } - } - peersstate::Peer::NotConnected(_) => {}, - peersstate::Peer::Unknown(_) => {}, - } + self.on_remove_from_priority_group(RESERVED_NODES, peer_id); } fn on_set_reserved_only(&mut self, reserved_only: bool) { self.reserved_only = reserved_only; - self.data.set_priority_only(reserved_only); if self.reserved_only { - // Disconnect non-reserved nodes. - let reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); + // Disconnect all the nodes that aren't reserved. for peer_id in self.data.connected_peers().cloned().collect::>().into_iter() { + if self.priority_groups.get(RESERVED_NODES).map_or(false, |g| g.contains(&peer_id)) { + continue; + } + let peer = self.data.peer(&peer_id).into_connected() .expect("We are enumerating connected peers, therefore the peer is connected; qed"); - if !reserved.contains(&peer_id) { - peer.disconnect(); - self.message_queue.push_back(Message::Drop(peer_id)); - } + peer.disconnect(); + self.message_queue.push_back(Message::Drop(peer_id)); } + } else { self.alloc_slots(); } } fn on_set_priority_group(&mut self, group_id: &str, peers: HashSet) { - self.data.set_priority_group(group_id, peers); - self.alloc_slots(); + // Determine the difference between the current group and the new list. + let (to_insert, to_remove) = { + let current_group = self.priority_groups.entry(group_id.to_owned()).or_default(); + let to_insert = peers.difference(current_group) + .cloned().collect::>(); + let to_remove = current_group.difference(&peers) + .cloned().collect::>(); + (to_insert, to_remove) + }; + + // Enumerate elements in `peers` not in `current_group`. + for peer_id in &to_insert { + // We don't call `on_add_to_priority_group` here in order to avoid calling + // `alloc_slots` all the time. + self.priority_groups.entry(group_id.to_owned()).or_default().insert(peer_id.clone()); + self.data.add_no_slot_node(peer_id.clone()); + } + + // Enumerate elements in `current_group` not in `peers`. + for peer in to_remove { + self.on_remove_from_priority_group(group_id, peer); + } + + if !to_insert.is_empty() { + self.alloc_slots(); + } } fn on_add_to_priority_group(&mut self, group_id: &str, peer_id: PeerId) { - self.data.add_to_priority_group(group_id, peer_id); + self.priority_groups.entry(group_id.to_owned()).or_default().insert(peer_id.clone()); + self.data.add_no_slot_node(peer_id); self.alloc_slots(); } fn on_remove_from_priority_group(&mut self, group_id: &str, peer_id: PeerId) { - self.data.remove_from_priority_group(group_id, &peer_id); - self.alloc_slots(); + if let Some(priority_group) = self.priority_groups.get_mut(group_id) { + if !priority_group.remove(&peer_id) { + // `PeerId` wasn't in the group in the first place. + return; + } + } else { + // Group doesn't exist, so the `PeerId` can't be in it. + return; + } + + // If that `PeerId` isn't in any other group, then it is no longer no-slot-occupying. + if !self.priority_groups.values().any(|l| l.contains(&peer_id)) { + self.data.remove_no_slot_node(&peer_id); + } + + // Disconnect the peer if necessary. + if group_id != RESERVED_NODES && self.reserved_only { + if let peersstate::Peer::Connected(peer) = self.data.peer(&peer_id) { + peer.disconnect(); + self.message_queue.push_back(Message::Drop(peer_id)); + } + } } fn on_report_peer(&mut self, peer_id: PeerId, change: ReputationChange) { @@ -374,25 +412,82 @@ impl Peerset { fn alloc_slots(&mut self) { self.update_time(); - // Try to grab the next node to attempt to connect to. - while let Some(next) = { - if self.reserved_only { - self.data.priority_not_connected_peer_from_group(RESERVED_NODES) - } else { - self.data.priority_not_connected_peer() - } - } { + // Try to connect to all the reserved nodes that we are not connected to. + loop { + let next = { + let data = &mut self.data; + self.priority_groups + .get(RESERVED_NODES) + .into_iter() + .flatten() + .filter(move |n| { + data.peer(n).into_connected().is_none() + }) + .next() + .cloned() + }; + + let next = match next { + Some(n) => n, + None => break, + }; + + let next = match self.data.peer(&next) { + peersstate::Peer::Unknown(n) => n.discover(), + peersstate::Peer::NotConnected(n) => n, + peersstate::Peer::Connected(_) => { + debug_assert!(false, "State inconsistency: not connected state"); + break; + } + }; + match next.try_outgoing() { Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())), Err(_) => break, // No more slots available. } } + // Nothing more to do if we're in reserved mode. + if self.reserved_only { + return; + } + + // Try to connect to all the nodes in priority groups and that we are not connected to. loop { - if self.reserved_only { - break + let next = { + let data = &mut self.data; + self.priority_groups + .values() + .flatten() + .filter(move |n| { + data.peer(n).into_connected().is_none() + }) + .next() + .cloned() + }; + + let next = match next { + Some(n) => n, + None => break, + }; + + let next = match self.data.peer(&next) { + peersstate::Peer::Unknown(n) => n.discover(), + peersstate::Peer::NotConnected(n) => n, + peersstate::Peer::Connected(_) => { + debug_assert!(false, "State inconsistency: not connected state"); + break; + } + }; + + match next.try_outgoing() { + Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())), + Err(_) => break, // No more slots available. } + } + // Now, we try to connect to non-priority nodes. + loop { // Try to grab the next node to attempt to connect to. let next = match self.data.highest_not_connected_peer() { Some(p) => p, @@ -527,9 +622,9 @@ impl Peerset { self.data.peers().len() } - /// Returns priority group by id. - pub fn get_priority_group(&self, group_id: &str) -> Option> { - self.data.get_priority_group(group_id) + /// Returns the content of a priority group. + pub fn priority_group(&self, group_id: &str) -> Option> { + self.priority_groups.get(group_id).map(|l| l.iter()) } } @@ -581,7 +676,6 @@ mod tests { assert_eq!(message, expected_message); peerset = p; } - assert!(peerset.message_queue.is_empty(), peerset.message_queue); peerset } @@ -711,4 +805,3 @@ mod tests { futures::executor::block_on(fut); } } - diff --git a/client/peerset/src/peersstate.rs b/client/peerset/src/peersstate.rs index 843ec0a36006f436e3d9b2b9c83175ec632566e5..59879f629e31ecdbfbcb224a8a7dfb437f150746 100644 --- a/client/peerset/src/peersstate.rs +++ b/client/peerset/src/peersstate.rs @@ -14,10 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Contains the state storage behind the peerset. +//! Reputation and slots allocation system behind the peerset. +//! +//! The [`PeersState`] state machine is responsible for managing the reputation and allocating +//! slots. It holds a list of nodes, each associated with a reputation value and whether we are +//! connected or not to this node. Thanks to this list, it knows how many slots are occupied. It +//! also holds a list of nodes which don't occupy slots. +//! +//! > Note: This module is purely dedicated to managing slots and reputations. Features such as +//! > for example connecting to some nodes in priority should be added outside of this +//! > module, rather than inside. use libp2p::PeerId; -use log::{error, warn}; +use log::error; use std::{borrow::Cow, collections::{HashSet, HashMap}}; use wasm_timer::Instant; @@ -37,23 +46,24 @@ pub struct PeersState { /// sort, to make the logic easier. nodes: HashMap, - /// Number of non-priority nodes for which the `ConnectionState` is `In`. + /// Number of slot-occupying nodes for which the `ConnectionState` is `In`. num_in: u32, - /// Number of non-priority nodes for which the `ConnectionState` is `In`. + /// Number of slot-occupying nodes for which the `ConnectionState` is `In`. num_out: u32, - /// Maximum allowed number of non-priority nodes for which the `ConnectionState` is `In`. + /// Maximum allowed number of slot-occupying nodes for which the `ConnectionState` is `In`. max_in: u32, - /// Maximum allowed number of non-priority nodes for which the `ConnectionState` is `Out`. + /// Maximum allowed number of slot-occupying nodes for which the `ConnectionState` is `Out`. max_out: u32, - /// Priority groups. Each group is identified by a string ID and contains a set of peer IDs. - priority_nodes: HashMap>, - - /// Only allow connections to/from peers in a priority group. - priority_only: bool, + /// List of node identities (discovered or not) that don't occupy slots. + /// + /// Note for future readers: this module is purely dedicated to managing slots. If you are + /// considering adding more features, please consider doing so outside of this module rather + /// than inside. + no_slot_nodes: HashSet, } /// State of a single node that we know about. @@ -106,15 +116,14 @@ impl ConnectionState { impl PeersState { /// Builds a new empty `PeersState`. - pub fn new(in_peers: u32, out_peers: u32, priority_only: bool) -> Self { + pub fn new(in_peers: u32, out_peers: u32) -> Self { PeersState { nodes: HashMap::new(), num_in: 0, num_out: 0, max_in: in_peers, max_out: out_peers, - priority_nodes: HashMap::new(), - priority_only, + no_slot_nodes: HashSet::new(), } } @@ -157,34 +166,6 @@ impl PeersState { .map(|(p, _)| p) } - /// Returns the first priority peer that we are not connected to. - /// - /// If multiple nodes are prioritized, which one is returned is unspecified. - pub fn priority_not_connected_peer(&mut self) -> Option { - let id = self.priority_nodes.values() - .flatten() - .find(|&id| self.nodes.get(id).map_or(false, |node| !node.connection_state.is_connected())) - .cloned(); - id.map(move |id| NotConnectedPeer { - state: self, - peer_id: Cow::Owned(id), - }) - } - - /// Returns the first priority peer that we are not connected to. - /// - /// If multiple nodes are prioritized, which one is returned is unspecified. - pub fn priority_not_connected_peer_from_group(&mut self, group_id: &str) -> Option { - let id = self.priority_nodes.get(group_id) - .and_then(|group| group.iter() - .find(|&id| self.nodes.get(id).map_or(false, |node| !node.connection_state.is_connected())) - .cloned()); - id.map(move |id| NotConnectedPeer { - state: self, - peer_id: Cow::Owned(id), - }) - } - /// Returns the peer with the highest reputation and that we are not connected to. /// /// If multiple nodes have the same reputation, which one is returned is unspecified. @@ -212,170 +193,40 @@ impl PeersState { } } - fn disconnect(&mut self, peer_id: &PeerId) { - let is_priority = self.is_priority(peer_id); - if let Some(mut node) = self.nodes.get_mut(peer_id) { - if !is_priority { - match node.connection_state { - ConnectionState::In => self.num_in -= 1, - ConnectionState::Out => self.num_out -= 1, - ConnectionState::NotConnected { .. } => - debug_assert!(false, "State inconsistency: disconnecting a disconnected node") - } - } - node.connection_state = ConnectionState::NotConnected { - last_connected: Instant::now(), - }; - } else { - warn!(target: "peerset", "Attempting to disconnect unknown peer {}", peer_id); - } - } - - /// Sets the peer as connected with an outgoing connection. - fn try_outgoing(&mut self, peer_id: &PeerId) -> bool { - let is_priority = self.is_priority(peer_id); - - // We are only accepting connections from priority nodes. - if !is_priority && self.priority_only { - return false; - } - - // Note that it is possible for num_out to be strictly superior to the max, in case we were - // connected to reserved node then marked them as not reserved. - if self.num_out >= self.max_out && !is_priority { - return false; + /// Add a node to the list of nodes that don't occupy slots. + /// + /// Has no effect if the peer was already in the group. + pub fn add_no_slot_node(&mut self, peer_id: PeerId) { + // Reminder: `HashSet::insert` returns false if the node was already in the set + if !self.no_slot_nodes.insert(peer_id.clone()) { + return; } - if let Some(mut peer) = self.nodes.get_mut(peer_id) { - peer.connection_state = ConnectionState::Out; - if !is_priority { - self.num_out += 1; + if let Some(peer) = self.nodes.get_mut(&peer_id) { + match peer.connection_state { + ConnectionState::In => self.num_in -= 1, + ConnectionState::Out => self.num_out -= 1, + ConnectionState::NotConnected { .. } => {}, } - return true; } - false } - /// Tries to accept the peer as an incoming connection. - /// - /// If there are enough slots available, switches the node to "connected" and returns `true`. If - /// the slots are full, the node stays "not connected" and we return `false`. + /// Removes a node from the list of nodes that don't occupy slots. /// - /// Note that reserved nodes don't count towards the number of slots. - fn try_accept_incoming(&mut self, peer_id: &PeerId) -> bool { - let is_priority = self.is_priority(peer_id); - - // We are only accepting connections from priority nodes. - if !is_priority && self.priority_only { - return false; + /// Has no effect if the peer was not in the group. + pub fn remove_no_slot_node(&mut self, peer_id: &PeerId) { + // Reminder: `HashSet::remove` returns false if the node was already not in the set + if !self.no_slot_nodes.remove(peer_id) { + return; } - // Note that it is possible for num_in to be strictly superior to the max, in case we were - // connected to reserved node then marked them as not reserved. - if self.num_in >= self.max_in && !is_priority { - return false; - } - if let Some(mut peer) = self.nodes.get_mut(peer_id) { - peer.connection_state = ConnectionState::In; - if !is_priority { - self.num_in += 1; + if let Some(peer) = self.nodes.get_mut(peer_id) { + match peer.connection_state { + ConnectionState::In => self.num_in += 1, + ConnectionState::Out => self.num_out += 1, + ConnectionState::NotConnected { .. } => {}, } - return true; } - false - } - - /// Sets priority group - pub fn set_priority_group(&mut self, group_id: &str, peers: HashSet) { - // update slot counters - let all_other_groups: HashSet<_> = self.priority_nodes - .iter() - .filter(|(g, _)| *g != group_id) - .flat_map(|(_, id)| id.clone()) - .collect(); - let existing_group = self.priority_nodes.remove(group_id).unwrap_or_default(); - for id in existing_group { - // update slots for nodes that are no longer priority - if !all_other_groups.contains(&id) { - if let Some(peer) = self.nodes.get_mut(&id) { - match peer.connection_state { - ConnectionState::In => self.num_in += 1, - ConnectionState::Out => self.num_out += 1, - ConnectionState::NotConnected { .. } => {}, - } - } - } - } - - for id in &peers { - // update slots for nodes that become priority - if !all_other_groups.contains(id) { - let peer = self.nodes.entry(id.clone()).or_default(); - match peer.connection_state { - ConnectionState::In => self.num_in -= 1, - ConnectionState::Out => self.num_out -= 1, - ConnectionState::NotConnected { .. } => {}, - } - } - } - self.priority_nodes.insert(group_id.into(), peers); - } - - /// Add a peer to a priority group. - pub fn add_to_priority_group(&mut self, group_id: &str, peer_id: PeerId) { - let mut peers = self.priority_nodes.get(group_id).cloned().unwrap_or_default(); - peers.insert(peer_id); - self.set_priority_group(group_id, peers); - } - - /// Remove a peer from a priority group. - pub fn remove_from_priority_group(&mut self, group_id: &str, peer_id: &PeerId) { - let mut peers = self.priority_nodes.get(group_id).cloned().unwrap_or_default(); - peers.remove(peer_id); - self.set_priority_group(group_id, peers); - } - - /// Get priority group content. - pub fn get_priority_group(&self, group_id: &str) -> Option> { - self.priority_nodes.get(group_id).cloned() - } - - /// Set whether to only allow connections to/from peers in a priority group. - /// Calling this method does not affect any existing connection, e.g. - /// enabling priority only will not disconnect from any non-priority peers - /// we are already connected to, only future incoming/outgoing connection - /// attempts will be affected. - pub fn set_priority_only(&mut self, priority: bool) { - self.priority_only = priority; - } - - /// Check that node is any priority group. - fn is_priority(&self, peer_id: &PeerId) -> bool { - self.priority_nodes.iter().any(|(_, group)| group.contains(peer_id)) - } - - /// Returns the reputation value of the node. - fn reputation(&self, peer_id: &PeerId) -> i32 { - self.nodes.get(peer_id).map_or(0, |p| p.reputation) - } - - /// Sets the reputation of the peer. - fn set_reputation(&mut self, peer_id: &PeerId, value: i32) { - let node = self.nodes - .entry(peer_id.clone()) - .or_default(); - node.reputation = value; - } - - /// Performs an arithmetic addition on the reputation score of that peer. - /// - /// In case of overflow, the value will be capped. - /// If the peer is unknown to us, we insert it and consider that it has a reputation of 0. - fn add_reputation(&mut self, peer_id: &PeerId, modifier: i32) { - let node = self.nodes - .entry(peer_id.clone()) - .or_default(); - node.reputation = node.reputation.saturating_add(modifier); } } @@ -437,7 +288,23 @@ impl<'a> ConnectedPeer<'a> { /// Switches the peer to "not connected". pub fn disconnect(self) -> NotConnectedPeer<'a> { - self.state.disconnect(&self.peer_id); + let is_no_slot_occupy = self.state.no_slot_nodes.contains(&*self.peer_id); + if let Some(mut node) = self.state.nodes.get_mut(&*self.peer_id) { + if !is_no_slot_occupy { + match node.connection_state { + ConnectionState::In => self.state.num_in -= 1, + ConnectionState::Out => self.state.num_out -= 1, + ConnectionState::NotConnected { .. } => + debug_assert!(false, "State inconsistency: disconnecting a disconnected node") + } + } + node.connection_state = ConnectionState::NotConnected { + last_connected: Instant::now(), + }; + } else { + debug_assert!(false, "State inconsistency: disconnecting a disconnected node"); + } + NotConnectedPeer { state: self.state, peer_id: self.peer_id, @@ -446,19 +313,27 @@ impl<'a> ConnectedPeer<'a> { /// Returns the reputation value of the node. pub fn reputation(&self) -> i32 { - self.state.reputation(&self.peer_id) + self.state.nodes.get(&*self.peer_id).map_or(0, |p| p.reputation) } /// Sets the reputation of the peer. pub fn set_reputation(&mut self, value: i32) { - self.state.set_reputation(&self.peer_id, value) + if let Some(node) = self.state.nodes.get_mut(&*self.peer_id) { + node.reputation = value; + } else { + debug_assert!(false, "State inconsistency: set_reputation on an unknown node"); + } } /// Performs an arithmetic addition on the reputation score of that peer. /// /// In case of overflow, the value will be capped. pub fn add_reputation(&mut self, modifier: i32) { - self.state.add_reputation(&self.peer_id, modifier) + if let Some(node) = self.state.nodes.get_mut(&*self.peer_id) { + node.reputation = node.reputation.saturating_add(modifier); + } else { + debug_assert!(false, "State inconsistency: add_reputation on an unknown node"); + } } } @@ -520,16 +395,29 @@ impl<'a> NotConnectedPeer<'a> { /// If there are enough slots available, switches the node to "connected" and returns `Ok`. If /// the slots are full, the node stays "not connected" and we return `Err`. /// - /// Note that priority nodes don't count towards the number of slots. + /// Non-slot-occupying nodes don't count towards the number of slots. pub fn try_outgoing(self) -> Result, NotConnectedPeer<'a>> { - if self.state.try_outgoing(&self.peer_id) { - Ok(ConnectedPeer { - state: self.state, - peer_id: self.peer_id, - }) + let is_no_slot_occupy = self.state.no_slot_nodes.contains(&*self.peer_id); + + // Note that it is possible for num_out to be strictly superior to the max, in case we were + // connected to reserved node then marked them as not reserved. + if self.state.num_out >= self.state.max_out && !is_no_slot_occupy { + return Err(self); + } + + if let Some(mut peer) = self.state.nodes.get_mut(&*self.peer_id) { + peer.connection_state = ConnectionState::Out; + if !is_no_slot_occupy { + self.state.num_out += 1; + } } else { - Err(self) + debug_assert!(false, "State inconsistency: try_outgoing on an unknown node"); } + + Ok(ConnectedPeer { + state: self.state, + peer_id: self.peer_id, + }) } /// Tries to accept the peer as an incoming connection. @@ -537,34 +425,54 @@ impl<'a> NotConnectedPeer<'a> { /// If there are enough slots available, switches the node to "connected" and returns `Ok`. If /// the slots are full, the node stays "not connected" and we return `Err`. /// - /// Note that priority nodes don't count towards the number of slots. + /// Non-slot-occupying nodes don't count towards the number of slots. pub fn try_accept_incoming(self) -> Result, NotConnectedPeer<'a>> { - if self.state.try_accept_incoming(&self.peer_id) { - Ok(ConnectedPeer { - state: self.state, - peer_id: self.peer_id, - }) + let is_no_slot_occupy = self.state.no_slot_nodes.contains(&*self.peer_id); + + // Note that it is possible for num_in to be strictly superior to the max, in case we were + // connected to reserved node then marked them as not reserved. + if self.state.num_in >= self.state.max_in && !is_no_slot_occupy { + return Err(self); + } + + if let Some(mut peer) = self.state.nodes.get_mut(&*self.peer_id) { + peer.connection_state = ConnectionState::In; + if !is_no_slot_occupy { + self.state.num_in += 1; + } } else { - Err(self) + debug_assert!(false, "State inconsistency: try_accept_incoming on an unknown node"); } + + Ok(ConnectedPeer { + state: self.state, + peer_id: self.peer_id, + }) } /// Returns the reputation value of the node. pub fn reputation(&self) -> i32 { - self.state.reputation(&self.peer_id) + self.state.nodes.get(&*self.peer_id).map_or(0, |p| p.reputation) } /// Sets the reputation of the peer. pub fn set_reputation(&mut self, value: i32) { - self.state.set_reputation(&self.peer_id, value) + if let Some(node) = self.state.nodes.get_mut(&*self.peer_id) { + node.reputation = value; + } else { + debug_assert!(false, "State inconsistency: set_reputation on an unknown node"); + } } /// Performs an arithmetic addition on the reputation score of that peer. /// /// In case of overflow, the value will be capped. - /// If the peer is unknown to us, we insert it and consider that it has a reputation of 0. pub fn add_reputation(&mut self, modifier: i32) { - self.state.add_reputation(&self.peer_id, modifier) + if let Some(node) = self.state.nodes.get_mut(&*self.peer_id) { + node.reputation = node.reputation.saturating_add(modifier); + } else { + debug_assert!(false, "State inconsistency: add_reputation on an unknown node"); + } } /// Un-discovers the peer. Removes it from the list. @@ -618,7 +526,7 @@ mod tests { #[test] fn full_slots_in() { - let mut peers_state = PeersState::new(1, 1, false); + let mut peers_state = PeersState::new(1, 1); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -632,14 +540,14 @@ mod tests { } #[test] - fn priority_node_doesnt_use_slot() { - let mut peers_state = PeersState::new(1, 1, false); + fn no_slot_node_doesnt_use_slot() { + let mut peers_state = PeersState::new(1, 1); let id1 = PeerId::random(); let id2 = PeerId::random(); - peers_state.set_priority_group("test", vec![id1.clone()].into_iter().collect()); - if let Peer::NotConnected(p) = peers_state.peer(&id1) { - assert!(p.try_accept_incoming().is_ok()); + peers_state.add_no_slot_node(id1.clone()); + if let Peer::Unknown(p) = peers_state.peer(&id1) { + assert!(p.discover().try_accept_incoming().is_ok()); } else { panic!() } if let Peer::Unknown(e) = peers_state.peer(&id2) { @@ -649,7 +557,7 @@ mod tests { #[test] fn disconnecting_frees_slot() { - let mut peers_state = PeersState::new(1, 1, false); + let mut peers_state = PeersState::new(1, 1); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -659,28 +567,9 @@ mod tests { assert!(peers_state.peer(&id2).into_not_connected().unwrap().try_accept_incoming().is_ok()); } - #[test] - fn priority_not_connected_peer() { - let mut peers_state = PeersState::new(25, 25, false); - let id1 = PeerId::random(); - let id2 = PeerId::random(); - - assert!(peers_state.priority_not_connected_peer().is_none()); - peers_state.peer(&id1).into_unknown().unwrap().discover(); - peers_state.peer(&id2).into_unknown().unwrap().discover(); - - assert!(peers_state.priority_not_connected_peer().is_none()); - peers_state.set_priority_group("test", vec![id1.clone()].into_iter().collect()); - assert!(peers_state.priority_not_connected_peer().is_some()); - peers_state.set_priority_group("test", vec![id2.clone(), id2.clone()].into_iter().collect()); - assert!(peers_state.priority_not_connected_peer().is_some()); - peers_state.set_priority_group("test", vec![].into_iter().collect()); - assert!(peers_state.priority_not_connected_peer().is_none()); - } - #[test] fn highest_not_connected_peer() { - let mut peers_state = PeersState::new(25, 25, false); + let mut peers_state = PeersState::new(25, 25); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -700,87 +589,11 @@ mod tests { } #[test] - fn disconnect_priority_doesnt_panic() { - let mut peers_state = PeersState::new(1, 1, false); + fn disconnect_no_slot_doesnt_panic() { + let mut peers_state = PeersState::new(1, 1); let id = PeerId::random(); - peers_state.set_priority_group("test", vec![id.clone()].into_iter().collect()); - let peer = peers_state.peer(&id).into_not_connected().unwrap().try_outgoing().unwrap(); + peers_state.add_no_slot_node(id.clone()); + let peer = peers_state.peer(&id).into_unknown().unwrap().discover().try_outgoing().unwrap(); peer.disconnect(); } - - #[test] - fn multiple_priority_groups_slot_count() { - let mut peers_state = PeersState::new(1, 1, false); - let id = PeerId::random(); - - if let Peer::Unknown(p) = peers_state.peer(&id) { - assert!(p.discover().try_accept_incoming().is_ok()); - } else { panic!() } - - assert_eq!(peers_state.num_in, 1); - peers_state.set_priority_group("test1", vec![id.clone()].into_iter().collect()); - assert_eq!(peers_state.num_in, 0); - peers_state.set_priority_group("test2", vec![id.clone()].into_iter().collect()); - assert_eq!(peers_state.num_in, 0); - peers_state.set_priority_group("test1", vec![].into_iter().collect()); - assert_eq!(peers_state.num_in, 0); - peers_state.set_priority_group("test2", vec![].into_iter().collect()); - assert_eq!(peers_state.num_in, 1); - } - - #[test] - fn priority_only_mode_ignores_drops_unknown_nodes() { - // test whether connection to/from given peer is allowed - let test_connection = |peers_state: &mut PeersState, id| { - if let Peer::Unknown(p) = peers_state.peer(id) { - p.discover(); - } - - let incoming = if let Peer::NotConnected(p) = peers_state.peer(id) { - p.try_accept_incoming().is_ok() - } else { - panic!() - }; - - if incoming { - peers_state.peer(id).into_connected().map(|p| p.disconnect()); - } - - let outgoing = if let Peer::NotConnected(p) = peers_state.peer(id) { - p.try_outgoing().is_ok() - } else { - panic!() - }; - - if outgoing { - peers_state.peer(id).into_connected().map(|p| p.disconnect()); - } - - incoming || outgoing - }; - - let mut peers_state = PeersState::new(1, 1, true); - let id = PeerId::random(); - - // this is an unknown peer and our peer state is set to only allow - // priority peers so any connection attempt should be denied. - assert!(!test_connection(&mut peers_state, &id)); - - // disabling priority only mode should allow the connection to go - // through. - peers_state.set_priority_only(false); - assert!(test_connection(&mut peers_state, &id)); - - // re-enabling it we should again deny connections from the peer. - peers_state.set_priority_only(true); - assert!(!test_connection(&mut peers_state, &id)); - - // but if we add the peer to a priority group it should be accepted. - peers_state.set_priority_group("TEST_GROUP", vec![id.clone()].into_iter().collect()); - assert!(test_connection(&mut peers_state, &id)); - - // and removing it will cause the connection to once again be denied. - peers_state.remove_from_priority_group("TEST_GROUP", &id); - assert!(!test_connection(&mut peers_state, &id)); - } } diff --git a/client/peerset/tests/fuzz.rs b/client/peerset/tests/fuzz.rs index 44477cec6589dbf2b6ce5922ae4ac3217fe9e973..6fa29e3d834cfcdaa0b035e03849432e20e7b3f3 100644 --- a/client/peerset/tests/fuzz.rs +++ b/client/peerset/tests/fuzz.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use futures::prelude::*; use libp2p::PeerId; @@ -44,13 +46,13 @@ fn test_once() { id }).collect(), priority_groups: { - let list = (0 .. Uniform::new_inclusive(0, 2).sample(&mut rng)).map(|_| { + let nodes = (0 .. Uniform::new_inclusive(0, 2).sample(&mut rng)).map(|_| { let id = PeerId::random(); known_nodes.insert(id.clone()); reserved_nodes.insert(id.clone()); id }).collect(); - vec![("reserved".to_owned(), list)] + vec![("foo".to_string(), nodes)] }, reserved_only: Uniform::new_inclusive(0, 10).sample(&mut rng) == 0, in_peers: Uniform::new_inclusive(0, 25).sample(&mut rng), diff --git a/client/proposer-metrics/Cargo.toml b/client/proposer-metrics/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..4e2a807b5dd35c930018b2d67decd161ea940b4f --- /dev/null +++ b/client/proposer-metrics/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sc-proposer-metrics" +version = "0.8.0-rc2" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "Basic metrics for block production." + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +log = "0.4.8" +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc2"} diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..5cb749f4a260aa1964e230cb8edb3dd9515f595c --- /dev/null +++ b/client/proposer-metrics/src/lib.rs @@ -0,0 +1,67 @@ +// Copyright 2020 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 . + +//! Prometheus basic proposer metrics. + +use prometheus_endpoint::{register, PrometheusError, Registry, Histogram, HistogramOpts, Gauge, U64}; + +/// Optional shareable link to basic authorship metrics. +#[derive(Clone, Default)] +pub struct MetricsLink(Option); + +impl MetricsLink { + pub fn new(registry: Option<&Registry>) -> Self { + Self( + registry.and_then(|registry| + Metrics::register(registry) + .map_err(|err| log::warn!("Failed to register proposer prometheus metrics: {}", err)) + .ok() + ) + ) + } + + pub fn report(&self, do_this: impl FnOnce(&Metrics) -> O) -> Option { + Some(do_this(self.0.as_ref()?)) + } +} + +/// Authorship metrics. +#[derive(Clone)] +pub struct Metrics { + pub block_constructed: Histogram, + pub number_of_transactions: Gauge, +} + +impl Metrics { + pub fn register(registry: &Registry) -> Result { + Ok(Self { + block_constructed: register( + Histogram::with_opts(HistogramOpts::new( + "proposer_block_constructed", + "Histogram of time taken to construct new block", + ))?, + registry, + )?, + number_of_transactions: register( + Gauge::new( + "proposer_number_of_transactions", + "Number of transactions included in block", + )?, + registry, + )?, + }) + } +} diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml index e0dac773bf0991a9b685c2c2ebb9621f9319d4d6..1075c3a11c810ceaf451887e68b40dc92d514c97 100644 --- a/client/rpc-api/Cargo.toml +++ b/client/rpc-api/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-rpc-api" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC interfaces." @@ -21,11 +21,11 @@ jsonrpc-derive = "14.0.3" jsonrpc-pubsub = "14.0.3" log = "0.4.8" parking_lot = "0.10.0" -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-version = { version = "2.0.0-dev", path = "../../primitives/version" } -sp-runtime = { path = "../../primitives/runtime" , version = "2.0.0-dev"} -sp-chain-spec = { path = "../../primitives/chain-spec" , version = "2.0.0-dev"} +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-version = { version = "2.0.0-rc2", path = "../../primitives/version" } +sp-runtime = { path = "../../primitives/runtime" , version = "2.0.0-rc2"} +sp-chain-spec = { path = "../../primitives/chain-spec" , version = "2.0.0-rc2"} serde = { version = "1.0.101", features = ["derive"] } serde_json = "1.0.41" -sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transaction-pool" } -sp-rpc = { version = "2.0.0-dev", path = "../../primitives/rpc" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../primitives/transaction-pool" } +sp-rpc = { version = "2.0.0-rc2", path = "../../primitives/rpc" } diff --git a/client/rpc-api/src/author/error.rs b/client/rpc-api/src/author/error.rs index dfd488e5da37fd86d5a94b40fb893ee3cfcd2ac6..e6ee36cdce19a181f47e4bd34d766c0034e2744c 100644 --- a/client/rpc-api/src/author/error.rs +++ b/client/rpc-api/src/author/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Authoring RPC module errors. diff --git a/client/rpc-api/src/author/mod.rs b/client/rpc-api/src/author/mod.rs index 49c4c996fa9e1705fa4344bcce708ecf66d5b45d..29f5b1d26e84cb9c8644292da26c74e07dd23a39 100644 --- a/client/rpc-api/src/author/mod.rs +++ b/client/rpc-api/src/author/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate block-author/full-node API. diff --git a/client/rpc-api/src/chain/error.rs b/client/rpc-api/src/chain/error.rs index ffa4d82bdff890b923ad51b22ff46ccb5efdee58..fd7bd0a43d778bf2a03be96baa5960e15f3dbd47 100644 --- a/client/rpc-api/src/chain/error.rs +++ b/client/rpc-api/src/chain/error.rs @@ -1,19 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . - +// along with this program. If not, see . //! Error helpers for Chain RPC module. diff --git a/client/rpc-api/src/chain/mod.rs b/client/rpc-api/src/chain/mod.rs index 2ab3851d37663a328e37b4f1d8998d103905d9f3..a7b26f3024248343225c018181b746f86e28a4f1 100644 --- a/client/rpc-api/src/chain/mod.rs +++ b/client/rpc-api/src/chain/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate blockchain API. diff --git a/client/rpc-api/src/child_state/mod.rs b/client/rpc-api/src/child_state/mod.rs index a46269cad6c0c72c7d6478632a7d9971032d5ab9..d956a7554f8ee798d2fa84c777ae33b591f257ce 100644 --- a/client/rpc-api/src/child_state/mod.rs +++ b/client/rpc-api/src/child_state/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate state API. diff --git a/client/rpc-api/src/errors.rs b/client/rpc-api/src/errors.rs index b75c34ead3806a7a0be3bb8104c4a30cd961138e..4e1a5b10fc5128fbb3e36dfb788a23c0575e965d 100644 --- a/client/rpc-api/src/errors.rs +++ b/client/rpc-api/src/errors.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use log::warn; diff --git a/client/rpc-api/src/helpers.rs b/client/rpc-api/src/helpers.rs index 912a5664b3c2fb9a1d48747fb46036ac02057b08..025fef1102c492adfb142a837d7e2f5e6a262e11 100644 --- a/client/rpc-api/src/helpers.rs +++ b/client/rpc-api/src/helpers.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use jsonrpc_core::futures::prelude::*; use futures::{channel::oneshot, compat::Compat}; diff --git a/client/rpc-api/src/offchain/error.rs b/client/rpc-api/src/offchain/error.rs index 695c0cf41fd6da092c970b55a6638dee8ff4ea06..ea5223f1ce7f935aefa8b6629ee2e82eebb48c13 100644 --- a/client/rpc-api/src/offchain/error.rs +++ b/client/rpc-api/src/offchain/error.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Offchain RPC errors. diff --git a/client/rpc-api/src/offchain/mod.rs b/client/rpc-api/src/offchain/mod.rs index bbe466ff5994d450164c47e005e0266e83e52440..427b6a1cc017bfeb09e52a43e14c14fa6ddf8669 100644 --- a/client/rpc-api/src/offchain/mod.rs +++ b/client/rpc-api/src/offchain/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate offchain API. diff --git a/client/rpc-api/src/policy.rs b/client/rpc-api/src/policy.rs index c01b5232f359c2224708f86b43467b4cdf4ca8d2..141dcfbc415f8294d6f140db7ce74012afa200ac 100644 --- a/client/rpc-api/src/policy.rs +++ b/client/rpc-api/src/policy.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Policy-related types. //! @@ -24,21 +26,21 @@ use jsonrpc_core as rpc; /// Signifies whether a potentially unsafe RPC should be denied. #[derive(Clone, Copy, Debug)] pub enum DenyUnsafe { - /// Denies only potentially unsafe RPCs. - Yes, - /// Allows calling every RPCs. - No + /// Denies only potentially unsafe RPCs. + Yes, + /// Allows calling every RPCs. + No, } impl DenyUnsafe { - /// Returns `Ok(())` if the RPCs considered unsafe are safe to call, - /// otherwise returns `Err(UnsafeRpcError)`. - pub fn check_if_safe(self) -> Result<(), UnsafeRpcError> { - match self { - DenyUnsafe::Yes => Err(UnsafeRpcError), - DenyUnsafe::No => Ok(()) - } - } + /// Returns `Ok(())` if the RPCs considered unsafe are safe to call, + /// otherwise returns `Err(UnsafeRpcError)`. + pub fn check_if_safe(self) -> Result<(), UnsafeRpcError> { + match self { + DenyUnsafe::Yes => Err(UnsafeRpcError), + DenyUnsafe::No => Ok(()), + } + } } /// Signifies whether an RPC considered unsafe is denied to be called externally. @@ -46,15 +48,15 @@ impl DenyUnsafe { pub struct UnsafeRpcError; impl std::fmt::Display for UnsafeRpcError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "RPC call is unsafe to be called externally") - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "RPC call is unsafe to be called externally") + } } impl std::error::Error for UnsafeRpcError {} impl From for rpc::Error { - fn from(_: UnsafeRpcError) -> rpc::Error { - rpc::Error::method_not_found() - } + fn from(_: UnsafeRpcError) -> rpc::Error { + rpc::Error::method_not_found() + } } diff --git a/client/rpc-api/src/state/error.rs b/client/rpc-api/src/state/error.rs index c9c2cf4e454d403dd63baaf383d6e85467996306..2fcca3c343f09efdd2acb1ce767cb2f80a80e5bd 100644 --- a/client/rpc-api/src/state/error.rs +++ b/client/rpc-api/src/state/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! State RPC errors. diff --git a/client/rpc-api/src/state/helpers.rs b/client/rpc-api/src/state/helpers.rs index 516b6c80c49a7bfcb931f10bbdc771a81d685b19..0d176ea67f35be0449bf8bb63c49401260e39070 100644 --- a/client/rpc-api/src/state/helpers.rs +++ b/client/rpc-api/src/state/helpers.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate state API helpers. diff --git a/client/rpc-api/src/state/mod.rs b/client/rpc-api/src/state/mod.rs index 3d38a16eb4a988137cd79905daa24b0c98153ad1..1bfbb4786e677bb2eb89cb2b51346f9ae4d56890 100644 --- a/client/rpc-api/src/state/mod.rs +++ b/client/rpc-api/src/state/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate state API. diff --git a/client/rpc-api/src/subscriptions.rs b/client/rpc-api/src/subscriptions.rs index 54881bad5123bfb9c98c0b716f7b1b514bab2d40..7feae662eeb1f31e6ecf6fc0c7efb61b80996d21 100644 --- a/client/rpc-api/src/subscriptions.rs +++ b/client/rpc-api/src/subscriptions.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::collections::HashMap; use std::sync::{Arc, atomic::{self, AtomicUsize}}; diff --git a/client/rpc-api/src/system/error.rs b/client/rpc-api/src/system/error.rs index fbb4e44bcb635f0bdb486f0b581068e1d342c061..4897aa485cbe47591b787e771fda59543d3644c4 100644 --- a/client/rpc-api/src/system/error.rs +++ b/client/rpc-api/src/system/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! System RPC module errors. diff --git a/client/rpc-api/src/system/helpers.rs b/client/rpc-api/src/system/helpers.rs index 46461d69888c18b86b4de44eb9c1f4941547a103..5dbe93543d8e5313a617a91ccfd3fa919ec661ee 100644 --- a/client/rpc-api/src/system/helpers.rs +++ b/client/rpc-api/src/system/helpers.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate system API helpers. diff --git a/client/rpc-api/src/system/mod.rs b/client/rpc-api/src/system/mod.rs index 486623477ecf1fc87c950ded18052e9b0b240a56..a7b746ee1b114afa525b5c077d22bf34ec1d5f54 100644 --- a/client/rpc-api/src/system/mod.rs +++ b/client/rpc-api/src/system/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate system API. diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 345aff13d8da75553bf7d80cdf5e9e214bf0bf1e..401f5f488253024ba8ec91bb49a314fb52c82032 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-rpc-server" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC servers." @@ -17,7 +17,7 @@ pubsub = { package = "jsonrpc-pubsub", version = "14.0.3" } log = "0.4.8" serde = "1.0.101" serde_json = "1.0.41" -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } [target.'cfg(not(target_os = "unknown"))'.dependencies] http = { package = "jsonrpc-http-server", version = "14.0.3" } diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs index 97fb10c15e4b5593ac247beb25563d29d7627648..6fe4586b6ee5eecf211512d5d953e2123da7e3cc 100644 --- a/client/rpc-servers/src/lib.rs +++ b/client/rpc-servers/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate RPC servers. diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index 66f7cb50e6d1272f8aecfe4975187fd16153674b..62f93195758b94884ed78333ea4280a3480df48e 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-rpc" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate Client RPC" @@ -12,37 +12,38 @@ description = "Substrate Client RPC" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sc-rpc-api = { version = "0.8.0-dev", path = "../rpc-api" } -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } +sc-rpc-api = { version = "0.8.0-rc2", path = "../rpc-api" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } codec = { package = "parity-scale-codec", version = "1.3.0" } futures = { version = "0.3.1", features = ["compat"] } jsonrpc-pubsub = "14.0.3" log = "0.4.8" -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } rpc = { package = "jsonrpc-core", version = "14.0.3" } -sp-version = { version = "2.0.0-dev", path = "../../primitives/version" } +sp-version = { version = "2.0.0-rc2", path = "../../primitives/version" } serde_json = "1.0.41" -sp-session = { version = "2.0.0-dev", path = "../../primitives/session" } -sp-offchain = { version = "2.0.0-dev", path = "../../primitives/offchain" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" } -sp-rpc = { version = "2.0.0-dev", path = "../../primitives/rpc" } -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } -sp-chain-spec = { version = "2.0.0-dev", path = "../../primitives/chain-spec" } -sc-executor = { version = "0.8.0-dev", path = "../executor" } -sc-block-builder = { version = "0.8.0-dev", path = "../../client/block-builder" } -sc-keystore = { version = "2.0.0-dev", path = "../keystore" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transaction-pool" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } +sp-session = { version = "2.0.0-rc2", path = "../../primitives/session" } +sp-offchain = { version = "2.0.0-rc2", path = "../../primitives/offchain" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } +sp-rpc = { version = "2.0.0-rc2", path = "../../primitives/rpc" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } +sp-chain-spec = { version = "2.0.0-rc2", path = "../../primitives/chain-spec" } +sc-executor = { version = "0.8.0-rc2", path = "../executor" } +sc-block-builder = { version = "0.8.0-rc2", path = "../../client/block-builder" } +sc-keystore = { version = "2.0.0-rc2", path = "../keystore" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../primitives/transaction-pool" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } hash-db = { version = "0.15.2", default-features = false } parking_lot = "0.10.0" [dev-dependencies] assert_matches = "1.3.0" futures01 = { package = "futures", version = "0.1.29" } -sc-network = { version = "0.8.0-dev", path = "../network" } -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } tokio = "0.1.22" -sc-transaction-pool = { version = "2.0.0-dev", path = "../transaction-pool" } +sc-transaction-pool = { version = "2.0.0-rc2", path = "../transaction-pool" } +lazy_static = "1.4.0" diff --git a/client/rpc/src/author/mod.rs b/client/rpc/src/author/mod.rs index 23aed953d01df3151f926e55e7b310cad4accf53..d59fad354ef3c74d7439ea6eb013f1d1450e84ac 100644 --- a/client/rpc/src/author/mod.rs +++ b/client/rpc/src/author/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate block-author/full-node API. diff --git a/client/rpc/src/author/tests.rs b/client/rpc/src/author/tests.rs index de2ee92fe3674c869bb4d954b973c81d28160f01..8c1b82028bd798b60d18ac3cca51e8987d2709a7 100644 --- a/client/rpc/src/author/tests.rs +++ b/client/rpc/src/author/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use super::*; @@ -30,7 +32,7 @@ use substrate_test_runtime_client::{ DefaultTestClientBuilderExt, TestClientBuilderExt, Backend, Client, }; use sc_transaction_pool::{BasicPool, FullChainApi}; -use tokio::runtime; +use futures::{executor, compat::Future01CompatExt}; fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { let tx = Transfer { @@ -48,7 +50,6 @@ type FullTransactionPool = BasicPool< >; struct TestSetup { - pub runtime: runtime::Runtime, pub client: Arc>, pub keystore: BareCryptoStorePtr, pub pool: Arc, @@ -68,7 +69,6 @@ impl Default for TestSetup { None, ).0); TestSetup { - runtime: runtime::Runtime::new().expect("Failed to create runtime in test setup"), client, keystore, pool, @@ -81,7 +81,7 @@ impl TestSetup { Author { client: self.client.clone(), pool: self.pool.clone(), - subscriptions: Subscriptions::new(Arc::new(self.runtime.executor())), + subscriptions: Subscriptions::new(Arc::new(crate::testing::TaskExecutor)), keystore: self.keystore.clone(), deny_unsafe: DenyUnsafe::No, } @@ -121,16 +121,20 @@ fn submit_rich_transaction_should_not_cause_error() { #[test] fn should_watch_extrinsic() { //given - let mut setup = TestSetup::default(); + let setup = TestSetup::default(); let p = setup.author(); let (subscriber, id_rx, data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); // when - p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 0).encode().into()); + p.watch_extrinsic( + Default::default(), + subscriber, + uxt(AccountKeyring::Alice, 0).encode().into(), + ); // then - assert_eq!(setup.runtime.block_on(id_rx), Ok(Ok(1.into()))); + assert_eq!(executor::block_on(id_rx.compat()), Ok(Ok(1.into()))); // check notifications let replacement = { let tx = Transfer { @@ -142,14 +146,14 @@ fn should_watch_extrinsic() { tx.into_signed_tx() }; AuthorApi::submit_extrinsic(&p, replacement.encode().into()).wait().unwrap(); - let (res, data) = setup.runtime.block_on(data.into_future()).unwrap(); + let (res, data) = executor::block_on(data.into_future().compat()).unwrap(); assert_eq!( res, Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":"ready","subscription":1}}"#.into()) ); let h = blake2_256(&replacement.encode()); assert_eq!( - setup.runtime.block_on(data.into_future()).unwrap().0, + executor::block_on(data.into_future().compat()).unwrap().0, Some(format!(r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":1}}}}"#, HexDisplay::from(&h))) ); } @@ -157,7 +161,7 @@ fn should_watch_extrinsic() { #[test] fn should_return_watch_validation_error() { //given - let mut setup = TestSetup::default(); + let setup = TestSetup::default(); let p = setup.author(); let (subscriber, id_rx, _data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); @@ -166,7 +170,7 @@ fn should_return_watch_validation_error() { p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 179).encode().into()); // then - let res = setup.runtime.block_on(id_rx).unwrap(); + let res = executor::block_on(id_rx.compat()).unwrap(); assert!(res.is_err(), "Expected the transaction to be rejected as invalid."); } diff --git a/client/rpc/src/chain/mod.rs b/client/rpc/src/chain/mod.rs index bd2e41bd4b685b37ac913f21b2c65580578aba1e..6d53fbbb06f6ed9871b4cc9faa59fff2b7db84c0 100644 --- a/client/rpc/src/chain/mod.rs +++ b/client/rpc/src/chain/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate blockchain API. diff --git a/client/rpc/src/chain/tests.rs b/client/rpc/src/chain/tests.rs index 68d904919b3d74faba6b8bb4add1f56776ab0e9c..e86d1d547fbdebf6c8e9623d3fe350f3784c64c7 100644 --- a/client/rpc/src/chain/tests.rs +++ b/client/rpc/src/chain/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use super::*; use assert_matches::assert_matches; @@ -23,14 +25,13 @@ use substrate_test_runtime_client::{ }; use sp_rpc::list::ListOrValue; use sc_block_builder::BlockBuilderProvider; +use futures::{executor, compat::{Future01CompatExt, Stream01CompatExt}}; +use crate::testing::TaskExecutor; #[test] fn should_return_header() { - let core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); assert_matches!( api.header(Some(client.genesis_hash()).into()).wait(), @@ -61,11 +62,8 @@ fn should_return_header() { #[test] fn should_return_a_block() { - let core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; let block_hash = block.hash(); @@ -115,11 +113,8 @@ fn should_return_a_block() { #[test] fn should_return_block_hash() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); assert_matches!( api.block_hash(None.into()), @@ -162,11 +157,8 @@ fn should_return_block_hash() { #[test] fn should_return_finalized_hash() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); assert_matches!( api.finalized_head(), @@ -192,76 +184,70 @@ fn should_return_finalized_hash() { #[test] fn should_notify_about_latest_block() { - let mut core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); api.subscribe_all_heads(Default::default(), subscriber); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert_eq!(executor::block_on(id.compat()), Ok(Ok(SubscriptionId::Number(1)))); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; client.import(BlockOrigin::Own, block).unwrap(); } // assert initial head sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); + let (notification, next) = executor::block_on(next.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } #[test] fn should_notify_about_best_block() { - let mut core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); api.subscribe_new_heads(Default::default(), subscriber); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert_eq!(executor::block_on(id.compat()), Ok(Ok(SubscriptionId::Number(1)))); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; client.import(BlockOrigin::Own, block).unwrap(); } // assert initial head sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); + let (notification, next) = executor::block_on(next.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(Stream01CompatExt::compat(next).into_future()).0, None); } #[test] 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"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); api.subscribe_finalized_heads(Default::default(), subscriber); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert_eq!(executor::block_on(id.compat()), Ok(Ok(SubscriptionId::Number(1)))); let block = client.new_block(Default::default()).unwrap().build().unwrap().block; client.import(BlockOrigin::Own, block).unwrap(); @@ -269,11 +255,11 @@ fn should_notify_about_finalized_block() { } // assert initial head sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); + let (notification, next) = executor::block_on(next.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index c4389913b4ffdda3ae4bb233583f55cc2d947dc2..f979b0ab6957e9702795ed9da292cc833143a070 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate RPC implementation. //! @@ -31,3 +33,5 @@ pub mod chain; pub mod offchain; pub mod state; pub mod system; +#[cfg(test)] +mod testing; diff --git a/client/rpc/src/metadata.rs b/client/rpc/src/metadata.rs index d35653f8e6278b966cee9e4933577b07075ba786..0416b07a6797bb21501bb71f343106efa595087f 100644 --- a/client/rpc/src/metadata.rs +++ b/client/rpc/src/metadata.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! RPC Metadata use std::sync::Arc; diff --git a/client/rpc/src/offchain/mod.rs b/client/rpc/src/offchain/mod.rs index 16c03395c738784c44de30682e3fb10c6f1ae15b..f8d2bb6a50f9c653491dc0536e019ad99ce20aa1 100644 --- a/client/rpc/src/offchain/mod.rs +++ b/client/rpc/src/offchain/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate offchain API. diff --git a/client/rpc/src/offchain/tests.rs b/client/rpc/src/offchain/tests.rs index cb05f3d4dbb890499ff140ac6e913e62b29c46d0..f65971a7ffe8ae278495dfb80921e979806c187a 100644 --- a/client/rpc/src/offchain/tests.rs +++ b/client/rpc/src/offchain/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use super::*; use assert_matches::assert_matches; diff --git a/client/rpc/src/state/mod.rs b/client/rpc/src/state/mod.rs index d1f4e2c5f9c164ac800c0c56f45f41d49a6089dc..168dc3e0105a49602fd508b1a6c6e80d025ddef2 100644 --- a/client/rpc/src/state/mod.rs +++ b/client/rpc/src/state/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate state API. diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index da904f3fdc6c5f17e294e0b118d5174d3268cf91..a610cbbfc8285f63c0ea6af6e46109a8c165aed8 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use super::*; use super::state_full::split_range; @@ -31,6 +33,8 @@ use substrate_test_runtime_client::{ runtime, }; use sp_runtime::generic::BlockId; +use crate::testing::TaskExecutor; +use futures::{executor, compat::Future01CompatExt}; const STORAGE_KEY: &[u8] = b"child"; @@ -46,13 +50,12 @@ fn should_return_storage() { const CHILD_VALUE: &[u8] = b"hello world !"; let child_info = ChildInfo::new_default(STORAGE_KEY); - let mut core = tokio::runtime::Runtime::new().unwrap(); let client = TestClientBuilder::new() .add_extra_storage(KEY.to_vec(), VALUE.to_vec()) .add_extra_child_storage(&child_info, KEY.to_vec(), CHILD_VALUE.to_vec()) .build(); let genesis_hash = client.genesis_hash(); - let (client, child) = new_full(Arc::new(client), Subscriptions::new(Arc::new(core.executor()))); + let (client, child) = new_full(Arc::new(client), Subscriptions::new(Arc::new(TaskExecutor))); let key = StorageKey(KEY.to_vec()); assert_eq!( @@ -70,9 +73,10 @@ fn should_return_storage() { VALUE.len(), ); assert_eq!( - core.block_on( + executor::block_on( child.storage(prefixed_storage_key(), key, Some(genesis_hash).into()) .map(|x| x.map(|x| x.0.len())) + .compat(), ).unwrap().unwrap() as usize, CHILD_VALUE.len(), ); @@ -82,12 +86,11 @@ fn should_return_storage() { #[test] fn should_return_child_storage() { let child_info = ChildInfo::new_default(STORAGE_KEY); - let core = tokio::runtime::Runtime::new().unwrap(); let client = Arc::new(substrate_test_runtime_client::TestClientBuilder::new() .add_child_storage(&child_info, "key", vec![42_u8]) .build()); let genesis_hash = client.genesis_hash(); - let (_client, child) = new_full(client, Subscriptions::new(Arc::new(core.executor()))); + let (_client, child) = new_full(client, Subscriptions::new(Arc::new(TaskExecutor))); let child_key = prefixed_storage_key(); let key = StorageKey(b"key".to_vec()); @@ -120,10 +123,9 @@ fn should_return_child_storage() { #[test] fn should_call_contract() { - let core = tokio::runtime::Runtime::new().unwrap(); let client = Arc::new(substrate_test_runtime_client::new()); let genesis_hash = client.genesis_hash(); - let (client, _child) = new_full(client, Subscriptions::new(Arc::new(core.executor()))); + let (client, _child) = new_full(client, Subscriptions::new(Arc::new(TaskExecutor))); assert_matches!( client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()).wait(), @@ -133,18 +135,16 @@ fn should_call_contract() { #[test] fn should_notify_about_storage_changes() { - let mut core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); api.subscribe_storage(Default::default(), subscriber, None.into()); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert_eq!(executor::block_on(id.compat()), Ok(Ok(SubscriptionId::Number(1)))); let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { @@ -158,21 +158,19 @@ fn should_notify_about_storage_changes() { } // assert notification sent to transport - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } #[test] fn should_send_initial_storage_changes_and_notifications() { - let mut core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let mut client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())); @@ -181,7 +179,7 @@ fn should_send_initial_storage_changes_and_notifications() { ]).into()); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert_eq!(executor::block_on(id.compat()), Ok(Ok(SubscriptionId::Number(1)))); let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { @@ -195,20 +193,19 @@ fn should_send_initial_storage_changes_and_notifications() { } // assert initial values sent to transport - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); + let (notification, next) = executor::block_on(next.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } #[test] fn should_query_storage() { fn run_tests(mut client: Arc, has_changes_trie_config: bool) { - let core = tokio::runtime::Runtime::new().unwrap(); - let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); let mut add_block = |nonce| { let mut builder = client.new_block(Default::default()).unwrap(); @@ -424,10 +421,8 @@ fn should_split_ranges() { #[test] fn should_return_runtime_version() { - let core = tokio::runtime::Runtime::new().unwrap(); - let client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",3],\ @@ -446,24 +441,23 @@ fn should_return_runtime_version() { #[test] fn should_notify_on_runtime_version_initially() { - let mut core = tokio::runtime::Runtime::new().unwrap(); let (subscriber, id, transport) = Subscriber::new_test("test"); { let client = Arc::new(substrate_test_runtime_client::new()); - let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(TaskExecutor))); api.subscribe_runtime_version(Default::default(), subscriber); // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + assert_eq!(executor::block_on(id.compat()), Ok(Ok(SubscriptionId::Number(1)))); } // assert initial version sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); + let (notification, next) = executor::block_on(transport.into_future().compat()).unwrap(); assert!(notification.is_some()); // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); + assert_eq!(executor::block_on(next.into_future().compat()).unwrap().0, None); } #[test] diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs index 2a19e5412ed4f6a01c74f76377c314de5fecc738..4b8abbe1444620e23467edfef567d9fd0f71c570 100644 --- a/client/rpc/src/system/mod.rs +++ b/client/rpc/src/system/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate system API. diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs index d0ec6951260fac346973e9c2b35f8992b8315f7a..25ebd80953be611e1d9bf20188714a5034ea95b3 100644 --- a/client/rpc/src/system/tests.rs +++ b/client/rpc/src/system/tests.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use super::*; diff --git a/client/rpc/src/testing.rs b/client/rpc/src/testing.rs new file mode 100644 index 0000000000000000000000000000000000000000..afca07a7fbe6a63048c9cfdc4d44cf2fcb933095 --- /dev/null +++ b/client/rpc/src/testing.rs @@ -0,0 +1,44 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +//! Testing utils used by the RPC tests. + +use rpc::futures::future as future01; +use futures::{executor, compat::Future01CompatExt, FutureExt}; + +// Executor shared by all tests. +// +// This shared executor is used to prevent `Too many open files` errors +// on systems with a lot of cores. +lazy_static::lazy_static! { + static ref EXECUTOR: executor::ThreadPool = executor::ThreadPool::new() + .expect("Failed to create thread pool executor for tests"); +} + +type Boxed01Future01 = Box + Send + 'static>; + +pub struct TaskExecutor; +impl future01::Executor for TaskExecutor { + fn execute( + &self, + future: Boxed01Future01, + ) -> std::result::Result<(), future01::ExecuteError>{ + EXECUTOR.spawn_ok(future.compat().map(drop)); + Ok(()) + } +} diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml index e5f6e229c7020f2e228cea7e1d190e3b496b0a16..fc5991bc3f131d04b2560b58af0c91079e9fbb2b 100644 --- a/client/service/Cargo.toml +++ b/client/service/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-service" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. Manages communication between them." @@ -39,38 +39,38 @@ hash-db = "0.15.2" serde = "1.0.101" serde_json = "1.0.41" sysinfo = "0.13.3" -sc-keystore = { version = "2.0.0-dev", path = "../keystore" } -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-trie = { version = "2.0.0-dev", path = "../../primitives/trie" } -sp-externalities = { version = "0.8.0-dev", path = "../../primitives/externalities" } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" } -sp-version = { version = "2.0.0-dev", path = "../../primitives/version" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-session = { version = "2.0.0-dev", path = "../../primitives/session" } -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } -sp-application-crypto = { version = "2.0.0-dev", path = "../../primitives/application-crypto" } -sp-consensus = { version = "0.8.0-dev", path = "../../primitives/consensus/common" } -sc-network = { version = "0.8.0-dev", path = "../network" } -sc-chain-spec = { version = "2.0.0-dev", path = "../chain-spec" } -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } -sc-client-db = { version = "0.8.0-dev", default-features = false, path = "../db" } +sc-keystore = { version = "2.0.0-rc2", path = "../keystore" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-trie = { version = "2.0.0-rc2", path = "../../primitives/trie" } +sp-externalities = { version = "0.8.0-rc2", path = "../../primitives/externalities" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } +sp-version = { version = "2.0.0-rc2", path = "../../primitives/version" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-session = { version = "2.0.0-rc2", path = "../../primitives/session" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } +sp-application-crypto = { version = "2.0.0-rc2", path = "../../primitives/application-crypto" } +sp-consensus = { version = "0.8.0-rc2", path = "../../primitives/consensus/common" } +sc-network = { version = "0.8.0-rc2", path = "../network" } +sc-chain-spec = { version = "2.0.0-rc2", path = "../chain-spec" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } +sc-client-db = { version = "0.8.0-rc2", default-features = false, path = "../db" } codec = { package = "parity-scale-codec", version = "1.3.0" } -sc-executor = { version = "0.8.0-dev", path = "../executor" } -sc-transaction-pool = { version = "2.0.0-dev", path = "../transaction-pool" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transaction-pool" } -sc-rpc-server = { version = "2.0.0-dev", path = "../rpc-servers" } -sc-rpc = { version = "2.0.0-dev", path = "../rpc" } -sc-block-builder = { version = "0.8.0-dev", path = "../block-builder" } -sp-block-builder = { version = "2.0.0-dev", path = "../../primitives/block-builder" } +sc-executor = { version = "0.8.0-rc2", path = "../executor" } +sc-transaction-pool = { version = "2.0.0-rc2", path = "../transaction-pool" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../primitives/transaction-pool" } +sc-rpc-server = { version = "2.0.0-rc2", path = "../rpc-servers" } +sc-rpc = { version = "2.0.0-rc2", path = "../rpc" } +sc-block-builder = { version = "0.8.0-rc2", path = "../block-builder" } +sp-block-builder = { version = "2.0.0-rc2", path = "../../primitives/block-builder" } -sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" } -sc-offchain = { version = "2.0.0-dev", path = "../offchain" } +sc-telemetry = { version = "2.0.0-rc2", path = "../telemetry" } +sc-offchain = { version = "2.0.0-rc2", path = "../offchain" } parity-multiaddr = { package = "parity-multiaddr", version = "0.7.3" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" , version = "0.8.0-dev"} -sc-tracing = { version = "2.0.0-dev", path = "../tracing" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus" , version = "0.8.0-rc2"} +sc-tracing = { version = "2.0.0-rc2", path = "../tracing" } tracing = "0.1.10" parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] } @@ -83,7 +83,7 @@ procfs = '0.7.8' [dev-dependencies] -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } -sp-consensus-babe = { version = "0.8.0-dev", path = "../../primitives/consensus/babe" } -grandpa = { version = "0.8.0-dev", package = "sc-finality-grandpa", path = "../finality-grandpa" } -grandpa-primitives = { version = "2.0.0-dev", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } +sp-consensus-babe = { version = "0.8.0-rc2", path = "../../primitives/consensus/babe" } +grandpa = { version = "0.8.0-rc2", package = "sc-finality-grandpa", path = "../finality-grandpa" } +grandpa-primitives = { version = "2.0.0-rc2", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" } diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 68abf8e3cdd5efde3d03c7d967dec7340455f929..d921606ea6b16f56662193bc65e2846c68dde4b5 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::{Service, NetworkStatus, NetworkState, error::Error, DEFAULT_PROTOCOL_ID, MallocSizeOfWasm}; use crate::{start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager, SpawnTaskHandle}; @@ -94,12 +96,61 @@ pub struct ServiceBuilder, finality_proof_provider: Option, transaction_pool: Arc, - rpc_extensions: TRpc, + rpc_extensions_builder: Box + Send>, remote_backend: Option>>, marker: PhantomData<(TBl, TRtApi)>, block_announce_validator_builder: Option) -> Box + Send> + Send>>, } +/// A utility trait for building an RPC extension given a `DenyUnsafe` instance. +/// This is useful since at service definition time we don't know whether the +/// specific interface where the RPC extension will be exposed is safe or not. +/// This trait allows us to lazily build the RPC extension whenever we bind the +/// service to an interface. +pub trait RpcExtensionBuilder { + /// The type of the RPC extension that will be built. + type Output: sc_rpc::RpcExtension; + + /// Returns an instance of the RPC extension for a particular `DenyUnsafe` + /// value, e.g. the RPC extension might not expose some unsafe methods. + fn build(&self, deny: sc_rpc::DenyUnsafe) -> Self::Output; +} + +impl RpcExtensionBuilder for F where + F: Fn(sc_rpc::DenyUnsafe) -> R, + R: sc_rpc::RpcExtension, +{ + type Output = R; + + fn build(&self, deny: sc_rpc::DenyUnsafe) -> Self::Output { + (*self)(deny) + } +} + +/// A utility struct for implementing an `RpcExtensionBuilder` given a cloneable +/// `RpcExtension`, the resulting builder will simply ignore the provided +/// `DenyUnsafe` instance and return a static `RpcExtension` instance. +struct NoopRpcExtensionBuilder(R); + +impl RpcExtensionBuilder for NoopRpcExtensionBuilder where + R: Clone + sc_rpc::RpcExtension, +{ + type Output = R; + + fn build(&self, _deny: sc_rpc::DenyUnsafe) -> Self::Output { + self.0.clone() + } +} + +impl From for NoopRpcExtensionBuilder where + R: sc_rpc::RpcExtension, +{ + fn from(e: R) -> NoopRpcExtensionBuilder { + NoopRpcExtensionBuilder(e) + } +} + + /// Full client type. pub type TFullClient = Client< TFullBackend, @@ -309,7 +360,7 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { finality_proof_request_builder: None, finality_proof_provider: None, transaction_pool: Arc::new(()), - rpc_extensions: Default::default(), + rpc_extensions_builder: Box::new(|_| ()), remote_backend: None, block_announce_validator_builder: None, marker: PhantomData, @@ -392,7 +443,7 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { finality_proof_request_builder: None, finality_proof_provider: None, transaction_pool: Arc::new(()), - rpc_extensions: Default::default(), + rpc_extensions_builder: Box::new(|_| ()), remote_backend: Some(remote_blockchain), block_announce_validator_builder: None, marker: PhantomData, @@ -465,7 +516,7 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, @@ -484,7 +535,7 @@ impl /// Defines which import queue to use. pub fn with_import_queue( self, - builder: impl FnOnce(&Configuration, Arc, Option, Arc, &SpawnTaskHandle) + builder: impl FnOnce(&Configuration, Arc, Option, Arc, &SpawnTaskHandle, Option<&Registry>) -> Result ) -> Result, Error> @@ -495,6 +546,7 @@ impl self.select_chain.clone(), self.transaction_pool.clone(), &self.task_manager.spawn_handle(), + self.config.prometheus_config.as_ref().map(|config| &config.registry), )?; Ok(ServiceBuilder { @@ -509,7 +561,7 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, @@ -547,7 +599,7 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, @@ -585,6 +637,7 @@ impl Option, Arc, &SpawnTaskHandle, + Option<&Registry>, ) -> Result<(UImpQu, Option), Error> ) -> Result, Error> @@ -597,6 +650,7 @@ impl self.select_chain.clone(), self.transaction_pool.clone(), &self.task_manager.spawn_handle(), + self.config.prometheus_config.as_ref().map(|config| &config.registry), )?; Ok(ServiceBuilder { @@ -611,7 +665,7 @@ impl finality_proof_request_builder: fprb, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, @@ -629,12 +683,13 @@ impl Option, Arc, &SpawnTaskHandle, + Option<&Registry>, ) -> Result<(UImpQu, UFprb), Error> ) -> Result, Error> where TSc: Clone, TFchr: Clone { - self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx, tb| - builder(cfg, cl, b, f, sc, tx, tb) + self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx, tb, pr| + builder(cfg, cl, b, f, sc, tx, tb, pr) .map(|(q, f)| (q, Some(f))) ) } @@ -674,21 +729,30 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, transaction_pool: Arc::new(transaction_pool), - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, }) } - /// Defines the RPC extensions to use. - pub fn with_rpc_extensions( + /// Defines the RPC extension builder to use. Unlike `with_rpc_extensions`, + /// this method is useful in situations where the RPC extensions need to + /// access to a `DenyUnsafe` instance to avoid exposing sensitive methods. + pub fn with_rpc_extensions_builder( self, - rpc_ext_builder: impl FnOnce(&Self) -> Result, - ) -> Result, Error> - where TSc: Clone, TFchr: Clone { - let rpc_extensions = rpc_ext_builder(&self)?; + rpc_extensions_builder: impl FnOnce(&Self) -> Result, + ) -> Result< + ServiceBuilder, + Error, + > + where + TSc: Clone, + TFchr: Clone, + URpcBuilder: RpcExtensionBuilder + Send + 'static, + URpc: sc_rpc::RpcExtension, + { + let rpc_extensions_builder = rpc_extensions_builder(&self)?; Ok(ServiceBuilder { config: self.config, @@ -702,13 +766,30 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions, + rpc_extensions_builder: Box::new(rpc_extensions_builder), remote_backend: self.remote_backend, block_announce_validator_builder: self.block_announce_validator_builder, marker: self.marker, }) } + /// Defines the RPC extensions to use. + pub fn with_rpc_extensions( + self, + rpc_extensions: impl FnOnce(&Self) -> Result, + ) -> Result< + ServiceBuilder, + Error, + > + where + TSc: Clone, + TFchr: Clone, + URpc: Clone + sc_rpc::RpcExtension + Send + 'static, + { + let rpc_extensions = rpc_extensions(&self)?; + self.with_rpc_extensions_builder(|_| Ok(NoopRpcExtensionBuilder::from(rpc_extensions))) + } + /// Defines the `BlockAnnounceValidator` to use. `DefaultBlockAnnounceValidator` will be used by /// default. pub fn with_block_announce_validator( @@ -730,7 +811,7 @@ impl finality_proof_request_builder: self.finality_proof_request_builder, finality_proof_provider: self.finality_proof_provider, transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, + rpc_extensions_builder: self.rpc_extensions_builder, remote_backend: self.remote_backend, block_announce_validator_builder: Some(Box::new(block_announce_validator_builder)), marker: self.marker, @@ -750,6 +831,7 @@ pub trait ServiceBuilderCommand { self, input: impl Read + Seek + Send + 'static, force: bool, + binary: bool, ) -> Pin> + Send>>; /// Performs the blocks export. @@ -810,7 +892,7 @@ ServiceBuilder< TSc: Clone, TImpQu: 'static + ImportQueue, TExPool: MaintainedTransactionPool::Hash> + MallocSizeOfWasm + 'static, - TRpc: sc_rpc::RpcExtension + Clone, + TRpc: sc_rpc::RpcExtension, { /// Set an ExecutionExtensionsFactory @@ -848,7 +930,7 @@ ServiceBuilder< finality_proof_request_builder, finality_proof_provider, transaction_pool, - rpc_extensions, + rpc_extensions_builder, remote_backend, block_announce_validator_builder, } = self; @@ -883,7 +965,6 @@ ServiceBuilder< imports_external_transactions: !matches!(config.role, Role::Light), pool: transaction_pool.clone(), client: client.clone(), - executor: task_manager.spawn_handle(), }); let protocol_id = { @@ -1155,14 +1236,21 @@ ServiceBuilder< maybe_offchain_rpc, author::AuthorApi::to_delegate(author), system::SystemApi::to_delegate(system), - rpc_extensions.clone(), + rpc_extensions_builder.build(deny_unsafe), )) }; let rpc = start_rpc_servers(&config, gen_handler)?; // This is used internally, so don't restrict access to unsafe RPC let rpc_handlers = gen_handler(sc_rpc::DenyUnsafe::No); - spawn_handle.spawn( + // The network worker is responsible for gathering all network messages and processing + // them. This is quite a heavy task, and at the time of the writing of this comment it + // frequently happens that this future takes several seconds or in some situations + // even more than a minute until it has processed its entire queue. This is clearly an + // issue, and ideally we would like to fix the network future to take as little time as + // possible, but we also take the extra harm-prevention measure to execute the networking + // future using `spawn_blocking`. + spawn_handle.spawn_blocking( "network-worker", build_network_future( config.role.clone(), diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 612e9310d182bbd4b0319f2f06c7246e7faf5c75..cb4ed24b60b624c78a6640ab25ba4cd1ceff7a6b 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Chain utilities. @@ -23,10 +25,10 @@ use sc_chain_spec::ChainSpec; use log::{warn, info}; use futures::{future, prelude::*}; use sp_runtime::traits::{ - Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion + Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion, MaybeSerializeDeserialize, }; use sp_runtime::generic::{BlockId, SignedBlock}; -use codec::{Decode, Encode, IoReader}; +use codec::{Decode, Encode, IoReader as CodecIoReader}; use crate::client::{Client, LocalCallExecutor}; use sp_consensus::{ BlockOrigin, @@ -37,12 +39,252 @@ use sp_core::storage::{StorageKey, well_known_keys, ChildInfo, Storage, StorageC use sc_client_api::{StorageProvider, BlockBackend, UsageProvider}; use std::{io::{Read, Write, Seek}, pin::Pin, collections::HashMap}; +use std::time::{Duration, Instant}; +use futures_timer::Delay; +use std::task::Poll; +use serde_json::{de::IoRead as JsonIoRead, Deserializer, StreamDeserializer}; +use std::convert::{TryFrom, TryInto}; +use sp_runtime::traits::{CheckedDiv, Saturating}; + +/// Number of blocks we will add to the queue before waiting for the queue to catch up. +const MAX_PENDING_BLOCKS: u64 = 1_024; + +/// Number of milliseconds to wait until next poll. +const DELAY_TIME: u64 = 2_000; + +/// Number of milliseconds that must have passed between two updates. +const TIME_BETWEEN_UPDATES: u64 = 3_000; /// Build a chain spec json pub fn build_spec(spec: &dyn ChainSpec, raw: bool) -> error::Result { spec.as_json(raw).map_err(Into::into) } + +/// Helper enum that wraps either a binary decoder (from parity-scale-codec), or a JSON decoder (from serde_json). +/// Implements the Iterator Trait, calling `next()` will decode the next SignedBlock and return it. +enum BlockIter where + R: std::io::Read + std::io::Seek, +{ + Binary { + // Total number of blocks we are expecting to decode. + num_expected_blocks: u64, + // Number of blocks we have decoded thus far. + read_block_count: u64, + // Reader to the data, used for decoding new blocks. + reader: CodecIoReader, + }, + Json { + // Nubmer of blocks we have decoded thus far. + read_block_count: u64, + // Stream to the data, used for decoding new blocks. + reader: StreamDeserializer<'static, JsonIoRead, SignedBlock>, + }, +} + +impl BlockIter where + R: Read + Seek + 'static, + B: BlockT + MaybeSerializeDeserialize, +{ + fn new(input: R, binary: bool) -> Result { + if binary { + let mut reader = CodecIoReader(input); + // If the file is encoded in binary format, it is expected to first specify the number + // of blocks that are going to be decoded. We read it and add it to our enum struct. + let num_expected_blocks: u64 = Decode::decode(&mut reader) + .map_err(|e| format!("Failed to decode the number of blocks: {:?}", e))?; + Ok(BlockIter::Binary { + num_expected_blocks, + read_block_count: 0, + reader, + }) + } else { + let stream_deser = Deserializer::from_reader(input) + .into_iter::>(); + Ok(BlockIter::Json { + reader: stream_deser, + read_block_count: 0, + }) + } + } + + /// Returns the number of blocks read thus far. + fn read_block_count(&self) -> u64 { + match self { + BlockIter::Binary { read_block_count, .. } + | BlockIter::Json { read_block_count, .. } + => *read_block_count, + } + } + + /// Returns the total number of blocks to be imported, if possible. + fn num_expected_blocks(&self) -> Option { + match self { + BlockIter::Binary { num_expected_blocks, ..} => Some(*num_expected_blocks), + BlockIter::Json {..} => None + } + } +} + +impl Iterator for BlockIter where + R: Read + Seek + 'static, + B: BlockT + MaybeSerializeDeserialize, +{ + type Item = Result, String>; + + fn next(&mut self) -> Option { + match self { + BlockIter::Binary { num_expected_blocks, read_block_count, reader } => { + if read_block_count < num_expected_blocks { + let block_result: Result, _> = SignedBlock::::decode(reader) + .map_err(|e| e.to_string()); + *read_block_count += 1; + Some(block_result) + } else { + // `read_block_count` == `num_expected_blocks` so we've read enough blocks. + None + } + } + BlockIter::Json { reader, read_block_count } => { + let res = Some(reader.next()?.map_err(|e| e.to_string())); + *read_block_count += 1; + res + } + } + } +} + +/// Imports the SignedBlock to the queue. +fn import_block_to_queue( + signed_block: SignedBlock, + queue: &mut TImpQu, + force: bool +) where + TBl: BlockT + MaybeSerializeDeserialize, + TImpQu: 'static + ImportQueue, +{ + let (header, extrinsics) = signed_block.block.deconstruct(); + let hash = header.hash(); + // import queue handles verification and importing it into the client. + queue.import_blocks(BlockOrigin::File, vec![ + IncomingBlock:: { + hash, + header: Some(header), + body: Some(extrinsics), + justification: signed_block.justification, + origin: None, + allow_missing_state: false, + import_existing: force, + } + ]); +} + +/// Returns true if we have imported every block we were supposed to import, else returns false. +fn importing_is_done( + num_expected_blocks: Option, + read_block_count: u64, + imported_blocks: u64 +) -> bool { + if let Some(num_expected_blocks) = num_expected_blocks { + imported_blocks >= num_expected_blocks + } else { + imported_blocks >= read_block_count + } +} + +/// Structure used to log the block importing speed. +struct Speedometer { + best_number: NumberFor, + last_number: Option>, + last_update: Instant, +} + +impl Speedometer { + /// Creates a fresh Speedometer. + fn new() -> Self { + Self { + best_number: NumberFor::::from(0), + last_number: None, + last_update: Instant::now(), + } + } + + /// Calculates `(best_number - last_number) / (now - last_update)` and + /// logs the speed of import. + fn display_speed(&self) { + // Number of milliseconds elapsed since last time. + let elapsed_ms = { + let elapsed = self.last_update.elapsed(); + let since_last_millis = elapsed.as_secs() * 1000; + let since_last_subsec_millis = elapsed.subsec_millis() as u64; + since_last_millis + since_last_subsec_millis + }; + + // Number of blocks that have been imported since last time. + let diff = match self.last_number { + None => return, + Some(n) => self.best_number.saturating_sub(n) + }; + + if let Ok(diff) = TryInto::::try_into(diff) { + // If the number of blocks can be converted to a regular integer, then it's easy: just + // do the math and turn it into a `f64`. + let speed = diff.saturating_mul(10_000).checked_div(u128::from(elapsed_ms)) + .map_or(0.0, |s| s as f64) / 10.0; + info!("📦 Current best block: {} ({:4.1} bps)", self.best_number, speed); + } else { + // If the number of blocks can't be converted to a regular integer, then we need a more + // algebraic approach and we stay within the realm of integers. + let one_thousand = NumberFor::::from(1_000); + let elapsed = NumberFor::::from( + >::try_from(elapsed_ms).unwrap_or(u32::max_value()) + ); + + let speed = diff.saturating_mul(one_thousand).checked_div(&elapsed) + .unwrap_or_else(Zero::zero); + info!("📦 Current best block: {} ({} bps)", self.best_number, speed) + } + } + + /// Updates the Speedometer. + fn update(&mut self, best_number: NumberFor) { + self.last_number = Some(self.best_number); + self.best_number = best_number; + self.last_update = Instant::now(); + } + + // If more than TIME_BETWEEN_UPDATES has elapsed since last update, + // then print and update the speedometer. + fn notify_user(&mut self, best_number: NumberFor) { + let delta = Duration::from_millis(TIME_BETWEEN_UPDATES); + if Instant::now().duration_since(self.last_update) >= delta { + self.display_speed(); + self.update(best_number); + } + } +} + +/// Different State that the `import_blocks` future could be in. +enum ImportState where + R: Read + Seek + 'static, + B: BlockT + MaybeSerializeDeserialize, +{ + /// We are reading from the BlockIter structure, adding those blocks to the queue if possible. + Reading{block_iter: BlockIter}, + /// The queue is full (contains at least MAX_PENDING_BLOCKS blocks) and we are waiting for it to catch up. + WaitingForImportQueueToCatchUp{ + block_iter: BlockIter, + delay: Delay, + block: SignedBlock + }, + // We have added all the blocks to the queue but they are still being processed. + WaitingForImportQueueToFinish{ + num_expected_blocks: Option, + read_block_count: u64, + delay: Delay, + }, +} + impl< TBl, TRtApi, TBackend, TExecDisp, TFchr, TSc, TImpQu, TFprb, TFpp, @@ -52,7 +294,7 @@ impl< Client>, TBl, TRtApi>, TFchr, TSc, TImpQu, TFprb, TFpp, TExPool, TRpc, Backend > where - TBl: BlockT, + TBl: BlockT + MaybeSerializeDeserialize, TBackend: 'static + sc_client_api::backend::Backend + Send, TExecDisp: 'static + NativeExecutionDispatch, TImpQu: 'static + ImportQueue, @@ -66,6 +308,7 @@ impl< mut self, input: impl Read + Seek + Send + 'static, force: bool, + binary: bool, ) -> Pin> + Send>> { struct WaitLink { imported_blocks: u64, @@ -85,7 +328,7 @@ impl< fn blocks_processed( &mut self, imported: usize, - _count: usize, + _num_expected_blocks: usize, results: Vec<(Result>, BlockImportError>, B::Hash)> ) { self.imported_blocks += imported as u64; @@ -100,10 +343,20 @@ impl< } } - let mut io_reader_input = IoReader(input); - let mut count = None::; - let mut read_block_count = 0; let mut link = WaitLink::new(); + let block_iter_res: Result, String> = BlockIter::new(input, binary); + + let block_iter = match block_iter_res { + Ok(block_iter) => block_iter, + Err(e) => { + // We've encountered an error while creating the block iterator + // so we can just return a future that returns an error. + return future::ready(Err(Error::Other(e))).boxed() + } + }; + + let mut state = Some(ImportState::Reading{block_iter}); + let mut speedometer = Speedometer::::new(); // Importing blocks is implemented as a future, because we want the operation to be // interruptible. @@ -115,85 +368,103 @@ impl< let import = future::poll_fn(move |cx| { let client = &self.client; let queue = &mut self.import_queue; - - // Start by reading the number of blocks if not done so already. - let count = match count { - Some(c) => c, - None => { - let c: u64 = match Decode::decode(&mut io_reader_input) { - Ok(c) => c, - Err(err) => { - let err = format!("Error reading file: {}", err); - return std::task::Poll::Ready(Err(From::from(err))); + match state.take().expect("state should never be None; qed") { + ImportState::Reading{mut block_iter} => { + match block_iter.next() { + None => { + // The iterator is over: we now need to wait for the import queue to finish. + let num_expected_blocks = block_iter.num_expected_blocks(); + let read_block_count = block_iter.read_block_count(); + let delay = Delay::new(Duration::from_millis(DELAY_TIME)); + state = Some(ImportState::WaitingForImportQueueToFinish{num_expected_blocks, read_block_count, delay}); }, - }; - info!("📦 Importing {} blocks", c); - count = Some(c); - c - } - }; - - // Read blocks from the input. - if read_block_count < count { - match SignedBlock::::decode(&mut io_reader_input) { - Ok(signed) => { - let (header, extrinsics) = signed.block.deconstruct(); - let hash = header.hash(); - // import queue handles verification and importing it into the client - queue.import_blocks(BlockOrigin::File, vec![ - IncomingBlock:: { - hash, - header: Some(header), - body: Some(extrinsics), - justification: signed.justification, - origin: None, - allow_missing_state: false, - import_existing: force, + Some(block_result) => { + let read_block_count = block_iter.read_block_count(); + match block_result { + Ok(block) => { + if read_block_count - link.imported_blocks >= MAX_PENDING_BLOCKS { + // The queue is full, so do not add this block and simply wait until + // the queue has made some progress. + let delay = Delay::new(Duration::from_millis(DELAY_TIME)); + state = Some(ImportState::WaitingForImportQueueToCatchUp{block_iter, delay, block}); + } else { + // Queue is not full, we can keep on adding blocks to the queue. + import_block_to_queue(block, queue, force); + state = Some(ImportState::Reading{block_iter}); + } + } + Err(e) => { + return Poll::Ready( + Err(Error::Other(format!("Error reading block #{}: {}", read_block_count, e)))) + } } - ]); + } } - Err(e) => { - warn!("Error reading block data at {}: {}", read_block_count, e); - return std::task::Poll::Ready(Ok(())); + }, + ImportState::WaitingForImportQueueToCatchUp{block_iter, mut delay, block} => { + let read_block_count = block_iter.read_block_count(); + if read_block_count - link.imported_blocks >= MAX_PENDING_BLOCKS { + // Queue is still full, so wait until there is room to insert our block. + match Pin::new(&mut delay).poll(cx) { + Poll::Pending => { + state = Some(ImportState::WaitingForImportQueueToCatchUp{block_iter, delay, block}); + return Poll::Pending + }, + Poll::Ready(_) => { + delay.reset(Duration::from_millis(DELAY_TIME)); + }, + } + state = Some(ImportState::WaitingForImportQueueToCatchUp{block_iter, delay, block}); + } else { + // Queue is no longer full, so we can add our block to the queue. + import_block_to_queue(block, queue, force); + // Switch back to Reading state. + state = Some(ImportState::Reading{block_iter}); + } + }, + ImportState::WaitingForImportQueueToFinish{num_expected_blocks, read_block_count, mut delay} => { + // All the blocks have been added to the queue, which doesn't mean they + // have all been properly imported. + if importing_is_done(num_expected_blocks, read_block_count, link.imported_blocks) { + // Importing is done, we can log the result and return. + info!( + "🎉 Imported {} blocks. Best: #{}", + read_block_count, client.chain_info().best_number + ); + return Poll::Ready(Ok(())) + } else { + // Importing is not done, we still have to wait for the queue to finish. + // Wait for the delay, because we know the queue is lagging behind. + match Pin::new(&mut delay).poll(cx) { + Poll::Pending => { + state = Some(ImportState::WaitingForImportQueueToFinish{num_expected_blocks, read_block_count, delay}); + return Poll::Pending + }, + Poll::Ready(_) => { + delay.reset(Duration::from_millis(DELAY_TIME)); + }, + } + + state = Some(ImportState::WaitingForImportQueueToFinish{num_expected_blocks, read_block_count, delay}); } } - - read_block_count += 1; - if read_block_count % 1000 == 0 { - info!("#{} blocks were added to the queue", read_block_count); - } - - cx.waker().wake_by_ref(); - return std::task::Poll::Pending; } - let blocks_before = link.imported_blocks; queue.poll_actions(cx, &mut link); - if link.has_error { - info!( - "Stopping after #{} blocks because of an error", - link.imported_blocks, - ); - return std::task::Poll::Ready(Ok(())); - } + let best_number = client.chain_info().best_number; + speedometer.notify_user(best_number); - if link.imported_blocks / 1000 != blocks_before / 1000 { - info!( - "#{} blocks were imported (#{} left)", - link.imported_blocks, - count - link.imported_blocks - ); + if link.has_error { + return Poll::Ready(Err( + Error::Other( + format!("Stopping after #{} blocks because of an error", link.imported_blocks) + ) + )) } - if link.imported_blocks >= count { - info!("🎉 Imported {} blocks. Best: #{}", read_block_count, client.chain_info().best_number); - return std::task::Poll::Ready(Ok(())); - - } else { - // Polling the import queue will re-schedule the task when ready. - return std::task::Poll::Pending; - } + cx.waker().wake_by_ref(); + Poll::Pending }); Box::pin(import) } @@ -226,7 +497,7 @@ impl< let client = &self.client; if last < block { - return std::task::Poll::Ready(Err("Invalid block range specified".into())); + return Poll::Ready(Err("Invalid block range specified".into())); } if !wrote_header { @@ -250,19 +521,19 @@ impl< } }, // Reached end of the chain. - None => return std::task::Poll::Ready(Ok(())), + None => return Poll::Ready(Ok(())), } if (block % 10000.into()).is_zero() { info!("#{}", block); } if block == last { - return std::task::Poll::Ready(Ok(())); + return Poll::Ready(Ok(())); } block += One::one(); // Re-schedule the task in order to continue the operation. cx.waker().wake_by_ref(); - std::task::Poll::Pending + Poll::Pending }); Box::pin(export) @@ -293,7 +564,7 @@ impl< 1u64.encode_to(&mut buf); block.encode_to(&mut buf); let reader = std::io::Cursor::new(buf); - self.import_blocks(reader, true) + self.import_blocks(reader, true, true) } Ok(None) => Box::pin(future::err("Unknown block".into())), Err(e) => Box::pin(future::err(format!("Error reading block: {:?}", e).into())), diff --git a/client/service/src/client/block_rules.rs b/client/service/src/client/block_rules.rs index e5614511817d35b5f2dbe4ebfb9501c5410553ec..247d09197b604c7335c5141f6409b9b727c67b97 100644 --- a/client/service/src/client/block_rules.rs +++ b/client/service/src/client/block_rules.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Client fixed chain specification rules diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index 229e7478e939f818977c268e2b57e9fae9422a5f..049bd888b13c78ca4f67eaadfa7dfa551b01c313 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{sync::Arc, panic::UnwindSafe, result, cell::RefCell}; use codec::{Encode, Decode}; diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index bc992291bdbf2bdba57cacb746d26860854c0324..77b3f065f43dd87fc37cc8d6e20723540a1f1cc5 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate Client @@ -87,6 +89,7 @@ use super::{ block_rules::{BlockRules, LookupResult as BlockLookupResult}, }; use futures::channel::mpsc; +use rand::Rng; #[cfg(feature="test-helpers")] use { @@ -661,8 +664,6 @@ impl Client where if let Ok(ImportResult::Imported(ref aux)) = result { if aux.is_new_best { - use rand::Rng; - // don't send telemetry block import events during initial sync for every // block to avoid spamming the telemetry server, these events will be randomly // sent at a rate of 1/10. @@ -954,7 +955,7 @@ impl Client where // we'll send notifications spuriously in that case. const MAX_TO_NOTIFY: usize = 256; let enacted = route_from_finalized.enacted(); - let start = enacted.len() - ::std::cmp::min(enacted.len(), MAX_TO_NOTIFY); + let start = enacted.len() - std::cmp::min(enacted.len(), MAX_TO_NOTIFY); for finalized in &enacted[start..] { operation.notify_finalized.push(finalized.hash); } @@ -978,14 +979,27 @@ impl Client where return Ok(()); } - for finalized_hash in notify_finalized { - let header = self.header(&BlockId::Hash(finalized_hash))? - .expect("header already known to exist in DB because it is indicated in the tree route; qed"); + // We assume the list is sorted and only want to inform the + // telemetry once about the finalized block. + if let Some(last) = notify_finalized.last() { + let header = self.header(&BlockId::Hash(*last))? + .expect( + "Header already known to exist in DB because it is \ + indicated in the tree route; qed" + ); telemetry!(SUBSTRATE_INFO; "notify.finalized"; "height" => format!("{}", header.number()), - "best" => ?finalized_hash, + "best" => ?last, ); + } + + for finalized_hash in notify_finalized { + let header = self.header(&BlockId::Hash(finalized_hash))? + .expect( + "Header already known to exist in DB because it is \ + indicated in the tree route; qed" + ); let notification = FinalityNotification { header, diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs index 41dbccc517390ff0a3884a59b35989327e546e06..4df08025e38264ab0a5f5b09631c95e4681d1b10 100644 --- a/client/service/src/client/genesis.rs +++ b/client/service/src/client/genesis.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Tool for creating the genesis block. diff --git a/client/service/src/client/light/backend.rs b/client/service/src/client/light/backend.rs index 78f3938aaa8285bc2dfb32829342794f133e567c..2cf994d3f5993c3f2f0681c0db8cee026234bdf3 100644 --- a/client/service/src/client/light/backend.rs +++ b/client/service/src/client/light/backend.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Light client backend. Only stores headers and justifications of blocks. //! Everything else is requested from full nodes on demand. @@ -316,12 +318,12 @@ impl BlockImportOperation for ImportOperation storage.insert(None, input.top); // create a list of children keys to re-compute roots for - let child_delta = input.children_default.iter() - .map(|(_storage_key, storage_child)| (storage_child.child_info.clone(), None)) - .collect::>(); + let child_delta = input.children_default + .iter() + .map(|(_storage_key, storage_child)| (&storage_child.child_info, std::iter::empty())); // make sure to persist the child storage - for (_child_key, storage_child) in input.children_default { + for (_child_key, storage_child) in input.children_default.clone() { storage.insert(Some(storage_child.child_info), storage_child.data); } @@ -348,7 +350,11 @@ impl BlockImportOperation for ImportOperation Ok(()) } - fn mark_finalized(&mut self, block: BlockId, _justification: Option) -> ClientResult<()> { + fn mark_finalized( + &mut self, + block: BlockId, + _justification: Option, + ) -> ClientResult<()> { self.finalized_blocks.push(block); Ok(()) } @@ -457,10 +463,10 @@ impl StateBackend for GenesisOrUnavailableState } } - fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) - where - I: IntoIterator, Option>)> - { + fn storage_root<'a>( + &self, + delta: impl Iterator)>, + ) -> (H::Out, Self::Transaction) where H::Out: Ord { match *self { GenesisOrUnavailableState::Genesis(ref state) => state.storage_root(delta), @@ -468,14 +474,11 @@ impl StateBackend for GenesisOrUnavailableState } } - fn child_storage_root( + fn child_storage_root<'a>( &self, child_info: &ChildInfo, - delta: I, - ) -> (H::Out, bool, Self::Transaction) - where - I: IntoIterator, Option>)> - { + delta: impl Iterator)>, + ) -> (H::Out, bool, Self::Transaction) where H::Out: Ord { match *self { GenesisOrUnavailableState::Genesis(ref state) => { let (root, is_equal, _) = state.child_storage_root(child_info, delta); diff --git a/client/service/src/client/light/blockchain.rs b/client/service/src/client/light/blockchain.rs index b6ccb4744b55907bff952cf6eba0753d72144394..c7b20de594d6787f12a498ea76d35f24eba9c524 100644 --- a/client/service/src/client/light/blockchain.rs +++ b/client/service/src/client/light/blockchain.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Light client blockchain backend. Only stores headers and justifications of recent //! blocks. CHT roots are stored for headers of ancient blocks. diff --git a/client/service/src/client/light/call_executor.rs b/client/service/src/client/light/call_executor.rs index 54fcf8e8f7f4c3d6b0e33c32e03d49a5f511eb79..81be65339b696cbf3f4b39cf33425a53a8a78bf9 100644 --- a/client/service/src/client/light/call_executor.rs +++ b/client/service/src/client/light/call_executor.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Methods that light client could use to execute runtime calls. diff --git a/client/service/src/client/light/fetcher.rs b/client/service/src/client/light/fetcher.rs index ae64565a504d1e3e90d2a3f4892ca69ac0b11069..542255496739a99a3b4e04bea5e02e76741c7b98 100644 --- a/client/service/src/client/light/fetcher.rs +++ b/client/service/src/client/light/fetcher.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Light client data fetcher. Fetches requested data from remote full nodes. diff --git a/client/service/src/client/light/mod.rs b/client/service/src/client/light/mod.rs index 9b3c3f5b29042a16ce402505a80a989f44269382..a3456f96a37869eca5fea94613bb61d578ff4731 100644 --- a/client/service/src/client/light/mod.rs +++ b/client/service/src/client/light/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Light client components. diff --git a/client/service/src/client/mod.rs b/client/service/src/client/mod.rs index fe3ad992b6690dcf0e9aae19bb3e855d4078581a..7c96f61a7867a6f68aab035e69494db8e53d748a 100644 --- a/client/service/src/client/mod.rs +++ b/client/service/src/client/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate Client and associated logic. //! diff --git a/client/service/src/config.rs b/client/service/src/config.rs index e0de85b56d598667b2774788825e6e4da847cb47..cc9c742ed68db22da0468251e707cbfb0dd2d086 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Service configuration. diff --git a/client/service/src/error.rs b/client/service/src/error.rs index 5a78a1878923080ee05d2c5c46568356b8a71a59..ffe1b39405501d224b7c56f40facb11776775f10 100644 --- a/client/service/src/error.rs +++ b/client/service/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Errors that can occur during the service operation. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 1c0f8ced74244cbc90d154045043b6a9e9d1790c..4f2be23f877ba1cd2401f197a94d3e1d625c0949 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. //! Manages communication between them. @@ -50,7 +52,7 @@ use futures::{ sink::SinkExt, task::{Spawn, FutureObj, SpawnError}, }; -use sc_network::{NetworkService, network_state::NetworkState, PeerId, ReportHandle}; +use sc_network::{NetworkService, network_state::NetworkState, PeerId}; use log::{log, warn, debug, error, Level}; use codec::{Encode, Decode}; use sp_runtime::generic::BlockId; @@ -62,7 +64,7 @@ pub use self::error::Error; pub use self::builder::{ new_full_client, new_client, ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend, - TFullCallExecutor, TLightCallExecutor, + TFullCallExecutor, TLightCallExecutor, RpcExtensionBuilder, }; pub use config::{Configuration, DatabaseConfig, PruningMode, Role, RpcMethods, TaskType}; pub use sc_chain_spec::{ @@ -76,7 +78,10 @@ pub use sc_executor::NativeExecutionDispatch; #[doc(hidden)] pub use std::{ops::Deref, result::Result, sync::Arc}; #[doc(hidden)] -pub use sc_network::config::{FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder}; +pub use sc_network::config::{ + FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder, TransactionImport, + TransactionImportFuture, +}; pub use sc_tracing::TracingReceiver; pub use task_manager::SpawnTaskHandle; use task_manager::TaskManager; @@ -365,8 +370,6 @@ fn build_network_future< // We poll `imported_blocks_stream`. while let Poll::Ready(Some(notification)) = Pin::new(&mut imported_blocks_stream).poll_next(cx) { - network.on_block_imported(notification.header, notification.is_new_best); - if announce_imported_blocks { network.service().announce_block(notification.hash, Vec::new()); } @@ -551,8 +554,8 @@ fn start_rpc_servers sc_rpc_server::RpcHandler, methods: &RpcMethods) -> sc_rpc::DenyUnsafe { - let is_exposed_addr = addr.map(|x| x.ip().is_loopback()).unwrap_or(false); + fn deny_unsafe(addr: &SocketAddr, methods: &RpcMethods) -> sc_rpc::DenyUnsafe { + let is_exposed_addr = !addr.ip().is_loopback(); match (is_exposed_addr, methods) { | (_, RpcMethods::Unsafe) | (false, RpcMethods::Auto) => sc_rpc::DenyUnsafe::No, @@ -566,7 +569,7 @@ fn start_rpc_servers sc_rpc_server::RpcHandler sc_rpc_server::RpcHandler { imports_external_transactions: bool, pool: Arc

, client: Arc, - executor: SpawnTaskHandle, } /// Get transactions for propagation. @@ -659,42 +661,42 @@ where fn import( &self, - report_handle: ReportHandle, - who: PeerId, - reputation_change_good: sc_network::ReputationChange, - reputation_change_bad: sc_network::ReputationChange, - transaction: B::Extrinsic - ) { + transaction: B::Extrinsic, + ) -> TransactionImportFuture { if !self.imports_external_transactions { debug!("Transaction rejected"); - return; + Box::pin(futures::future::ready(TransactionImport::None)); } let encoded = transaction.encode(); - match Decode::decode(&mut &encoded[..]) { - Ok(uxt) => { - let best_block_id = BlockId::hash(self.client.info().best_hash); - let source = sp_transaction_pool::TransactionSource::External; - let import_future = self.pool.submit_one(&best_block_id, source, uxt); - let import_future = import_future - .map(move |import_result| { - match import_result { - Ok(_) => report_handle.report_peer(who, reputation_change_good), - Err(e) => match e.into_pool_error() { - Ok(sp_transaction_pool::error::Error::AlreadyImported(_)) => (), - Ok(e) => { - report_handle.report_peer(who, reputation_change_bad); - debug!("Error adding transaction to the pool: {:?}", e) - } - Err(e) => debug!("Error converting pool error: {:?}", e), - } - } - }); - - self.executor.spawn("extrinsic-import", import_future); + let uxt = match Decode::decode(&mut &encoded[..]) { + Ok(uxt) => uxt, + Err(e) => { + debug!("Transaction invalid: {:?}", e); + return Box::pin(futures::future::ready(TransactionImport::Bad)); } - Err(e) => debug!("Error decoding transaction {}", e), - } + }; + + let best_block_id = BlockId::hash(self.client.info().best_hash); + + let import_future = self.pool.submit_one(&best_block_id, sp_transaction_pool::TransactionSource::External, uxt); + Box::pin(async move { + match import_future.await { + Ok(_) => TransactionImport::NewGood, + Err(e) => match e.into_pool_error() { + Ok(sp_transaction_pool::error::Error::AlreadyImported(_)) => TransactionImport::KnownGood, + Ok(e) => { + debug!("Error adding transaction to the pool: {:?}", e); + TransactionImport::Bad + } + Err(e) => { + debug!("Error converting pool error: {:?}", e); + // it is not bad at least, just some internal node logic error, so peer is innocent. + TransactionImport::KnownGood + } + } + } + }) } fn on_broadcasted(&self, propagations: HashMap>) { diff --git a/client/service/src/metrics.rs b/client/service/src/metrics.rs index 6456f9b1ee0be5df1b113574647d629f77bb6af3..f3463ffdbe61685e7a43757079e3ec768bdff04a 100644 --- a/client/service/src/metrics.rs +++ b/client/service/src/metrics.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::convert::TryFrom; diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 094f6bcff0411c3659d7e10c78de9fd7fe521bff..4b55b19269358bc6d7c2eb98770cc7181aade745 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-service-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -20,24 +20,24 @@ log = "0.4.8" env_logger = "0.7.0" fdlimit = "0.1.4" parking_lot = "0.10.0" -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -sp-state-machine = { version = "0.8.0-dev", path = "../../../primitives/state-machine" } -sp-externalities = { version = "0.8.0-dev", path = "../../../primitives/externalities" } -sp-trie = { version = "2.0.0-dev", path = "../../../primitives/trie" } -sp-storage = { version = "2.0.0-dev", path = "../../../primitives/storage" } -sc-client-db = { version = "0.8.0-dev", default-features = false, path = "../../db" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../../primitives/state-machine" } +sp-externalities = { version = "0.8.0-rc2", path = "../../../primitives/externalities" } +sp-trie = { version = "2.0.0-rc2", path = "../../../primitives/trie" } +sp-storage = { version = "2.0.0-rc2", path = "../../../primitives/storage" } +sc-client-db = { version = "0.8.0-rc2", default-features = false, path = "../../db" } futures = { version = "0.3.1", features = ["compat"] } -sc-service = { version = "0.8.0-dev", default-features = false, features = ["test-helpers"], path = "../../service" } -sc-network = { version = "0.8.0-dev", path = "../../network" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../../primitives/transaction-pool" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../../test-utils/runtime" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sc-client-api = { version = "2.0.0-dev", path = "../../api" } -sc-block-builder = { version = "0.8.0-dev", path = "../../block-builder" } -sc-executor = { version = "0.8.0-dev", path = "../../executor" } -sp-panic-handler = { version = "2.0.0-dev", path = "../../../primitives/panic-handler" } +sc-service = { version = "0.8.0-rc2", default-features = false, features = ["test-helpers"], path = "../../service" } +sc-network = { version = "0.8.0-rc2", path = "../../network" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../../primitives/transaction-pool" } +substrate-test-runtime = { version = "2.0.0-rc2", path = "../../../test-utils/runtime" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../test-utils/runtime/client" } +sc-client-api = { version = "2.0.0-rc2", path = "../../api" } +sc-block-builder = { version = "0.8.0-rc2", path = "../../block-builder" } +sc-executor = { version = "0.8.0-rc2", path = "../../executor" } +sp-panic-handler = { version = "2.0.0-rc2", path = "../../../primitives/panic-handler" } parity-scale-codec = "1.3.0" diff --git a/client/service/test/src/client/db.rs b/client/service/test/src/client/db.rs index bc175652c9f79f36fd3b67c18b96beb68781dedb..36d49732246e579d610a707d827c0b5d49c00ea6 100644 --- a/client/service/test/src/client/db.rs +++ b/client/service/test/src/client/db.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use sp_core::offchain::{OffchainStorage, storage::InMemOffchainStorage}; use std::sync::Arc; @@ -52,4 +54,4 @@ fn in_memory_offchain_storage() { assert!(!storage.compare_and_set(b"B", b"A", Some(b""), b"Y")); assert!(storage.compare_and_set(b"B", b"A", None, b"X")); assert_eq!(storage.get(b"B", b"A"), Some(b"X".to_vec())); -} \ No newline at end of file +} diff --git a/client/service/test/src/client/light.rs b/client/service/test/src/client/light.rs index 76e48828ee429c1128b6d7b448d1d3d95fd8c817..ec319e4832fdb3ee4e71c8f05d44ac3bf2ea2835 100644 --- a/client/service/test/src/client/light.rs +++ b/client/service/test/src/client/light.rs @@ -1,18 +1,21 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . + use sc_service::client::light::{ call_executor::{ GenesisCallExecutor, diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index e81d1ebb5364bc404cec0bb80539a0c385b77ee7..2124f0ced412294b134a153642dd8e2bec581133 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use parity_scale_codec::{Encode, Decode, Joiner}; use sc_executor::native_executor_instance; diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index fd6774136597c0044a4814aa94c1dbaafe9c0281..63c7e0795dc1ac2f9ce53de80e25fd0ae16a1904 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Service integration test utils. diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml index c2d2f2eb0badf5a60a8db5c5af44790eb6e125a8..e1b784c222a86a4f26b1cad20b33250f44ef4e6a 100644 --- a/client/state-db/Cargo.toml +++ b/client/state-db/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-state-db" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "State database maintenance. Handles canonicalization and pruning in the database." @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] parking_lot = "0.10.0" log = "0.4.8" -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] } parity-util-mem-derive = "0.1.0" diff --git a/client/state-db/src/lib.rs b/client/state-db/src/lib.rs index 94d51c89126485167228606da10db2aff4df1cc3..61470894e487e3884bc873301ff17e39345a0877 100644 --- a/client/state-db/src/lib.rs +++ b/client/state-db/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! State database maintenance. Handles canonicalization and pruning in the database. The input to //! this module is a `ChangeSet` which is basically a list of key-value pairs (trie nodes) that diff --git a/client/state-db/src/noncanonical.rs b/client/state-db/src/noncanonical.rs index 6a743e7d45913bc684961a300494b5e4154339f6..d77f20c50d05f30916f024666607dc7f3f16d440 100644 --- a/client/state-db/src/noncanonical.rs +++ b/client/state-db/src/noncanonical.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Canonicalization window. //! Maintains trees of block overlays and allows discarding trees/roots diff --git a/client/state-db/src/pruning.rs b/client/state-db/src/pruning.rs index 6921beea916564a779ab7543c2d9e10d9c67b5da..69b07c285fad8318152611d9473c508367a9f73c 100644 --- a/client/state-db/src/pruning.rs +++ b/client/state-db/src/pruning.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Pruning window. //! diff --git a/client/state-db/src/test.rs b/client/state-db/src/test.rs index accafa9bf831fb323b7f0247080f85d08d1c3f4d..11ce4ad8226202d0f08a9e77bdddfb8e7772deaa 100644 --- a/client/state-db/src/test.rs +++ b/client/state-db/src/test.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Test utils diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml index 0928d1d2a151822643e58781b8da23178acc6f9c..e88a9dc779a4a23817394a70d3633bb3e8e1481a 100644 --- a/client/telemetry/Cargo.toml +++ b/client/telemetry/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sc-telemetry" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] description = "Telemetry utils" edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sc-telemetry" @@ -19,7 +19,7 @@ parking_lot = "0.10.0" futures = "0.3.4" futures-timer = "3.0.1" wasm-timer = "0.2.0" -libp2p = { version = "0.18.1", default-features = false, features = ["websocket", "wasm-ext", "tcp", "dns"] } +libp2p = { version = "0.19.1", default-features = false, features = ["websocket", "wasm-ext", "tcp-async-std", "dns"] } log = "0.4.8" pin-project = "0.4.6" rand = "0.7.2" diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs index 6c90d6bbcca9f3a60fc765e056abd908c0ea0636..315bedbe5b6d92d4a96fa5085658d95c1c99a29b 100644 --- a/client/telemetry/src/lib.rs +++ b/client/telemetry/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Telemetry utilities. //! diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs index 8f43bb612a10503d0d8968821bc90f1469140f85..68d4c4e20971bf31af0943e43e2effdd5037f062 100644 --- a/client/telemetry/src/worker.rs +++ b/client/telemetry/src/worker.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Contains the object that makes the telemetry work. //! diff --git a/client/telemetry/src/worker/node.rs b/client/telemetry/src/worker/node.rs index 454f504d660050995cba1f6c122c311ba35741ee..6b1a0f62b129b365888f2a2f3d30dfe58a7634d9 100644 --- a/client/telemetry/src/worker/node.rs +++ b/client/telemetry/src/worker/node.rs @@ -1,18 +1,20 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Contains the `Node` struct, which handles communications with a single telemetry endpoint. diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml index 23f44fd057570e4aae988a2d316e51aea01e3150..dfcedddbd185ca90e21e4e921b1b14f1b3ecb6b2 100644 --- a/client/tracing/Cargo.toml +++ b/client/tracing/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sc-tracing" -version = "2.0.0-dev" -license = "GPL-3.0" +version = "2.0.0-rc2" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" @@ -20,7 +20,7 @@ serde_json = "1.0.41" slog = { version = "2.5.2", features = ["nested-values"] } tracing-core = "0.1.7" -sc-telemetry = { version = "2.0.0-dev", path = "../telemetry" } +sc-telemetry = { version = "2.0.0-rc2", path = "../telemetry" } [dev-dependencies] tracing = "0.1.10" diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 6d4f69676c6308858ff30006d6136ab04abe16b5..0b394da3576759dcce0af2a988a9b7aa6fbfc3c8 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-transaction-pool" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate transaction pool implementation." @@ -20,21 +20,21 @@ intervalier = "0.4.0" log = "0.4.8" parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] } parking_lot = "0.10.0" -prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-dev"} -sc-client-api = { version = "2.0.0-dev", path = "../api" } -sc-transaction-graph = { version = "2.0.0-dev", path = "./graph" } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } -sp-tracing = { version = "2.0.0-dev", path = "../../primitives/tracing" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../primitives/transaction-pool" } -sp-blockchain = { version = "2.0.0-dev", path = "../../primitives/blockchain" } -sp-utils = { version = "2.0.0-dev", path = "../../primitives/utils" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-rc2"} +sc-client-api = { version = "2.0.0-rc2", path = "../api" } +sc-transaction-graph = { version = "2.0.0-rc2", path = "./graph" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } +sp-tracing = { version = "2.0.0-rc2", path = "../../primitives/tracing" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../primitives/transaction-pool" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../primitives/blockchain" } +sp-utils = { version = "2.0.0-rc2", path = "../../primitives/utils" } wasm-timer = "0.2" [dev-dependencies] assert_matches = "1.3.0" hex = "0.4" -sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" } -substrate-test-runtime-transaction-pool = { version = "2.0.0-dev", path = "../../test-utils/runtime/transaction-pool" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sp-keyring = { version = "2.0.0-rc2", path = "../../primitives/keyring" } +substrate-test-runtime-transaction-pool = { version = "2.0.0-rc2", path = "../../test-utils/runtime/transaction-pool" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } diff --git a/client/transaction-pool/graph/Cargo.toml b/client/transaction-pool/graph/Cargo.toml index 842d54f920a71acc70ef31ce2fa2d474099808a7..2290a29c8f6977f7caeb253c8be46b15fd519040 100644 --- a/client/transaction-pool/graph/Cargo.toml +++ b/client/transaction-pool/graph/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sc-transaction-graph" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Generic Transaction Pool" @@ -18,18 +18,18 @@ log = "0.4.8" parking_lot = "0.10.0" serde = { version = "1.0.101", features = ["derive"] } wasm-timer = "0.2" -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-utils = { version = "2.0.0-dev", path = "../../../primitives/utils" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-transaction-pool = { version = "2.0.0-dev", path = "../../../primitives/transaction-pool" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-utils = { version = "2.0.0-rc2", path = "../../../primitives/utils" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-transaction-pool = { version = "2.0.0-rc2", path = "../../../primitives/transaction-pool" } parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] } linked-hash-map = "0.5.2" [dev-dependencies] assert_matches = "1.3.0" codec = { package = "parity-scale-codec", version = "1.3.0" } -substrate-test-runtime = { version = "2.0.0-dev", path = "../../../test-utils/runtime" } +substrate-test-runtime = { version = "2.0.0-rc2", path = "../../../test-utils/runtime" } criterion = "0.3" [[bench]] diff --git a/client/transaction-pool/graph/benches/basics.rs b/client/transaction-pool/graph/benches/basics.rs index 23b4dba3488061429a39c04bcd717b55ee007c78..ee92b60d548e6b6aedd3a475206330e83f56cbf4 100644 --- a/client/transaction-pool/graph/benches/basics.rs +++ b/client/transaction-pool/graph/benches/basics.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use criterion::{criterion_group, criterion_main, Criterion}; diff --git a/client/transaction-pool/graph/src/base_pool.rs b/client/transaction-pool/graph/src/base_pool.rs index 38151e9bfd23b87b3fd4511022eaa7f9953ab46a..0128e94675e23ff8329988f768e9d87defc2bfdf 100644 --- a/client/transaction-pool/graph/src/base_pool.rs +++ b/client/transaction-pool/graph/src/base_pool.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! A basic version of the dependency graph. //! diff --git a/client/transaction-pool/graph/src/error.rs b/client/transaction-pool/graph/src/error.rs index 6fd7748e369aba3508251c04f976a49a0214b312..392ddaa39be6f2d809792985b283cf5630d09792 100644 --- a/client/transaction-pool/graph/src/error.rs +++ b/client/transaction-pool/graph/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Transaction pool errors. diff --git a/client/transaction-pool/graph/src/future.rs b/client/transaction-pool/graph/src/future.rs index 76181c837f988586d72ebd3568b4c31a35ac6b8d..80e6825d4ff9d3097f485d8fe86ca388ef0a3197 100644 --- a/client/transaction-pool/graph/src/future.rs +++ b/client/transaction-pool/graph/src/future.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{ collections::{HashMap, HashSet}, diff --git a/client/transaction-pool/graph/src/lib.rs b/client/transaction-pool/graph/src/lib.rs index ed10ef38d2bfd868eda7504b74bbe3018dee0c6f..04e5d0d3fbe9ffc4dda84c150d31e594e342ef19 100644 --- a/client/transaction-pool/graph/src/lib.rs +++ b/client/transaction-pool/graph/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Generic Transaction Pool //! diff --git a/client/transaction-pool/graph/src/listener.rs b/client/transaction-pool/graph/src/listener.rs index 92ba71007e209f6ef06d249864b25cdda191776b..2923f2b34a8d0c8e4ac1883a1b756e8e0fcad33d 100644 --- a/client/transaction-pool/graph/src/listener.rs +++ b/client/transaction-pool/graph/src/listener.rs @@ -1,22 +1,24 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{ - collections::HashMap, hash, + collections::HashMap, hash, fmt::Debug, }; use linked_hash_map::LinkedHashMap; use serde::Serialize; @@ -25,7 +27,7 @@ use log::{debug, trace, warn}; use sp_runtime::traits; /// Extrinsic pool default listener. -pub struct Listener { +pub struct Listener { watchers: HashMap>>, finality_watchers: LinkedHashMap, Vec>, } @@ -33,7 +35,7 @@ pub struct Listener { /// Maximum number of blocks awaiting finality at any time. const MAX_FINALITY_WATCHERS: usize = 512; -impl Default for Listener { +impl Default for Listener { fn default() -> Self { Listener { watchers: Default::default(), @@ -72,7 +74,7 @@ impl Listener { /// New transaction was added to the ready pool or promoted from the future pool. pub fn ready(&mut self, tx: &H, old: Option<&H>) { - trace!(target: "txpool", "[{:?}] Ready (replaced: {:?})", tx, old); + trace!(target: "txpool", "[{:?}] Ready (replaced with {:?})", tx, old); self.fire(tx, |watcher| watcher.ready()); if let Some(old) = old { self.fire(old, |watcher| watcher.usurped(tx.clone())); @@ -87,7 +89,7 @@ impl Listener { /// Transaction was dropped from the pool because of the limit. pub fn dropped(&mut self, tx: &H, by: Option<&H>) { - trace!(target: "txpool", "[{:?}] Dropped (replaced by {:?})", tx, by); + trace!(target: "txpool", "[{:?}] Dropped (replaced with {:?})", tx, by); self.fire(tx, |watcher| match by { Some(t) => watcher.usurped(t.clone()), None => watcher.dropped(), @@ -97,9 +99,9 @@ impl Listener { /// Transaction was removed as invalid. pub fn invalid(&mut self, tx: &H, warn: bool) { if warn { - warn!(target: "txpool", "Extrinsic invalid: {:?}", tx); + warn!(target: "txpool", "[{:?}] Extrinsic invalid", tx); } else { - debug!(target: "txpool", "Extrinsic invalid: {:?}", tx); + debug!(target: "txpool", "[{:?}] Extrinsic invalid", tx); } self.fire(tx, |watcher| watcher.invalid()); } @@ -129,10 +131,12 @@ impl Listener { } /// Notify all watchers that transactions have been finalized - pub fn finalized(&mut self, block_hash: BlockHash, txs: Vec) { - self.finality_watchers.remove(&block_hash); - for h in txs { - self.fire(&h, |s| s.finalized(block_hash.clone())) + pub fn finalized(&mut self, block_hash: BlockHash) { + if let Some(hashes) = self.finality_watchers.remove(&block_hash) { + for hash in hashes { + log::debug!(target: "txpool", "[{:?}] Sent finalization event (block {:?})", hash, block_hash); + self.fire(&hash, |s| s.finalized(block_hash)) + } } } } diff --git a/client/transaction-pool/graph/src/pool.rs b/client/transaction-pool/graph/src/pool.rs index 0b817b155d8ecaef12aee3461e0e475d20b15a86..4f41e9110915ef9bf8abe27ffc0cabf78f5c295c 100644 --- a/client/transaction-pool/graph/src/pool.rs +++ b/client/transaction-pool/graph/src/pool.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{ hash, diff --git a/client/transaction-pool/graph/src/ready.rs b/client/transaction-pool/graph/src/ready.rs index c856535a6165140844a339d0539aa291236a561f..b5807ffce448052660f83873082551139a53608e 100644 --- a/client/transaction-pool/graph/src/ready.rs +++ b/client/transaction-pool/graph/src/ready.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{ collections::{HashMap, HashSet, BTreeSet}, diff --git a/client/transaction-pool/graph/src/rotator.rs b/client/transaction-pool/graph/src/rotator.rs index be96174d1d91696832201bae8d9c6db4d1d0769f..65e21d0d4b5068262a6caf00add896ab51f4a710 100644 --- a/client/transaction-pool/graph/src/rotator.rs +++ b/client/transaction-pool/graph/src/rotator.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Rotate extrinsic inside the pool. //! diff --git a/client/transaction-pool/graph/src/validated_pool.rs b/client/transaction-pool/graph/src/validated_pool.rs index 2ff2acfe24fc8db886c2639fd8a9d2c346642532..9ab45e3b263c09cefa60b53a7670943812807545 100644 --- a/client/transaction-pool/graph/src/validated_pool.rs +++ b/client/transaction-pool/graph/src/validated_pool.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use std::{ collections::{HashSet, HashMap}, @@ -25,7 +27,6 @@ use crate::listener::Listener; use crate::rotator::PoolRotator; use crate::watcher::Watcher; use serde::Serialize; -use log::{debug, warn}; use parking_lot::{Mutex, RwLock}; use sp_runtime::{ @@ -187,11 +188,11 @@ impl ValidatedPool { let ready_limit = &self.options.ready; let future_limit = &self.options.future; - debug!(target: "txpool", "Pool Status: {:?}", status); + log::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) { - debug!( + log::debug!( target: "txpool", "Enforcing limits ({}/{}kB ready, {}/{}kB future", ready_limit.count, ready_limit.total_bytes / 1024, @@ -207,8 +208,11 @@ impl ValidatedPool { self.rotator.ban(&Instant::now(), removed.iter().map(|x| x.clone())); removed }; + if !removed.is_empty() { + log::debug!(target: "txpool", "Enforcing limits: {} dropped", removed.len()); + } + // run notifications - debug!(target: "txpool", "Enforcing limits: {} dropped", removed.len()); let mut listener = self.listener.write(); for h in &removed { listener.dropped(h, None); @@ -322,7 +326,7 @@ impl ValidatedPool { // we do not want to fail if single transaction import has failed // nor we do want to propagate this error, because it could tx unknown to caller // => let's just notify listeners (and issue debug message) - warn!( + log::warn!( target: "txpool", "[{:?}] Removing invalid transaction from update: {}", hash, @@ -529,14 +533,14 @@ impl ValidatedPool { return vec![]; } - debug!(target: "txpool", "Removing invalid transactions: {:?}", hashes); + log::debug!(target: "txpool", "Removing invalid transactions: {:?}", hashes); // temporarily ban invalid transactions self.rotator.ban(&Instant::now(), hashes.iter().cloned()); let invalid = self.pool.write().remove_subtree(hashes); - debug!(target: "txpool", "Removed invalid transactions: {:?}", invalid); + log::debug!(target: "txpool", "Removed invalid transactions: {:?}", invalid); let mut listener = self.listener.write(); for tx in &invalid { @@ -558,16 +562,8 @@ impl ValidatedPool { /// Notify all watchers that transactions in the block with hash have been finalized pub async fn on_block_finalized(&self, block_hash: BlockHash) -> Result<(), B::Error> { - debug!(target: "txpool", "Attempting to notify watchers of finalization for {}", block_hash); - // fetch all extrinsic hashes - if let Some(txs) = self.api.block_body(&BlockId::Hash(block_hash.clone())).await? { - let tx_hashes = txs.into_iter() - .map(|tx| self.api.hash_and_length(&tx).0) - .collect::>(); - // notify the watcher that these extrinsics have been finalized - self.listener.write().finalized(block_hash, tx_hashes); - } - + log::trace!(target: "txpool", "Attempting to notify watchers of finalization for {}", block_hash); + self.listener.write().finalized(block_hash); Ok(()) } diff --git a/client/transaction-pool/graph/src/watcher.rs b/client/transaction-pool/graph/src/watcher.rs index d54cc2718b7cbf40f33633df249d7a8d36da826a..9d9a91bb23f69acb0ad42a1eba4dcadecc856c66 100644 --- a/client/transaction-pool/graph/src/watcher.rs +++ b/client/transaction-pool/graph/src/watcher.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Extrinsics status updates. diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index bd7e11a3a69520d03b027309532e48697f0d5db2..725fb6ec4a8bf615f079eedfc59728b5926c3e45 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Chain api required for the transaction pool. diff --git a/client/transaction-pool/src/error.rs b/client/transaction-pool/src/error.rs index fa48b387c41d88ebfeab55278d777ff31b0dc1f0..c0f795df1801a0c59313aac28346bb6797ff04b7 100644 --- a/client/transaction-pool/src/error.rs +++ b/client/transaction-pool/src/error.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Transaction pool error. diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index e095191c574fad94fb8f3bec7d2ce8c5e5f55a03..05d7189a04a0d0b9f40c93f47fb7d090c0872133 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Substrate transaction pool implementation. @@ -296,7 +298,9 @@ impl TransactionPool for BasicPool } fn remove_invalid(&self, hashes: &[TxHash]) -> Vec> { - self.pool.validated_pool().remove_invalid(hashes) + let removed = self.pool.validated_pool().remove_invalid(hashes); + self.metrics.report(|metrics| metrics.validations_invalid.inc_by(removed.len() as u64)); + removed } fn status(&self) -> PoolStatus { diff --git a/client/transaction-pool/src/metrics.rs b/client/transaction-pool/src/metrics.rs index 78e49b3ca53af732d28bd48ea65dc65b74835264..e377b2fe8294c706ae82b27a0ce6958428006c5e 100644 --- a/client/transaction-pool/src/metrics.rs +++ b/client/transaction-pool/src/metrics.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Transaction pool Prometheus metrics. @@ -45,6 +47,7 @@ impl MetricsLink { pub struct Metrics { pub validations_scheduled: Counter, pub validations_finished: Counter, + pub validations_invalid: Counter, } impl Metrics { @@ -64,6 +67,13 @@ impl Metrics { )?, registry, )?, + validations_invalid: register( + Counter::new( + "sub_txpool_validations_invalid", + "Total number of transactions that were removed from the pool as invalid", + )?, + registry, + )?, }) } } diff --git a/client/transaction-pool/src/revalidation.rs b/client/transaction-pool/src/revalidation.rs index f203bf08a0cf0321d084de6ff7efaf96905f466b..423ff92ba4db0389116cfa6b631e9fc8582d5ef8 100644 --- a/client/transaction-pool/src/revalidation.rs +++ b/client/transaction-pool/src/revalidation.rs @@ -1,18 +1,20 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Pool periodic revalidation. @@ -176,7 +178,7 @@ impl RevalidationWorker { for ext_hash in transactions { // we don't add something that already scheduled for revalidation if self.members.contains_key(&ext_hash) { - log::debug!( + log::trace!( target: "txpool", "[{:?}] Skipped adding for revalidation: Already there.", ext_hash, @@ -243,6 +245,16 @@ impl RevalidationWorker { Some(worker_payload) => { this.best_block = worker_payload.at; this.push(worker_payload); + + if this.members.len() > 0 { + log::debug!( + target: "txpool", + "Updated revalidation queue at {}. Transactions: {:?}", + this.best_block, + this.members, + ); + } + continue; }, // R.I.P. worker! @@ -324,7 +336,7 @@ where /// revalidation is actually done. pub async fn revalidate_later(&self, at: NumberFor, transactions: Vec>) { if transactions.len() > 0 { - log::debug!(target: "txpool", "Added {} transactions to revalidation queue", transactions.len()); + log::debug!(target: "txpool", "Sent {} transactions to revalidation queue", transactions.len()); } if let Some(ref to_worker) = self.background { diff --git a/client/transaction-pool/src/testing/mod.rs b/client/transaction-pool/src/testing/mod.rs index a8f40c6b6475b57656bb0f373851f2162f283be5..350c4137c37b23a5d1fdfde94f0b19acde7cbdb4 100644 --- a/client/transaction-pool/src/testing/mod.rs +++ b/client/transaction-pool/src/testing/mod.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . //! Tests for top-level transaction pool api diff --git a/client/transaction-pool/src/testing/pool.rs b/client/transaction-pool/src/testing/pool.rs index 45fb6f42c321fab9dfe038506d60fb79ec527ee6..4f30d5b6c350065e83a0d620ecd8a9f7624a500c 100644 --- a/client/transaction-pool/src/testing/pool.rs +++ b/client/transaction-pool/src/testing/pool.rs @@ -1,18 +1,20 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. -// Substrate is free software: you can redistribute it and/or modify +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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, +// This program 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 +// 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 . +// along with this program. If not, see . use crate::*; use sp_transaction_pool::TransactionStatus; diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 31e489ffe5dbfef804345b361dbfd21493143529..4c4cf46e5cb0669f3956597c63a6c3c2cc547fee 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,6 +6,47 @@ The format is based on [Keep a Changelog]. ## Unreleased +## 2.0.0-rc1 -> 2.0.0-rc2 + + + +## 2.0.0-alpha.8 -> 2.0.0-rc1 + +Runtime +------- + +* Allow operational recovery path if on_initialize use fullblock. (#6089) +* Maximum extrinsic weight limit (#6067) + +Client +------ + +* Add JSON format to import blocks and set it as default (#5816) +* Upgrade to libp2p v0.19 - Changes the default PeerId representation (#6064) + + +## 2.0.0-alpha.7 -> 2.0.0-alpha.8 + +**License Changed** +From this release forward, the code is released under a new – more relaxed – license scheme: Client (`sc-*`) is released under "GPL 3.0 or newer with the Classpath Exception", while primitives, FRAME, the pallets, utils and test-utils are released under "Apache 2.0". More details in the [Relax licensing scheme PR](https://github.com/paritytech/substrate/pull/5947). + +Runtime +------- + +* Democracy weight (#5828) +* Make `Digest` support `StorageAppend` (#5922) + +Client +------ + +* Meter block import results via prometheus (#6025) +* Added RuntimePublic for ecdsa public key. (#6029) +* Benchmarks for elections-phragmen pallet (#5845) +* Monitor transactions rejected from the pool as invalid (#5992) +* client/network: Remove default Kademlia DHT in favor of per protocol DHT (#5993) +* Allow passing multiple --log CLI options (#5982) +* client: Replace `unsafe_rpc_expose` with an `RpcMethods` enum (#5729) + ## 2.0.0-alpha.6 -> 2.0.0-alpha.7 Runtime diff --git a/docs/media/sub.gif b/docs/media/sub.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8d73d9171aac0751961206256cf1d219416814e Binary files /dev/null and b/docs/media/sub.gif differ diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index 4e09ea8aa51e8f5f39d87e5ea8294fca26f065e4..f40eab532e2c9287c43ca2ccef2d85b787febf2d 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-assets" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME asset management pallet" @@ -15,16 +15,16 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } # Needed for various traits. In our case, `OnFinalize`. -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } # Needed for type-safe access to storage DB. -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } # `system` module provides us with all sorts of useful stuff and macros depend on it being around. -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-std = { version = "2.0.0-dev", path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc2", path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 1aaedd4c74d79ce948606481249c538de95308f9..2c67a320c1eae3a05bba40f6c77ab7401b9b7731 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Assets Module //! @@ -256,6 +257,8 @@ decl_storage! { /// The next asset identifier up for grabs. NextAssetId get(fn next_asset_id): T::AssetId; /// The total unit supply of an asset. + /// + /// TWOX-NOTE: `AssetId` is trusted, so this is safe. TotalSupply: map hasher(twox_64_concat) T::AssetId => T::Balance; } } @@ -316,6 +319,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml index 623cf80df7b24a26b7b0d0567e3cfc8e6f7272f3..bb964bd415f59a6ea6250f9cfd7b090a8deae6c7 100644 --- a/frame/aura/Cargo.toml +++ b/frame/aura/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-aura" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME AURA consensus pallet" @@ -12,23 +12,23 @@ description = "FRAME AURA consensus pallet" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.101", optional = true } -pallet-session = { version = "2.0.0-dev", default-features = false, path = "../session" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-dev"} -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -sp-consensus-aura = { path = "../../primitives/consensus/aura", default-features = false, version = "0.8.0-dev"} -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -sp-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../primitives/timestamp" } -pallet-timestamp = { version = "2.0.0-dev", default-features = false, path = "../timestamp" } +pallet-session = { version = "2.0.0-rc2", default-features = false, path = "../session" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +sp-consensus-aura = { version = "0.8.0-rc2", path = "../../primitives/consensus/aura", default-features = false } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +sp-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/timestamp" } +pallet-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../timestamp" } [dev-dependencies] +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../primitives/io" } lazy_static = "1.4.0" parking_lot = "0.10.0" @@ -38,8 +38,6 @@ std = [ "sp-application-crypto/std", "codec/std", "sp-inherents/std", - "sp-io/std", - "sp-core/std", "sp-std/std", "serde", "sp-runtime/std", diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs index e2aafde9efe6ef699bcd61ef861fe7104dd7e331..d124ef0017e5ff292abb927e3c6983a1f10c48b6 100644 --- a/frame/aura/src/lib.rs +++ b/frame/aura/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Aura Module //! diff --git a/frame/aura/src/mock.rs b/frame/aura/src/mock.rs index 8154ef4c9f50db3dd99a760e4cfd7e8bee00bac8..84d895cd0609971db0bcfe1c3201d318d1df6197 100644 --- a/frame/aura/src/mock.rs +++ b/frame/aura/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -60,6 +61,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/aura/src/tests.rs b/frame/aura/src/tests.rs index a7cb5503c4712acb79c0902be5f9a707e6f7ad07..ca0fc3de3763809d1f7d4c50d4adf862b8e9305d 100644 --- a/frame/aura/src/tests.rs +++ b/frame/aura/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml index 5f267b3159561345bb30d0b734f89b36d25acc6e..3aa36b5cac6cb6717ce9ba58dd8d2dbf0efeb5bc 100644 --- a/frame/authority-discovery/Cargo.toml +++ b/frame/authority-discovery/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-authority-discovery" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for authority discovery" @@ -12,20 +12,20 @@ description = "FRAME pallet for authority discovery" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-authority-discovery = { version = "2.0.0-dev", default-features = false, path = "../../primitives/authority-discovery" } -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } +sp-authority-discovery = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/authority-discovery" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/application-crypto" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.101", optional = true } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -pallet-session = { version = "2.0.0-dev", features = ["historical" ], path = "../session", default-features = false } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0-rc2", features = ["historical" ], path = "../session", default-features = false } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../primitives/staking" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/staking" } [features] default = ["std"] @@ -33,8 +33,6 @@ std = [ "sp-application-crypto/std", "sp-authority-discovery/std", "codec/std", - "sp-core/std", - "sp-io/std", "sp-std/std", "serde", "pallet-session/std", diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index ca3e293ae740e69dad63f366cdc34c38023fe046..1b7915ce3a4d467dc70595f92ba11c98fe4749f0 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Authority discovery module. //! @@ -157,6 +158,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 98776c0e00d012a35d3d4faa5d82f6b8622b5655..7bde40887a9f6428a848db545daffe3ac5337c37 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "pallet-authorship" -version = "2.0.0-dev" +version = "2.0.0-rc2" description = "Block and Uncle Author tracking for the FRAME" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,27 +12,27 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-authorship = { version = "2.0.0-dev", default-features = false, path = "../../primitives/authorship" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-dev"} +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/inherents" } +sp-authorship = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/authorship" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } impl-trait-for-tuples = "0.1.3" +[dev-dependencies] +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../primitives/io" } + [features] default = ["std"] std = [ "codec/std", - "sp-core/std", "sp-inherents/std", "sp-runtime/std", "sp-std/std", "frame-support/std", "frame-system/std", - "sp-io/std", "sp-authorship/std", ] diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index e799ec2367e84e6627e23396f15b34e620db0bc5..b9b30bf41111ac17ee8f4b232acdd46907b9ec44 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Authorship tracking for FRAME runtimes. //! @@ -432,6 +433,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml index 631b4ac4d4abdda90fd6c810a4943aa28401d9d5..060b6ad1ec341ad6d5bb8212a184619608915792 100644 --- a/frame/babe/Cargo.toml +++ b/frame/babe/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-babe" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Consensus extension module for BABE consensus. Collects on-chain randomness from VRF outputs and manages epoch transitions." @@ -14,28 +14,28 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-timestamp = { version = "2.0.0-dev", default-features = false, path = "../timestamp" } -sp-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../primitives/timestamp" } -pallet-session = { version = "2.0.0-dev", default-features = false, path = "../session" } -sp-consensus-babe = { version = "0.8.0-dev", default-features = false, path = "../../primitives/consensus/babe" } -sp-consensus-vrf = { version = "0.8.0-dev", default-features = false, path = "../../primitives/consensus/vrf" } -sp-io = { path = "../../primitives/io", default-features = false , version = "2.0.0-dev"} +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/inherents" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/application-crypto" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../timestamp" } +sp-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/timestamp" } +pallet-session = { version = "2.0.0-rc2", default-features = false, path = "../session" } +sp-consensus-babe = { version = "0.8.0-rc2", default-features = false, path = "../../primitives/consensus/babe" } +sp-consensus-vrf = { version = "0.8.0-rc2", default-features = false, path = "../../primitives/consensus/vrf" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } [features] default = ["std"] std = [ - "serde", "codec/std", + "serde", "sp-std/std", "sp-application-crypto/std", "frame-support/std", diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index dc704b5bcc338e385c3913f48bca768d316bcda5..91421739327ab0e885da3af3d86491ff1210132f 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Consensus extension module for BABE consensus. Collects on-chain randomness //! from VRF outputs and manages epoch transitions. @@ -41,7 +42,7 @@ use sp_inherents::{InherentIdentifier, InherentData, ProvideInherent, MakeFatalE use sp_consensus_babe::{ BABE_ENGINE_ID, ConsensusLog, BabeAuthorityWeight, SlotNumber, inherents::{INHERENT_IDENTIFIER, BabeInherentData}, - digests::{NextEpochDescriptor, PreDigest}, + digests::{NextEpochDescriptor, NextConfigDescriptor, PreDigest}, }; use sp_consensus_vrf::schnorrkel; pub use sp_consensus_babe::{AuthorityId, VRF_OUTPUT_LENGTH, RANDOMNESS_LENGTH, PUBLIC_KEY_LENGTH}; @@ -135,6 +136,9 @@ decl_storage! { // variable to its underlying value. pub Randomness get(fn randomness): schnorrkel::Randomness; + /// Next epoch configuration, if changed. + NextEpochConfig: Option; + /// Next epoch randomness. NextRandomness: schnorrkel::Randomness; @@ -148,6 +152,8 @@ decl_storage! { /// We reset all segments and return to `0` at the beginning of every /// epoch. SegmentIndex build(|_| 0): u32; + + /// TWOX-NOTE: `SegmentIndex` is an increasing integer, so this is okay. UnderConstruction: map hasher(twox_64_concat) u32 => Vec; /// Temporary value (cleared at block finalization) which is `Some` @@ -349,6 +355,9 @@ impl Module { // -------------- IMPORTANT NOTE -------------- // This implementation is linked to how [`should_epoch_change`] is working. This might need to // be updated accordingly, if the underlying mechanics of slot and epochs change. + // + // WEIGHT NOTE: This function is tied to the weight of `EstimateNextSessionRotation`. If you update + // this function, you must also update the corresponding weight. pub fn next_expected_epoch_change(now: T::BlockNumber) -> Option { let next_slot = Self::current_epoch_start().saturating_add(T::EpochDuration::get()); next_slot @@ -360,6 +369,15 @@ impl Module { }) } + /// Plan an epoch config change. The epoch config change is recorded and will be enacted on the + /// next call to `enact_epoch_change`. The config will be activated one epoch after. Multiple calls to this + /// method will replace any existing planned config change that had not been enacted yet. + pub fn plan_config_change( + config: NextConfigDescriptor, + ) { + NextEpochConfig::put(config); + } + /// DANGEROUS: Enact an epoch change. Should be done on every block where `should_epoch_change` has returned `true`, /// and the caller is the only caller of this function. /// @@ -395,12 +413,15 @@ impl Module { // so that nodes can track changes. let next_randomness = NextRandomness::get(); - let next = NextEpochDescriptor { + let next_epoch = NextEpochDescriptor { authorities: next_authorities, randomness: next_randomness, }; + Self::deposit_consensus(ConsensusLog::NextEpochData(next_epoch)); - Self::deposit_consensus(ConsensusLog::NextEpochData(next)) + if let Some(next_config) = NextEpochConfig::take() { + Self::deposit_consensus(ConsensusLog::NextConfigData(next_config)); + } } // finds the start slot of the current epoch. only guaranteed to @@ -550,6 +571,12 @@ impl frame_support::traits::EstimateNextSessionRotation Option { Self::next_expected_epoch_change(now) } + + // The validity of this weight depends on the implementation of `estimate_next_session_rotation` + fn weight(_now: T::BlockNumber) -> Weight { + // Read: Current Slot, Epoch Index, Genesis Slot + T::DbWeight::get().reads(3) + } } impl frame_support::traits::Lateness for Module { diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index 933c69c98ab6011cd8c0278ad253ae8e900e61e4..de0092817149417eb486fa7ba8939782a1653365 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -72,6 +73,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type ModuleToIndex = (); diff --git a/frame/babe/src/tests.rs b/frame/babe/src/tests.rs index af2ecd1e1a0af2b13dc778140d3e2ec1c6b48f9a..ecb3639fc573bd66230ada5ce052e966d4edc8b3 100644 --- a/frame/babe/src/tests.rs +++ b/frame/babe/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Consensus extension module tests for BABE consensus. @@ -21,6 +22,7 @@ use mock::*; use frame_support::traits::OnFinalize; use pallet_session::ShouldEndSession; use sp_core::crypto::IsWrappedBy; +use sp_consensus_babe::AllowedSlots; use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof}; const EMPTY_RANDOMNESS: [u8; 32] = [ @@ -149,3 +151,35 @@ fn can_predict_next_epoch_change() { assert_eq!(Babe::next_expected_epoch_change(System::block_number()), Some(5 + 2)); }) } + +#[test] +fn can_enact_next_config() { + new_test_ext(0).1.execute_with(|| { + assert_eq!(::EpochDuration::get(), 3); + // this sets the genesis slot to 6; + go_to_block(1, 6); + assert_eq!(Babe::genesis_slot(), 6); + assert_eq!(Babe::current_slot(), 6); + assert_eq!(Babe::epoch_index(), 0); + go_to_block(2, 7); + + Babe::plan_config_change(NextConfigDescriptor::V1 { + c: (1, 4), + allowed_slots: AllowedSlots::PrimarySlots, + }); + + progress_to_block(4); + Babe::on_finalize(9); + let header = System::finalize(); + + let consensus_log = sp_consensus_babe::ConsensusLog::NextConfigData( + sp_consensus_babe::digests::NextConfigDescriptor::V1 { + c: (1, 4), + allowed_slots: AllowedSlots::PrimarySlots, + } + ); + let consensus_digest = DigestItem::Consensus(BABE_ENGINE_ID, consensus_log.encode()); + + assert_eq!(header.digest.logs[2], consensus_digest.clone()) + }); +} diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 769e68112cedb46f89cf7e68462391ee7092378e..ae69fb17c2acd45b1b0236ae46efafcb829fecef 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-balances" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage balances" @@ -14,16 +14,16 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-transaction-payment = { version = "2.0.0-dev", path = "../transaction-payment" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +pallet-transaction-payment = { version = "2.0.0-rc2", path = "../transaction-payment" } [features] default = ["std"] @@ -31,7 +31,6 @@ std = [ "serde", "codec/std", "sp-std/std", - "sp-io/std", "sp-runtime/std", "frame-benchmarking/std", "frame-support/std", diff --git a/frame/balances/src/benchmarking.rs b/frame/balances/src/benchmarking.rs index 3c2067559fcf21dcae48356f0acf00685c7844f2..a5f8e6fe36cd48190f964348e68580a185cd28d0 100644 --- a/frame/balances/src/benchmarking.rs +++ b/frame/balances/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Balances pallet benchmarking. diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index b1d88edb0333eb5bae561365fcac0de091667b81..d5f9aab37bc95c1b2b71d257a64ecdb0e9e0dfaf 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Balances Module //! @@ -862,6 +863,7 @@ impl, I: Instance> frame_system::Trait for ElevatedTrait { type DbWeight = T::DbWeight; type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = T::MaximumBlockWeight; type MaximumBlockLength = T::MaximumBlockLength; type AvailableBlockRatio = T::AvailableBlockRatio; type Version = T::Version; diff --git a/frame/balances/src/tests.rs b/frame/balances/src/tests.rs index 7663b8922bc04efa32b1a6fefcc476590436c9c6..149b9f07d223b38b283179c00b38c4ebfe7a4f00 100644 --- a/frame/balances/src/tests.rs +++ b/frame/balances/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macro for creating the tests for the module. @@ -36,7 +37,7 @@ macro_rules! decl_tests { ($test:ty, $ext_builder:ty, $existential_deposit:expr) => { use crate::*; - use sp_runtime::{Fixed128, traits::{SignedExtension, BadOrigin}}; + use sp_runtime::{FixedPointNumber, Fixed128, traits::{SignedExtension, BadOrigin}}; use frame_support::{ assert_noop, assert_ok, assert_err, traits::{ @@ -153,7 +154,7 @@ macro_rules! decl_tests { .monied(true) .build() .execute_with(|| { - pallet_transaction_payment::NextFeeMultiplier::put(Fixed128::from_natural(1)); + pallet_transaction_payment::NextFeeMultiplier::put(Fixed128::saturating_from_integer(1)); Balances::set_lock(ID_1, &1, 10, WithdrawReason::Reserve.into()); assert_noop!( >::transfer(&1, &2, 1, AllowDeath), diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index 5d25fdb50ceba6dd8b09e014f904a0e408eba43d..7b9ec1f91eade64d2268181cc5c8970e51ece09a 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -20,14 +21,14 @@ use sp_runtime::{ Perbill, - traits::{ConvertInto, IdentityLookup}, + traits::IdentityLookup, testing::Header, }; use sp_core::H256; use sp_io; use frame_support::{impl_outer_origin, parameter_types}; use frame_support::traits::Get; -use frame_support::weights::{Weight, DispatchInfo}; +use frame_support::weights::{Weight, DispatchInfo, IdentityFee}; use std::cell::RefCell; use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo}; @@ -70,6 +71,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -85,7 +87,7 @@ impl pallet_transaction_payment::Trait for Test { type Currency = Module; type OnTransactionPayment = (); type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } impl Trait for Test { diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index afc0edbae7f161c3c0284f271b63c2f15cfdb3f2..9ff76839f4cb270537bdad6cc36c403ea260a996 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -20,14 +21,14 @@ use sp_runtime::{ Perbill, - traits::{ConvertInto, IdentityLookup}, + traits::IdentityLookup, testing::Header, }; use sp_core::H256; use sp_io; use frame_support::{impl_outer_origin, parameter_types}; use frame_support::traits::{Get, StorageMapShim}; -use frame_support::weights::{Weight, DispatchInfo}; +use frame_support::weights::{Weight, DispatchInfo, IdentityFee}; use std::cell::RefCell; use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo}; @@ -70,6 +71,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -85,7 +87,7 @@ impl pallet_transaction_payment::Trait for Test { type Currency = Module; type OnTransactionPayment = (); type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } impl Trait for Test { diff --git a/frame/benchmark/Cargo.toml b/frame/benchmark/Cargo.toml index 0b506d12ec90e838438b433e74ac8e8df5a413f7..6ef770b6c1b0a91f5104ef39153f985e21bde150 100644 --- a/frame/benchmark/Cargo.toml +++ b/frame/benchmark/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-benchmark" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Patterns to benchmark in a FRAME runtime." @@ -14,12 +14,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } [features] default = ["std"] diff --git a/frame/benchmark/src/benchmarking.rs b/frame/benchmark/src/benchmarking.rs index 1e4740da2c0595b45be30c4a1dc2496176f7d157..ddf3df9eaad4cb5a367724a5b2b1508359856bc4 100644 --- a/frame/benchmark/src/benchmarking.rs +++ b/frame/benchmark/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Benchmarks for common FRAME Pallet operations. diff --git a/frame/benchmark/src/lib.rs b/frame/benchmark/src/lib.rs index 037edc9d269860fcb5914221b33ca5c873950166..422272f817c7a2f75c2b991a40a01929b4dc48b2 100644 --- a/frame/benchmark/src/lib.rs +++ b/frame/benchmark/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A pallet that contains common runtime patterns in an isolated manner. //! This pallet is **not** meant to be used in a production blockchain, just diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml index 8089a2a3661d0ffecc7b5c6c067ce740e350a083..24db2adc48f295bf1020af9d71b0588dcc6c3b41 100644 --- a/frame/benchmarking/Cargo.toml +++ b/frame/benchmarking/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-benchmarking" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Macro for benchmarking a FRAME runtime." @@ -15,13 +15,13 @@ targets = ["x86_64-unknown-linux-gnu"] linregress = "0.1" paste = "0.1" codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-api = { version = "2.0.0-dev", path = "../../primitives/api", default-features = false } -sp-runtime-interface = { version = "2.0.0-dev", path = "../../primitives/runtime-interface", default-features = false } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime", default-features = false } -sp-std = { version = "2.0.0-dev", path = "../../primitives/std", default-features = false } -sp-io = { path = "../../primitives/io", default-features = false, version = "2.0.0-dev"} -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-api = { version = "2.0.0-rc2", path = "../../primitives/api", default-features = false } +sp-runtime-interface = { version = "2.0.0-rc2", path = "../../primitives/runtime-interface", default-features = false } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime", default-features = false } +sp-std = { version = "2.0.0-rc2", path = "../../primitives/std", default-features = false } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io", default-features = false } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [features] default = [ "std" ] diff --git a/frame/benchmarking/src/analysis.rs b/frame/benchmarking/src/analysis.rs index 1d30b86fc9f41ccc9045f01e58a669ba3c524e75..04464309755505a29702bc3fb2a32cbc8563a54b 100644 --- a/frame/benchmarking/src/analysis.rs +++ b/frame/benchmarking/src/analysis.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tools for analysing the benchmark results. diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index 8a9df7e4cf3419823bb696b979eda0550aec5e16..ae9ef90764cd2387fb03f89533f74afa4cbcc1e6 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macro for benchmarking a FRAME runtime. @@ -921,6 +922,10 @@ macro_rules! impl_benchmark_tests { let selected_benchmark = SelectedBenchmark::$name; let components = >::components(&selected_benchmark); + assert!( + components.len() != 0, + "You need to add components to your benchmark!", + ); for (_, (name, low, high)) in components.iter().enumerate() { // Test only the low and high value, assuming values in the middle won't break for component_value in vec![low, high] { diff --git a/frame/benchmarking/src/tests.rs b/frame/benchmarking/src/tests.rs index 67ad9b4d22025dd8b4132ee1b023049132cf6da8..dc9d160b5ee9268f826a8fda1b092e5f94350420 100644 --- a/frame/benchmarking/src/tests.rs +++ b/frame/benchmarking/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. @@ -81,6 +82,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); type MaximumBlockLength = (); type AvailableBlockRatio = (); type Version = (); diff --git a/frame/benchmarking/src/utils.rs b/frame/benchmarking/src/utils.rs index 41b968fbfcad6be7be50a5d737399a9fcd41d0c1..31ec3783cc06167f5a7e3f282894fbb117fdec0a 100644 --- a/frame/benchmarking/src/utils.rs +++ b/frame/benchmarking/src/utils.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Interfaces, types and utils for benchmarking a FRAME runtime. diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml index 2107bf0b2f5dbbd8834692890d376083b8e80fcc..d62b5ee580dea4098e348262c9ea635e9f92e928 100644 --- a/frame/collective/Cargo.toml +++ b/frame/collective/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-collective" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Collective system: Members of a set of account IDs can make their collective feelings known through dispatched calls from one of two specialized origins." @@ -14,17 +14,17 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] hex-literal = "0.2.1" -pallet-balances = { version = "2.0.0-dev", path = "../balances" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } [features] default = ["std"] diff --git a/frame/collective/src/benchmarking.rs b/frame/collective/src/benchmarking.rs index 5c25051fd083716065cbb90a59b17041d7219724..b9558d8c8ce1c54badba18e5de6558f13591d54d 100644 --- a/frame/collective/src/benchmarking.rs +++ b/frame/collective/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Staking pallet benchmarking. @@ -22,14 +23,14 @@ use frame_system::RawOrigin as SystemOrigin; use frame_system::EventRecord; use frame_benchmarking::{benchmarks_instance, account}; use sp_runtime::traits::Bounded; +use sp_std::mem::size_of; +use frame_system::Call as SystemCall; use frame_system::Module as System; use crate::Module as Collective; const SEED: u32 = 0; -const MAX_MEMBERS: u32 = 1000; -const MAX_PROPOSALS: u32 = 100; const MAX_BYTES: u32 = 1_024; fn assert_last_event, I: Instance>(generic_event: >::Event) { @@ -46,28 +47,64 @@ benchmarks_instance! { set_members { let m in 1 .. MAX_MEMBERS; let n in 1 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); // Set old members. // We compute the difference of old and new members, so it should influence timing. let mut old_members = vec![]; let mut last_old_member = T::AccountId::default(); - for i in 0 .. n { + for i in 0 .. m { last_old_member = account("old member", i, SEED); old_members.push(last_old_member.clone()); } + let old_members_count = old_members.len() as u32; - Collective::::set_members(SystemOrigin::Root.into(), old_members, Some(last_old_member))?; + Collective::::set_members( + SystemOrigin::Root.into(), + old_members.clone(), + Some(last_old_member.clone()), + MAX_MEMBERS, + )?; + + // Set a high threshold for proposals passing so that they stay around. + let threshold = m.max(2); + // Length of the proposals should be irrelevant to `set_members`. + let length = 100; + for i in 0 .. p { + // Proposals should be different so that different proposal hashes are generated + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; length]).into(); + Collective::::propose( + SystemOrigin::Signed(last_old_member.clone()).into(), + threshold, + Box::new(proposal.clone()), + MAX_BYTES, + )?; + let hash = T::Hashing::hash_of(&proposal); + // Vote on the proposal to increase state relevant for `set_members`. + // Not voting for `last_old_member` because they proposed and not voting for the first member + // to keep the proposal from passing. + for j in 2 .. m - 1 { + let voter = &old_members[j as usize]; + let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + hash, + i, + approve, + )?; + } + } // Construct `new_members`. // It should influence timing since it will sort this vector. let mut new_members = vec![]; let mut last_member = T::AccountId::default(); - for i in 0 .. m { + for i in 0 .. n { last_member = account("member", i, SEED); new_members.push(last_member.clone()); } - }: _(SystemOrigin::Root, new_members.clone(), Some(last_member)) + }: _(SystemOrigin::Root, new_members.clone(), Some(last_member), MAX_MEMBERS) verify { new_members.sort(); assert_eq!(Collective::::members(), new_members); @@ -77,9 +114,11 @@ benchmarks_instance! { let m in 1 .. MAX_MEMBERS; let b in 1 .. MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; + // Construct `members`. let mut members = vec![]; - for i in 0 .. m { + for i in 0 .. m - 1 { let member = account("member", i, SEED); members.push(member); } @@ -87,15 +126,17 @@ benchmarks_instance! { let caller: T::AccountId = account("caller", 0, SEED); members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members, None)?; + Collective::::set_members(SystemOrigin::Root.into(), members, None, MAX_MEMBERS)?; - let proposal: T::Proposal = frame_system::Call::::remark(vec![1; b as usize]).into(); + let proposal: T::Proposal = SystemCall::::remark(vec![1; b as usize]).into(); - }: _(SystemOrigin::Signed(caller), Box::new(proposal.clone())) + }: _(SystemOrigin::Signed(caller), Box::new(proposal.clone()), bytes_in_storage) verify { let proposal_hash = T::Hashing::hash_of(&proposal); // Note that execution fails due to mis-matched origin - assert_last_event::(RawEvent::MemberExecuted(proposal_hash, false).into()); + assert_last_event::( + RawEvent::MemberExecuted(proposal_hash, Err(DispatchError::BadOrigin)).into() + ); } // This tests when execution would happen immediately after proposal @@ -103,9 +144,11 @@ benchmarks_instance! { let m in 1 .. MAX_MEMBERS; let b in 1 .. MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; + // Construct `members`. let mut members = vec![]; - for i in 0 .. m { + for i in 0 .. m - 1 { let member = account("member", i, SEED); members.push(member); } @@ -113,169 +156,230 @@ benchmarks_instance! { let caller: T::AccountId = account("caller", 0, SEED); members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members, None)?; + Collective::::set_members(SystemOrigin::Root.into(), members, None, MAX_MEMBERS)?; - let proposal: T::Proposal = frame_system::Call::::remark(vec![1; b as usize]).into(); + let proposal: T::Proposal = SystemCall::::remark(vec![1; b as usize]).into(); let threshold = 1; - }: propose(SystemOrigin::Signed(caller), threshold, Box::new(proposal.clone())) + }: propose(SystemOrigin::Signed(caller), threshold, Box::new(proposal.clone()), bytes_in_storage) verify { let proposal_hash = T::Hashing::hash_of(&proposal); // Note that execution fails due to mis-matched origin - assert_last_event::(RawEvent::Executed(proposal_hash, false).into()); + assert_last_event::( + RawEvent::Executed(proposal_hash, Err(DispatchError::BadOrigin)).into() + ); } // This tests when proposal is created and queued as "proposed" propose_proposed { - let m in 1 .. MAX_MEMBERS; - let p in 0 .. MAX_PROPOSALS; + let m in 2 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); let b in 1 .. MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; + // Construct `members`. let mut members = vec![]; - for i in 0 .. m { + for i in 0 .. m - 1 { let member = account("member", i, SEED); members.push(member); } - let caller: T::AccountId = account("caller", 0, SEED); members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members, None)?; - - let threshold = m.max(2); + Collective::::set_members(SystemOrigin::Root.into(), members, None, MAX_MEMBERS)?; + let threshold = m; // Add previous proposals. - for i in 0 .. p { + for i in 0 .. p - 1 { // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = frame_system::Call::::remark(vec![i as u8; b as usize]).into(); - Collective::::propose(SystemOrigin::Signed(caller.clone()).into(), threshold, Box::new(proposal))?; + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(caller.clone()).into(), + threshold, + Box::new(proposal), + bytes_in_storage, + )?; } - assert_eq!(Collective::::proposals().len(), p as usize); + assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - let proposal: T::Proposal = frame_system::Call::::remark(vec![p as u8; b as usize]).into(); + let proposal: T::Proposal = SystemCall::::remark(vec![p as u8; b as usize]).into(); - }: propose(SystemOrigin::Signed(caller.clone()), threshold, Box::new(proposal.clone())) + }: propose(SystemOrigin::Signed(caller.clone()), threshold, Box::new(proposal.clone()), bytes_in_storage) verify { // New proposal is recorded - assert_eq!(Collective::::proposals().len(), (p + 1) as usize); + assert_eq!(Collective::::proposals().len(), p as usize); let proposal_hash = T::Hashing::hash_of(&proposal); - assert_last_event::(RawEvent::Proposed(caller, p, proposal_hash, threshold).into()); + assert_last_event::(RawEvent::Proposed(caller, p - 1, proposal_hash, threshold).into()); } - vote_insert { - let m in 2 .. MAX_MEMBERS; - let p in 1 .. MAX_PROPOSALS; - let b in 1 .. MAX_BYTES; + vote { + // We choose 5 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 5 .. MAX_MEMBERS; + + let p = T::MaxProposals::get(); + let b = MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; // Construct `members`. let mut members = vec![]; - for i in 0 .. m { + let proposer: T::AccountId = account("proposer", 0, SEED); + members.push(proposer.clone()); + for i in 1 .. m - 1 { let member = account("member", i, SEED); members.push(member); } - - let caller: T::AccountId = account("caller", 0, SEED); - members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None)?; + let voter: T::AccountId = account("voter", 0, SEED); + members.push(voter.clone()); + Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, MAX_MEMBERS)?; // Threshold is 1 less than the number of members so that one person can vote nay - let threshold = m; + let threshold = m - 1; // Add previous proposals let mut last_hash = T::Hash::default(); for i in 0 .. p { // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = frame_system::Call::::remark(vec![i as u8; b as usize]).into(); - Collective::::propose(SystemOrigin::Signed(caller.clone()).into(), threshold, Box::new(proposal.clone()))?; + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(proposer.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; last_hash = T::Hashing::hash_of(&proposal); } - // Have everyone vote aye on last proposal, while keeping it from passing - for j in 2 .. m { + let index = p - 1; + // Have almost everyone vote aye on last proposal, while keeping it from passing. + // Proposer already voted aye so we start at 1. + for j in 1 .. m - 3 { let voter = &members[j as usize]; let approve = true; - Collective::::vote(SystemOrigin::Signed(voter.clone()).into(), last_hash.clone(), p - 1, approve)?; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; } + // Voter votes aye without resolving the vote. + let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; assert_eq!(Collective::::proposals().len(), p as usize); - // Caller switches vote to nay, but does not kill the vote, just updates + inserts - let index = p - 1; + // Voter switches vote to nay, but does not kill the vote, just updates + inserts let approve = false; - }: vote(SystemOrigin::Signed(caller), last_hash.clone(), index, approve) + }: _(SystemOrigin::Signed(voter), last_hash.clone(), index, approve) verify { // All proposals exist and the last proposal has just been updated. assert_eq!(Collective::::proposals().len(), p as usize); let voting = Collective::::voting(&last_hash).ok_or(Error::::ProposalMissing)?; - assert_eq!(voting.ayes.len(), (m - 2) as usize); + assert_eq!(voting.ayes.len(), (m - 3) as usize); assert_eq!(voting.nays.len(), 1); } - vote_disapproved { - let m in 2 .. MAX_MEMBERS; - let p in 1 .. MAX_PROPOSALS; + close_early_disapproved { + // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 4 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); let b in 1 .. MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; + // Construct `members`. let mut members = vec![]; - for i in 0 .. m { + let proposer: T::AccountId = account("proposer", 0, SEED); + members.push(proposer.clone()); + for i in 1 .. m - 1 { let member = account("member", i, SEED); members.push(member); } - - let caller: T::AccountId = account("caller", 0, SEED); - members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None)?; + let voter: T::AccountId = account("voter", 0, SEED); + members.push(voter.clone()); + Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, MAX_MEMBERS)?; // Threshold is total members so that one nay will disapprove the vote - let threshold = m + 1; + let threshold = m; // Add previous proposals let mut last_hash = T::Hash::default(); for i in 0 .. p { // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = frame_system::Call::::remark(vec![i as u8; b as usize]).into(); - Collective::::propose(SystemOrigin::Signed(caller.clone()).into(), threshold, Box::new(proposal.clone()))?; + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(proposer.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; last_hash = T::Hashing::hash_of(&proposal); } - // Have everyone vote aye on last proposal, while keeping it from passing - for j in 1 .. m { + let index = p - 1; + // Have most everyone vote aye on last proposal, while keeping it from passing. + // Proposer already voted aye so we start at 1. + for j in 1 .. m - 2 { let voter = &members[j as usize]; let approve = true; - Collective::::vote(SystemOrigin::Signed(voter.clone()).into(), last_hash.clone(), p - 1, approve)?; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; } + // Voter votes aye without resolving the vote. + let approve = true; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; assert_eq!(Collective::::proposals().len(), p as usize); - // Caller switches vote to nay, which kills the vote - let index = p - 1; + // Voter switches vote to nay, which kills the vote let approve = false; - - }: vote(SystemOrigin::Signed(caller), last_hash.clone(), index, approve) + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; + + }: close(SystemOrigin::Signed(voter), last_hash.clone(), index, Weight::max_value(), bytes_in_storage) verify { // The last proposal is removed. assert_eq!(Collective::::proposals().len(), (p - 1) as usize); assert_last_event::(RawEvent::Disapproved(last_hash).into()); } - vote_approved { - let m in 2 .. MAX_MEMBERS; - let p in 1 .. MAX_PROPOSALS; + close_early_approved { + // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 4 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); let b in 1 .. MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; + // Construct `members`. let mut members = vec![]; - for i in 0 .. m { + for i in 0 .. m - 1 { let member = account("member", i, SEED); members.push(member); } - let caller: T::AccountId = account("caller", 0, SEED); members.push(caller.clone()); - Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None)?; + Collective::::set_members(SystemOrigin::Root.into(), members.clone(), None, MAX_MEMBERS)?; // Threshold is 2 so any two ayes will approve the vote let threshold = 2; @@ -284,102 +388,156 @@ benchmarks_instance! { let mut last_hash = T::Hash::default(); for i in 0 .. p { // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = frame_system::Call::::remark(vec![i as u8; b as usize]).into(); - Collective::::propose(SystemOrigin::Signed(caller.clone()).into(), threshold, Box::new(proposal.clone()))?; + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(caller.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; last_hash = T::Hashing::hash_of(&proposal); } // Caller switches vote to nay on their own proposal, allowing them to be the deciding approval vote - Collective::::vote(SystemOrigin::Signed(caller.clone()).into(), last_hash.clone(), p - 1, false)?; - - // Have everyone vote nay on last proposal, while keeping it from failing - for j in 2 .. m { + Collective::::vote( + SystemOrigin::Signed(caller.clone()).into(), + last_hash.clone(), + p - 1, + false, + )?; + + // Have almost everyone vote nay on last proposal, while keeping it from failing. + for j in 2 .. m - 1 { let voter = &members[j as usize]; let approve = false; - Collective::::vote(SystemOrigin::Signed(voter.clone()).into(), last_hash.clone(), p - 1, approve)?; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + p - 1, + approve, + )?; } // Member zero is the first aye - Collective::::vote(SystemOrigin::Signed(members[0].clone()).into(), last_hash.clone(), p - 1, true)?; + Collective::::vote( + SystemOrigin::Signed(members[0].clone()).into(), + last_hash.clone(), + p - 1, + true, + )?; assert_eq!(Collective::::proposals().len(), p as usize); // Caller switches vote to aye, which passes the vote let index = p - 1; let approve = true; + Collective::::vote( + SystemOrigin::Signed(caller.clone()).into(), + last_hash.clone(), + index, approve, + )?; - }: vote(SystemOrigin::Signed(caller), last_hash.clone(), index, approve) + }: close(SystemOrigin::Signed(caller), last_hash.clone(), index, Weight::max_value(), bytes_in_storage) verify { // The last proposal is removed. assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(RawEvent::Executed(last_hash, false).into()); + assert_last_event::(RawEvent::Executed(last_hash, Err(DispatchError::BadOrigin)).into()); } close_disapproved { - let m in 2 .. MAX_MEMBERS; - let p in 1 .. MAX_PROPOSALS; + // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 4 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); let b in 1 .. MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; + // Construct `members`. let mut members = vec![]; - for i in 0 .. m { + for i in 0 .. m - 1 { let member = account("member", i, SEED); members.push(member); } let caller: T::AccountId = account("caller", 0, SEED); members.push(caller.clone()); - - Collective::::set_members(SystemOrigin::Root.into(), members.clone(), Some(caller.clone()))?; + Collective::::set_members( + SystemOrigin::Root.into(), + members.clone(), + Some(caller.clone()), + MAX_MEMBERS, + )?; // Threshold is one less than total members so that two nays will disapprove the vote - let threshold = m; + let threshold = m - 1; // Add proposals let mut last_hash = T::Hash::default(); for i in 0 .. p { // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = frame_system::Call::::remark(vec![i as u8; b as usize]).into(); - Collective::::propose(SystemOrigin::Signed(caller.clone()).into(), threshold, Box::new(proposal.clone()))?; + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(caller.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; last_hash = T::Hashing::hash_of(&proposal); } - // Have everyone vote aye on last proposal, while keeping it from passing - // A few abstainers will be the nay votes needed to fail the vote - for j in 2 .. m { + let index = p - 1; + // Have almost everyone vote aye on last proposal, while keeping it from passing. + // A few abstainers will be the nay votes needed to fail the vote. + for j in 2 .. m - 1 { let voter = &members[j as usize]; let approve = true; - Collective::::vote(SystemOrigin::Signed(voter.clone()).into(), last_hash.clone(), p - 1, approve)?; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + index, + approve, + )?; } // caller is prime, prime votes nay - Collective::::vote(SystemOrigin::Signed(caller.clone()).into(), last_hash.clone(), p - 1, false)?; + Collective::::vote( + SystemOrigin::Signed(caller.clone()).into(), + last_hash.clone(), + index, + false, + )?; System::::set_block_number(T::BlockNumber::max_value()); assert_eq!(Collective::::proposals().len(), p as usize); // Prime nay will close it as disapproved - }: close(SystemOrigin::Signed(caller), last_hash, p - 1) + }: close(SystemOrigin::Signed(caller), last_hash, index, Weight::max_value(), bytes_in_storage) verify { assert_eq!(Collective::::proposals().len(), (p - 1) as usize); assert_last_event::(RawEvent::Disapproved(last_hash).into()); } - close_approved { - let m in 2 .. MAX_MEMBERS; - let p in 1 .. MAX_PROPOSALS; + // We choose 4 as a minimum so we always trigger a vote in the voting loop (`for j in ...`) + let m in 4 .. MAX_MEMBERS; + let p in 1 .. T::MaxProposals::get(); let b in 1 .. MAX_BYTES; + let bytes_in_storage = b + size_of::() as u32; + // Construct `members`. let mut members = vec![]; - for i in 0 .. m { + for i in 0 .. m - 1 { let member = account("member", i, SEED); members.push(member); } let caller: T::AccountId = account("caller", 0, SEED); members.push(caller.clone()); - - Collective::::set_members(SystemOrigin::Root.into(), members.clone(), Some(caller.clone()))?; + Collective::::set_members( + SystemOrigin::Root.into(), + members.clone(), + Some(caller.clone()), + MAX_MEMBERS, + )?; // Threshold is two, so any two ayes will pass the vote let threshold = 2; @@ -388,17 +546,27 @@ benchmarks_instance! { let mut last_hash = T::Hash::default(); for i in 0 .. p { // Proposals should be different so that different proposal hashes are generated - let proposal: T::Proposal = frame_system::Call::::remark(vec![i as u8; b as usize]).into(); - Collective::::propose(SystemOrigin::Signed(caller.clone()).into(), threshold, Box::new(proposal.clone()))?; + let proposal: T::Proposal = SystemCall::::remark(vec![i as u8; b as usize]).into(); + Collective::::propose( + SystemOrigin::Signed(caller.clone()).into(), + threshold, + Box::new(proposal.clone()), + bytes_in_storage, + )?; last_hash = T::Hashing::hash_of(&proposal); } - // Have everyone vote nay on last proposal, while keeping it from failing - // A few abstainers will be the aye votes needed to pass the vote - for j in 2 .. m { + // Have almost everyone vote nay on last proposal, while keeping it from failing. + // A few abstainers will be the aye votes needed to pass the vote. + for j in 2 .. m - 1 { let voter = &members[j as usize]; let approve = false; - Collective::::vote(SystemOrigin::Signed(voter.clone()).into(), last_hash.clone(), p - 1, approve)?; + Collective::::vote( + SystemOrigin::Signed(voter.clone()).into(), + last_hash.clone(), + p - 1, + approve + )?; } // caller is prime, prime already votes aye by creating the proposal @@ -406,10 +574,10 @@ benchmarks_instance! { assert_eq!(Collective::::proposals().len(), p as usize); // Prime aye will close it as approved - }: close(SystemOrigin::Signed(caller), last_hash, p - 1) + }: close(SystemOrigin::Signed(caller), last_hash, p - 1, Weight::max_value(), bytes_in_storage) verify { assert_eq!(Collective::::proposals().len(), (p - 1) as usize); - assert_last_event::(RawEvent::Executed(last_hash, false).into()); + assert_last_event::(RawEvent::Executed(last_hash, Err(DispatchError::BadOrigin)).into()); } } @@ -420,16 +588,64 @@ mod tests { use frame_support::assert_ok; #[test] - fn test_benchmarks() { + fn set_members() { new_test_ext().execute_with(|| { assert_ok!(test_benchmark_set_members::()); + }); + } + + #[test] + fn execute() { + new_test_ext().execute_with(|| { assert_ok!(test_benchmark_execute::()); + }); + } + + #[test] + fn propose_execute() { + new_test_ext().execute_with(|| { assert_ok!(test_benchmark_propose_execute::()); + }); + } + + #[test] + fn propose_proposed() { + new_test_ext().execute_with(|| { assert_ok!(test_benchmark_propose_proposed::()); - assert_ok!(test_benchmark_vote_insert::()); - assert_ok!(test_benchmark_vote_disapproved::()); - assert_ok!(test_benchmark_vote_approved::()); + }); + } + + #[test] + fn vote() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_vote::()); + }); + } + + #[test] + fn close_early_disapproved() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_close_early_disapproved::()); + }); + } + + #[test] + fn close_early_approved() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_close_early_approved::()); + }); + } + + #[test] + fn close_disapproved() { + new_test_ext().execute_with(|| { assert_ok!(test_benchmark_close_disapproved::()); + }); + } + + #[test] + fn close_approved() { + new_test_ext().execute_with(|| { assert_ok!(test_benchmark_close_approved::()); }); } diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 662465616ed1bec6c55ecff56e5e0a664ac519c2..3192ef0fc1c5591ff909977e93a99d88232e412a 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -1,24 +1,27 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Collective system: Members of a set of account IDs can make their collective feelings known //! through dispatched calls from one of two specialized origins. //! //! The membership can be provided in one of two ways: either directly, using the Root-dispatchable //! function `set_members`, or indirectly, through implementing the `ChangeMembers`. +//! The pallet assumes that the amount of members stays at or below `MAX_MEMBERS` for its weight +//! calculations, but enforces this neither in `set_members` nor in `change_members_sorted`. //! //! A "prime" member may be set allowing their vote to act as the default vote in case of any //! abstentions after the voting period. @@ -38,13 +41,19 @@ use sp_std::{prelude::*, result}; use sp_core::u32_trait::Value as U32; -use sp_runtime::RuntimeDebug; -use sp_runtime::traits::Hash; +use sp_io::storage; +use sp_runtime::{RuntimeDebug, traits::Hash}; + use frame_support::{ - dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, - traits::{Get, ChangeMembers, InitializeMembers, EnsureOrigin}, decl_module, decl_event, - decl_storage, decl_error, ensure, - weights::DispatchClass, + codec::{Decode, Encode}, + debug, decl_error, decl_event, decl_module, decl_storage, + dispatch::{ + DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable, Parameter, + PostDispatchInfo, + }, + ensure, + traits::{ChangeMembers, EnsureOrigin, Get, InitializeMembers}, + weights::{DispatchClass, GetDispatchInfo, Weight}, }; use frame_system::{self as system, ensure_signed, ensure_root}; @@ -60,18 +69,31 @@ pub type ProposalIndex = u32; /// vote exactly once, therefore also the number of votes for any given motion. pub type MemberCount = u32; +/// The maximum number of members supported by the pallet. Used for weight estimation. +/// +/// NOTE: +/// + Benchmarks will need to be re-run and weights adjusted if this changes. +/// + This pallet assumes that dependents keep to the limit without enforcing it. +pub const MAX_MEMBERS: MemberCount = 100; + pub trait Trait: frame_system::Trait { /// The outer origin type. type Origin: From>; /// The outer call dispatch type. - type Proposal: Parameter + Dispatchable>::Origin> + From>; + type Proposal: Parameter + + Dispatchable>::Origin, PostInfo=PostDispatchInfo> + + From> + + GetDispatchInfo; /// The outer event type. type Event: From> + Into<::Event>; /// The time-out for council motions. type MotionDuration: Get; + + /// Maximum number of proposals allowed to be active in parallel. + type MaxProposals: Get; } /// Origin for the collective module. @@ -144,9 +166,9 @@ decl_event! { /// A motion was not approved by the required threshold. Disapproved(Hash), /// A motion was executed; `bool` is true if returned without error. - Executed(Hash, bool), + Executed(Hash, DispatchResult), /// A single member did some action; `bool` is true if returned without error. - MemberExecuted(Hash, bool), + MemberExecuted(Hash, DispatchResult), /// A proposal was closed after its duration was up. Closed(Hash, MemberCount, MemberCount), } @@ -168,12 +190,152 @@ decl_error! { AlreadyInitialized, /// The close call is made too early, before the end of the voting. TooEarly, + /// There can only be a maximum of `MaxProposals` active proposals. + TooManyProposals, + /// The given weight bound for the proposal was too low. + WrongProposalWeight, + /// The given length bound for the proposal was too low. + WrongProposalLength, } } -// Note: this module is not benchmarked. The weights are obtained based on the similarity of the -// executed logic with other democracy function. Note that councillor operations are assigned to the -// operational class. +/// Functions for calcuating the weight of dispatchables. +mod weight_for { + use frame_support::{traits::Get, weights::Weight}; + use super::{Trait, Instance}; + + /// Calculate the weight for `set_members`. + /// + /// Based on benchmark: + /// 0 + M * 20.47 + N * 0.109 + P * 26.29 µs (min squares analysis) + /// + /// Note: The complexity of `set_members` is quadratic (`O(MP + N)`), so the linear approximation + /// of the benchmark is not always permissible. It is here, though, because the linear approximation + /// covered the range of possible values and we estimate weight via the worst case (max paramter + /// values) before execution so we can be sure that we are only overestimating. + pub(crate) fn set_members, I: Instance>( + old_count: Weight, + new_count: Weight, + proposals: Weight, + ) -> Weight { + let db = T::DbWeight::get(); + db.reads_writes(1, 1) // mutate `Members` + .saturating_add(db.writes(1)) // set `Prime` + .saturating_add(db.reads(1)) // read `Proposals` + .saturating_add(db.reads_writes(proposals, proposals)) // update votes (`Voting`) + .saturating_add(old_count.saturating_mul(21_000_000)) // M + .saturating_add(new_count.saturating_mul(110_000)) // N + .saturating_add(proposals.saturating_mul(27_000_000)) // P + } + + /// Calculate the weight for `execute`. + /// + /// Based on benchmark: + /// 22.62 + M * 0.115 + B * 0.003 µs (min squares analysis) + pub(crate) fn execute, I: Instance>( + members: Weight, + proposal: Weight, + length: Weight, + ) -> Weight { + T::DbWeight::get().reads(1) // read members for `is_member` + .saturating_add(23_000_000) // constant + .saturating_add(length.saturating_mul(4_000)) // B + .saturating_add(members.saturating_mul(120_000)) // M + .saturating_add(proposal) // P + } + + /// Calculate the weight for `propose` if the proposal is executed straight away (`threshold < 2`). + /// + /// Based on benchmark: + /// 28.12 + M * 0.218 + B * 0.003 µs (min squares analysis) + pub(crate) fn propose_execute, I: Instance>( + members: Weight, + proposal: Weight, + length: Weight, + ) -> Weight { + T::DbWeight::get().reads(2) // `is_member` + `contains_key` + .saturating_add(29_000_000) // constant + .saturating_add(length.saturating_mul(3_000)) // B + .saturating_add(members.saturating_mul(220_000)) // M + .saturating_add(proposal) // P1 + } + + /// Calculate the weight for `propose` if the proposal is put up for a vote (`threshold >= 2`). + /// + /// Based on benchmark: + /// 49.75 + M * 0.105 + P2 0.502 + B * 0.006 µs (min squares analysis) + pub(crate) fn propose_proposed, I: Instance>( + members: Weight, + proposals: Weight, + length: Weight, + ) -> Weight { + T::DbWeight::get().reads(2) // `is_member` + `contains_key` + .saturating_add(T::DbWeight::get().reads_writes(2, 4)) // `proposal` insertion + .saturating_add(50_000_000) // constant + .saturating_add(length.saturating_mul(6_000)) // B + .saturating_add(members.saturating_mul(110_000)) // M + .saturating_add(proposals.saturating_mul(510_000)) // P2 + } + + /// Calculate the weight for `vote`. + /// + /// Based on benchmark: + /// 24.03 + M * 0.349 + P * 0.119 + B * 0.003 µs (min squares analysis) + pub(crate) fn vote, I: Instance>( + members: Weight, + ) -> Weight { + T::DbWeight::get().reads(1) // read `Members` + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) // mutate `Voting` + .saturating_add(30_000_000) // constant + .saturating_add(members.saturating_mul(500_000)) // M + } + + /// Calculate the weight for `close`. + /// + /// Based on benchmarks: + /// - early disapproved: 37.21 + M * 0.239 + P2 * 0.466 + B * 0.002 µs (min squares analysis) + /// - early approved: 50.82 + M * 0.211 + P2 * 0.478 + B * 0.008 µs (min squares analysis) + /// - disapproved: 51.08 + M * 0.224 + P2 * 0.475 + B * 0.003 µs (min squares analysis) + /// - approved: 65.95 + M * 0.226 + P2 * 0.487 + B * 0.005 µs (min squares analysis) + pub(crate) fn close, I: Instance>( + members: Weight, + proposal_weight: Weight, + proposals: Weight, + length: Weight, + ) -> Weight { + let db = T::DbWeight::get(); + close_without_finalize::(members, length) + .saturating_add(db.reads(1)) // `Prime` + .saturating_add(db.writes(1)) // `Proposals` + .saturating_add(db.writes(1)) // `Voting` + .saturating_add(proposal_weight) // P1 + .saturating_add(proposals.saturating_mul(490_000)) // P2 + } + + /// Calculate the weight for `close` without the call to `approve/disapprove_proposal`. + pub(crate) fn close_without_finalize, I: Instance>( + members: Weight, + length: Weight, + ) -> Weight { + T::DbWeight::get().reads(3) // `Members`, `Voting`, `ProposalOf` + .saturating_add(66_000_000) // constant + .saturating_add(length.saturating_mul(8_000)) // B + .saturating_add(members.saturating_mul(250_000)) // M + } +} + +/// Return the weight of a dispatch call result as an `Option`. +/// +/// Will return the weight regardless of what the state of the result is. +fn get_result_weight(result: DispatchResultWithPostInfo) -> Option { + match result { + Ok(post_info) => post_info.actual_weight, + Err(err) => err.post_info.actual_weight, + } +} + + +// Note that councillor operations are assigned to the operational class. decl_module! { pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { type Error = Error; @@ -182,72 +344,231 @@ decl_module! { /// Set the collective's membership. /// - /// - `new_members`: The new member list. Be nice to the chain and - // provide it sorted. + /// - `new_members`: The new member list. Be nice to the chain and provide it sorted. /// - `prime`: The prime member whose vote sets the default. + /// - `old_count`: The upper bound for the previous number of members in storage. + /// Used for weight estimation. /// /// Requires root origin. - #[weight = (100_000_000, DispatchClass::Operational)] - fn set_members(origin, new_members: Vec, prime: Option) { + /// + /// NOTE: Does not enforce the expected `MAX_MEMBERS` limit on the amount of members, but + /// the weight estimations rely on it to estimate dispatchable weight. + /// + /// # + /// ## Weight + /// - `O(MP + N)` where: + /// - `M` old-members-count (code- and governance-bounded) + /// - `N` new-members-count (code- and governance-bounded) + /// - `P` proposals-count (code-bounded) + /// - DB: + /// - 1 storage mutation (codec `O(M)` read, `O(N)` write) for reading and writing the members + /// - 1 storage read (codec `O(P)`) for reading the proposals + /// - `P` storage mutations (codec `O(M)`) for updating the votes for each proposal + /// - 1 storage write (codec `O(1)`) for deleting the old `prime` and setting the new one + /// # + #[weight = ( + weight_for::set_members::( + (*old_count).into(), // M + new_members.len() as Weight, // N + T::MaxProposals::get().into(), // P + ), + DispatchClass::Operational + )] + fn set_members(origin, + new_members: Vec, + prime: Option, + old_count: MemberCount, + ) -> DispatchResultWithPostInfo { ensure_root(origin)?; + if new_members.len() > MAX_MEMBERS as usize { + debug::error!( + "New members count exceeds maximum amount of members expected. (expected: {}, actual: {})", + MAX_MEMBERS, + new_members.len() + ); + } + + let old = Members::::get(); + if old.len() > old_count as usize { + debug::warn!( + "Wrong count used to estimate set_members weight. (expected: {}, actual: {})", + old_count, + old.len() + ); + } let mut new_members = new_members; new_members.sort(); - let old = Members::::get(); - >::set_members_sorted(&new_members[..], &old); + >::set_members_sorted(&new_members, &old); Prime::::set(prime); + + Ok(Some(weight_for::set_members::( + old.len() as Weight, // M + new_members.len() as Weight, // N + T::MaxProposals::get().into(), // P + )).into()) } /// Dispatch a proposal from a member using the `Member` origin. /// /// Origin must be a member of the collective. - #[weight = (100_000_000, DispatchClass::Operational)] - fn execute(origin, proposal: Box<>::Proposal>) { + /// + /// # + /// ## Weight + /// - `O(M + P)` where `M` members-count (code-bounded) and `P` complexity of dispatching `proposal` + /// - DB: 1 read (codec `O(M)`) + DB access of `proposal` + /// - 1 event + /// # + #[weight = ( + weight_for::execute::( + MAX_MEMBERS.into(), + proposal.get_dispatch_info().weight, + *length_bound as Weight, + ), + DispatchClass::Operational + )] + fn execute(origin, + proposal: Box<>::Proposal>, + #[compact] length_bound: u32, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), Error::::NotMember); + let members = Self::members(); + ensure!(members.contains(&who), Error::::NotMember); + let proposal_len = proposal.using_encoded(|x| x.len()); + ensure!(proposal_len <= length_bound as usize, Error::::WrongProposalLength); let proposal_hash = T::Hashing::hash_of(&proposal); - let ok = proposal.dispatch(RawOrigin::Member(who).into()).is_ok(); - Self::deposit_event(RawEvent::MemberExecuted(proposal_hash, ok)); + let result = proposal.dispatch(RawOrigin::Member(who).into()); + Self::deposit_event( + RawEvent::MemberExecuted(proposal_hash, result.map(|_| ()).map_err(|e| e.error)) + ); + + Ok(get_result_weight(result).map(|w| weight_for::execute::( + members.len() as Weight, + w, + proposal_len as Weight + )).into()) } + /// Add a new proposal to either be voted on or executed directly. + /// + /// Requires the sender to be member. + /// + /// `threshold` determines whether `proposal` is executed directly (`threshold < 2`) + /// or put up for voting. + /// /// # - /// - Bounded storage reads and writes. - /// - Argument `threshold` has bearing on weight. + /// ## Weight + /// - `O(B + M + P1)` or `O(B + M + P2)` where: + /// - `B` is `proposal` size in bytes (length-fee-bounded) + /// - `M` is members-count (code- and governance-bounded) + /// - branching is influenced by `threshold` where: + /// - `P1` is proposal execution complexity (`threshold < 2`) + /// - `P2` is proposals-count (code-bounded) (`threshold >= 2`) + /// - DB: + /// - 1 storage read `is_member` (codec `O(M)`) + /// - 1 storage read `ProposalOf::contains_key` (codec `O(1)`) + /// - DB accesses influenced by `threshold`: + /// - EITHER storage accesses done by `proposal` (`threshold < 2`) + /// - OR proposal insertion (`threshold <= 2`) + /// - 1 storage mutation `Proposals` (codec `O(P2)`) + /// - 1 storage mutation `ProposalCount` (codec `O(1)`) + /// - 1 storage write `ProposalOf` (codec `O(B)`) + /// - 1 storage write `Voting` (codec `O(M)`) + /// - 1 event /// # - #[weight = (5_000_000_000, DispatchClass::Operational)] - fn propose(origin, #[compact] threshold: MemberCount, proposal: Box<>::Proposal>) { + #[weight = ( + if *threshold < 2 { + weight_for::propose_execute::( + MAX_MEMBERS.into(), // M + proposal.get_dispatch_info().weight, // P1 + *length_bound as Weight, // B + ) + } else { + weight_for::propose_proposed::( + MAX_MEMBERS.into(), // M + T::MaxProposals::get().into(), // P2 + *length_bound as Weight, // B + ) + }, + DispatchClass::Operational + )] + fn propose(origin, + #[compact] threshold: MemberCount, + proposal: Box<>::Proposal>, + #[compact] length_bound: u32 + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), Error::::NotMember); + let members = Self::members(); + ensure!(members.contains(&who), Error::::NotMember); + let proposal_len = proposal.using_encoded(|x| x.len()); + ensure!(proposal_len <= length_bound as usize, Error::::WrongProposalLength); let proposal_hash = T::Hashing::hash_of(&proposal); - ensure!(!>::contains_key(proposal_hash), Error::::DuplicateProposal); if threshold < 2 { let seats = Self::members().len() as MemberCount; - let ok = proposal.dispatch(RawOrigin::Members(1, seats).into()).is_ok(); - Self::deposit_event(RawEvent::Executed(proposal_hash, ok)); + let result = proposal.dispatch(RawOrigin::Members(1, seats).into()); + Self::deposit_event( + RawEvent::Executed(proposal_hash, result.map(|_| ()).map_err(|e| e.error)) + ); + + Ok(get_result_weight(result).map(|w| weight_for::propose_execute::( + members.len() as Weight, // M + w, // P1 + proposal_len as Weight, // B + )).into()) } else { + let active_proposals = + >::try_mutate(|proposals| -> Result { + proposals.push(proposal_hash); + ensure!( + proposals.len() <= T::MaxProposals::get() as usize, + Error::::TooManyProposals + ); + Ok(proposals.len()) + })?; let index = Self::proposal_count(); >::mutate(|i| *i += 1); - >::mutate(|proposals| proposals.push(proposal_hash)); >::insert(proposal_hash, *proposal); let end = system::Module::::block_number() + T::MotionDuration::get(); let votes = Votes { index, threshold, ayes: vec![who.clone()], nays: vec![], end }; >::insert(proposal_hash, votes); Self::deposit_event(RawEvent::Proposed(who, index, proposal_hash, threshold)); + + Ok(Some(weight_for::propose_proposed::( + members.len() as Weight, // M + active_proposals as Weight, // P2 + proposal_len as Weight, // B + )).into()) } } + /// Add an aye or nay vote for the sender to the given proposal. + /// + /// Requires the sender to be a member. + /// /// # - /// - Bounded storage read and writes. - /// - Will be slightly heavier if the proposal is approved / disapproved after the vote. + /// ## Weight + /// - `O(M)` where `M` is members-count (code- and governance-bounded) + /// - DB: + /// - 1 storage read `Members` (codec `O(M)`) + /// - 1 storage mutation `Voting` (codec `O(M)`) + /// - 1 event /// # - #[weight = (200_000_000, DispatchClass::Operational)] - fn vote(origin, proposal: T::Hash, #[compact] index: ProposalIndex, approve: bool) { + #[weight = ( + weight_for::vote::(MAX_MEMBERS.into()), + DispatchClass::Operational + )] + fn vote(origin, + proposal: T::Hash, + #[compact] index: ProposalIndex, + approve: bool, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), Error::::NotMember); + let members = Self::members(); + ensure!(members.contains(&who), Error::::NotMember); let mut voting = Self::voting(&proposal).ok_or(Error::::ProposalMissing)?; ensure!(voting.index == index, Error::::WrongIndex); @@ -279,64 +600,175 @@ decl_module! { let no_votes = voting.nays.len() as MemberCount; Self::deposit_event(RawEvent::Voted(who, proposal, approve, yes_votes, no_votes)); - let seats = Self::members().len() as MemberCount; + Voting::::insert(&proposal, voting); - let approved = yes_votes >= voting.threshold; - let disapproved = seats.saturating_sub(no_votes) < voting.threshold; - if approved || disapproved { - Self::finalize_proposal(approved, seats, voting, proposal); - } else { - Voting::::insert(&proposal, voting); - } + Ok(Some(weight_for::vote::(members.len() as Weight)).into()) } - /// May be called by any signed account after the voting duration has ended in order to - /// finish voting and close the proposal. + /// Close a vote that is either approved, disapproved or whose voting period has ended. + /// + /// May be called by any signed account in order to finish voting and close the proposal. /// - /// Abstentions are counted as rejections unless there is a prime member set and the prime - /// member cast an approval. + /// If called before the end of the voting period it will only close the vote if it is + /// has enough votes to be approved or disapproved. /// - /// - the weight of `proposal` preimage. - /// - up to three events deposited. - /// - one read, two removals, one mutation. (plus three static reads.) - /// - computation and i/o `O(P + L + M)` where: - /// - `M` is number of members, - /// - `P` is number of active proposals, - /// - `L` is the encoded length of `proposal` preimage. - #[weight = (200_000_000, DispatchClass::Operational)] - fn close(origin, proposal: T::Hash, #[compact] index: ProposalIndex) { + /// If called after the end of the voting period abstentions are counted as rejections + /// unless there is a prime member set and the prime member cast an approval. + /// + /// + `proposal_weight_bound`: The maximum amount of weight consumed by executing the closed proposal. + /// + `length_bound`: The upper bound for the length of the proposal in storage. Checked via + /// `storage::read` so it is `size_of::() == 4` larger than the pure length. + /// + /// # + /// ## Weight + /// - `O(B + M + P1 + P2)` where: + /// - `B` is `proposal` size in bytes (length-fee-bounded) + /// - `M` is members-count (code- and governance-bounded) + /// - `P1` is the complexity of `proposal` preimage. + /// - `P2` is proposal-count (code-bounded) + /// - DB: + /// - 2 storage reads (`Members`: codec `O(M)`, `Prime`: codec `O(1)`) + /// - 3 mutations (`Voting`: codec `O(M)`, `ProposalOf`: codec `O(B)`, `Proposals`: codec `O(P2)`) + /// - any mutations done while executing `proposal` (`P1`) + /// - up to 3 events + /// # + #[weight = ( + weight_for::close::( + MAX_MEMBERS.into(), // `M` + *proposal_weight_bound, // `P1` + T::MaxProposals::get().into(), // `P2` + *length_bound as Weight, // B + ), + DispatchClass::Operational + )] + fn close(origin, + proposal_hash: T::Hash, + #[compact] index: ProposalIndex, + #[compact] proposal_weight_bound: Weight, + #[compact] length_bound: u32 + ) -> DispatchResultWithPostInfo { let _ = ensure_signed(origin)?; - let voting = Self::voting(&proposal).ok_or(Error::::ProposalMissing)?; + let voting = Self::voting(&proposal_hash).ok_or(Error::::ProposalMissing)?; ensure!(voting.index == index, Error::::WrongIndex); - ensure!(system::Module::::block_number() >= voting.end, Error::::TooEarly); - - // default to true only if there's a prime and they voted in favour. - let default = Self::prime().map_or( - false, - |who| voting.ayes.iter().any(|a| a == &who), - ); let mut no_votes = voting.nays.len() as MemberCount; let mut yes_votes = voting.ayes.len() as MemberCount; let seats = Self::members().len() as MemberCount; + let approved = yes_votes >= voting.threshold; + let disapproved = seats.saturating_sub(no_votes) < voting.threshold; + // Allow (dis-)approving the proposal as soon as there are enough votes. + if approved { + let (proposal, len) = Self::validate_and_get_proposal( + &proposal_hash, + length_bound, + proposal_weight_bound + )?; + Self::deposit_event(RawEvent::Closed(proposal_hash, yes_votes, no_votes)); + let approve_weight = Self::do_approve_proposal(seats, voting, proposal_hash, proposal); + return Ok(Some( + weight_for::close_without_finalize::(seats.into(), len as Weight) + .saturating_add(approve_weight) + ).into()); + } else if disapproved { + Self::deposit_event(RawEvent::Closed(proposal_hash, yes_votes, no_votes)); + let disapprove_weight = Self::do_disapprove_proposal(proposal_hash); + return Ok(Some( + weight_for::close_without_finalize::(seats.into(), 0) + .saturating_add(disapprove_weight) + ).into()); + } + + // Only allow actual closing of the proposal after the voting period has ended. + ensure!(system::Module::::block_number() >= voting.end, Error::::TooEarly); + + // default to true only if there's a prime and they voted in favour. + let default = Self::prime().map_or(false, |who| voting.ayes.iter().any(|a| a == &who)); + let abstentions = seats - (yes_votes + no_votes); match default { true => yes_votes += abstentions, false => no_votes += abstentions, } + let approved = yes_votes >= voting.threshold; + + if approved { + let (proposal, len) = Self::validate_and_get_proposal( + &proposal_hash, + length_bound, + proposal_weight_bound + )?; + Self::deposit_event(RawEvent::Closed(proposal_hash, yes_votes, no_votes)); + let approve_weight = Self::do_approve_proposal(seats, voting, proposal_hash, proposal); + return Ok(Some( + weight_for::close_without_finalize::(seats.into(), len as Weight) + .saturating_add(T::DbWeight::get().reads(1)) // read `Prime` + .saturating_add(approve_weight) + ).into()); + } else { + Self::deposit_event(RawEvent::Closed(proposal_hash, yes_votes, no_votes)); + let disapprove_weight = Self::do_disapprove_proposal(proposal_hash); + return Ok(Some( + weight_for::close_without_finalize::(seats.into(), 0) + .saturating_add(T::DbWeight::get().reads(1)) // read `Prime` + .saturating_add(disapprove_weight) + ).into()); + } + } - Self::deposit_event(RawEvent::Closed(proposal, yes_votes, no_votes)); - Self::finalize_proposal(yes_votes >= voting.threshold, seats, voting, proposal); + /// Disapprove a proposal, close, and remove it from the system, regardless of its current state. + /// + /// Must be called by the Root origin. + /// + /// Parameters: + /// * `proposal_hash`: The hash of the proposal that should be disapproved. + /// + /// # + /// Complexity: O(P) where P is the number of max proposals + /// Base Weight: .49 * P + /// DB Weight: + /// * Reads: Proposals + /// * Writes: Voting, Proposals, ProposalOf + /// # + #[weight = T::DbWeight::get().reads_writes(1, 3) // `Voting`, `Proposals`, `ProposalOf` + .saturating_add(490_000 * Weight::from(T::MaxProposals::get())) // P2 + ] + fn disapprove_proposal(origin, proposal_hash: T::Hash) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + let actual_weight = Self::do_disapprove_proposal(proposal_hash); + Ok(Some(actual_weight).into()) } } } impl, I: Instance> Module { + /// Check whether `who` is a member of the collective. pub fn is_member(who: &T::AccountId) -> bool { + // Note: The dispatchables *do not* use this to check membership so make sure + // to update those if this is changed. Self::members().contains(who) } + /// Ensure that the right proposal bounds were passed and get the proposal from storage. + /// + /// Checks the length in storage via `storage::read` which adds an extra `size_of::() == 4` + /// to the length. + fn validate_and_get_proposal( + hash: &T::Hash, + length_bound: u32, + weight_bound: Weight + ) -> Result<(>::Proposal, usize), DispatchError> { + let key = ProposalOf::::hashed_key_for(hash); + // read the length of the proposal storage entry directly + let proposal_len = storage::read(&key, &mut [0; 0], 0) + .ok_or(Error::::ProposalMissing)?; + ensure!(proposal_len <= length_bound, Error::::WrongProposalLength); + let proposal = ProposalOf::::get(hash).ok_or(Error::::ProposalMissing)?; + let proposal_weight = proposal.get_dispatch_info().weight; + ensure!(proposal_weight <= weight_bound, Error::::WrongProposalWeight); + Ok((proposal, proposal_len as usize)) + } + /// Weight: /// If `approved`: /// - the weight of `proposal` preimage. @@ -351,39 +783,80 @@ impl, I: Instance> Module { /// Two removals, one mutation. /// Computation and i/o `O(P)` where: /// - `P` is number of active proposals - fn finalize_proposal( - approved: bool, + fn do_approve_proposal( seats: MemberCount, voting: Votes, - proposal: T::Hash, - ) { - if approved { - Self::deposit_event(RawEvent::Approved(proposal)); - - // execute motion, assuming it exists. - if let Some(p) = ProposalOf::::take(&proposal) { - let origin = RawOrigin::Members(voting.threshold, seats).into(); - let ok = p.dispatch(origin).is_ok(); - Self::deposit_event(RawEvent::Executed(proposal, ok)); - } - } else { - // disapproved - ProposalOf::::remove(&proposal); - Self::deposit_event(RawEvent::Disapproved(proposal)); - } + proposal_hash: T::Hash, + proposal: >::Proposal, + ) -> Weight { + let mut weight: Weight = 0; + Self::deposit_event(RawEvent::Approved(proposal_hash)); + + let dispatch_weight = proposal.get_dispatch_info().weight; + let origin = RawOrigin::Members(voting.threshold, seats).into(); + let result = proposal.dispatch(origin); + Self::deposit_event( + RawEvent::Executed(proposal_hash, result.map(|_| ()).map_err(|e| e.error)) + ); + weight = weight.saturating_add( + // default to the dispatch info weight for safety + get_result_weight(result).unwrap_or(dispatch_weight) // P1 + ); + + let remove_proposal_weight = Self::remove_proposal(proposal_hash); + weight.saturating_add(remove_proposal_weight) + } + + fn do_disapprove_proposal(proposal_hash: T::Hash) -> Weight { + // disapproved + Self::deposit_event(RawEvent::Disapproved(proposal_hash)); + Self::remove_proposal(proposal_hash) + } - // remove vote - Voting::::remove(&proposal); - Proposals::::mutate(|proposals| proposals.retain(|h| h != &proposal)); + // Removes a proposal from the pallet, cleaning up votes and the vector of proposals. + fn remove_proposal(proposal_hash: T::Hash) -> Weight { + // remove proposal and vote + ProposalOf::::remove(&proposal_hash); + Voting::::remove(&proposal_hash); + let num_proposals = Proposals::::mutate(|proposals| { + proposals.retain(|h| h != &proposal_hash); + proposals.len() + 1 // calculate weight based on original length + }); + T::DbWeight::get().reads_writes(1, 3) // `Voting`, `Proposals`, `ProposalOf` + .saturating_add(490_000 * num_proposals as Weight) // P2 } } impl, I: Instance> ChangeMembers for Module { + /// Update the members of the collective. Votes are updated and the prime is reset. + /// + /// NOTE: Does not enforce the expected `MAX_MEMBERS` limit on the amount of members, but + /// the weight estimations rely on it to estimate dispatchable weight. + /// + /// # + /// ## Weight + /// - `O(MP + N)` + /// - where `M` old-members-count (governance-bounded) + /// - where `N` new-members-count (governance-bounded) + /// - where `P` proposals-count + /// - DB: + /// - 1 storage read (codec `O(P)`) for reading the proposals + /// - `P` storage mutations for updating the votes (codec `O(M)`) + /// - 1 storage write (codec `O(N)`) for storing the new members + /// - 1 storage write (codec `O(1)`) for deleting the old prime + /// # fn change_members_sorted( _incoming: &[T::AccountId], outgoing: &[T::AccountId], new: &[T::AccountId], ) { + if new.len() > MAX_MEMBERS as usize { + debug::error!( + "New members count exceeds maximum amount of members expected. (expected: {}, actual: {})", + MAX_MEMBERS, + new.len() + ); + } // remove accounts from all current voting in motions. let mut outgoing = outgoing.to_vec(); outgoing.sort_unstable(); @@ -539,6 +1012,7 @@ mod tests { pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const MotionDuration: u64 = 3; + pub const MaxProposals: u32 = 100; } impl frame_system::Trait for Test { type Origin = Origin; @@ -556,6 +1030,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -569,12 +1044,14 @@ mod tests { type Proposal = Call; type Event = Event; type MotionDuration = MotionDuration; + type MaxProposals = MaxProposals; } impl Trait for Test { type Origin = Origin; type Proposal = Call; type Event = Event; type MotionDuration = MotionDuration; + type MaxProposals = MaxProposals; } pub type Block = sp_runtime::generic::Block; @@ -620,19 +1097,21 @@ mod tests { fn close_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); System::set_block_number(3); assert_noop!( - Collective::close(Origin::signed(4), hash.clone(), 0), + Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len), Error::::TooEarly ); System::set_block_number(4); - assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0)); + assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len)); let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; assert_eq!(System::events(), vec![ @@ -644,18 +1123,57 @@ mod tests { }); } + #[test] + fn proposal_weight_limit_works_on_approve() { + new_test_ext().execute_with(|| { + let proposal = Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MAX_MEMBERS)); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; + let hash = BlakeTwo256::hash_of(&proposal); + // Set 1 as prime voter + Prime::::set(Some(1)); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); + // With 1's prime vote, this should pass + System::set_block_number(4); + assert_noop!( + Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight - 100, proposal_len), + Error::::WrongProposalWeight + ); + assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len)); + }) + } + + #[test] + fn proposal_weight_limit_ignored_on_disapprove() { + new_test_ext().execute_with(|| { + let proposal = Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MAX_MEMBERS)); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; + let hash = BlakeTwo256::hash_of(&proposal); + + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); + // No votes, this proposal wont pass + System::set_block_number(4); + assert_ok!( + Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight - 100, proposal_len) + ); + }) + } + #[test] fn close_with_prime_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::set_members(Origin::ROOT, vec![1, 2, 3], Some(3))); + assert_ok!(Collective::set_members(Origin::ROOT, vec![1, 2, 3], Some(3), MAX_MEMBERS)); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); System::set_block_number(4); - assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0)); + assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len)); let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; assert_eq!(System::events(), vec![ @@ -671,14 +1189,16 @@ mod tests { fn close_with_voting_prime_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::set_members(Origin::ROOT, vec![1, 2, 3], Some(1))); + assert_ok!(Collective::set_members(Origin::ROOT, vec![1, 2, 3], Some(1), MAX_MEMBERS)); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); System::set_block_number(4); - assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0)); + assert_ok!(Collective::close(Origin::signed(4), hash.clone(), 0, proposal_weight, proposal_len)); let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; assert_eq!(System::events(), vec![ @@ -686,7 +1206,7 @@ mod tests { record(Event::collective_Instance1(RawEvent::Voted(2, hash.clone(), true, 2, 0))), record(Event::collective_Instance1(RawEvent::Closed(hash.clone(), 3, 0))), record(Event::collective_Instance1(RawEvent::Approved(hash.clone()))), - record(Event::collective_Instance1(RawEvent::Executed(hash.clone(), false))) + record(Event::collective_Instance1(RawEvent::Executed(hash.clone(), Err(DispatchError::BadOrigin)))) ]); }); } @@ -695,9 +1215,10 @@ mod tests { fn removal_of_old_voters_votes_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = BlakeTwo256::hash_of(&proposal); let end = 4; - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); assert_eq!( Collective::voting(&hash), @@ -710,8 +1231,9 @@ mod tests { ); let proposal = make_proposal(69); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(3), hash.clone(), 1, false)); assert_eq!( Collective::voting(&hash), @@ -729,29 +1251,31 @@ mod tests { fn removal_of_old_voters_votes_works_with_set_members() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = BlakeTwo256::hash_of(&proposal); let end = 4; - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![], end }) ); - assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 3, 4], None)); + assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 3, 4], None, MAX_MEMBERS)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![], end }) ); let proposal = make_proposal(69); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(3), hash.clone(), 1, false)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3], end }) ); - assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 4], None)); + assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 4], None, MAX_MEMBERS)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![], end }) @@ -763,9 +1287,10 @@ mod tests { fn propose_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash = proposal.blake2_256().into(); let end = 4; - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_eq!(Collective::proposals(), vec![hash]); assert_eq!(Collective::proposal_of(&hash), Some(proposal)); assert_eq!( @@ -788,12 +1313,59 @@ mod tests { }); } + #[test] + fn limit_active_proposals() { + new_test_ext().execute_with(|| { + for i in 0..MaxProposals::get() { + let proposal = make_proposal(i as u64); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); + } + let proposal = make_proposal(MaxProposals::get() as u64 + 1); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + assert_noop!( + Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len), + Error::::TooManyProposals + ); + }) + } + + #[test] + fn correct_validate_and_get_proposal() { + new_test_ext().execute_with(|| { + let proposal = Call::Collective(crate::Call::set_members(vec![1, 2, 3], None, MAX_MEMBERS)); + let length = proposal.encode().len() as u32; + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), length)); + + let hash = BlakeTwo256::hash_of(&proposal); + let weight = proposal.get_dispatch_info().weight; + assert_noop!( + Collective::validate_and_get_proposal(&BlakeTwo256::hash_of(&vec![3; 4]), length, weight), + Error::::ProposalMissing + ); + assert_noop!( + Collective::validate_and_get_proposal(&hash, length - 2, weight), + Error::::WrongProposalLength + ); + assert_noop!( + Collective::validate_and_get_proposal(&hash, length, weight - 10), + Error::::WrongProposalWeight + ); + let res = Collective::validate_and_get_proposal(&hash, length, weight); + assert_ok!(res.clone()); + let (retrieved_proposal, len) = res.unwrap(); + assert_eq!(length as usize, len); + assert_eq!(proposal, retrieved_proposal); + }) + } + #[test] fn motions_ignoring_non_collective_proposals_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); assert_noop!( - Collective::propose(Origin::signed(42), 3, Box::new(proposal.clone())), + Collective::propose(Origin::signed(42), 3, Box::new(proposal.clone()), proposal_len), Error::::NotMember ); }); @@ -803,8 +1375,9 @@ mod tests { fn motions_ignoring_non_collective_votes_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_noop!( Collective::vote(Origin::signed(42), hash.clone(), 0, true), Error::::NotMember, @@ -817,8 +1390,9 @@ mod tests { new_test_ext().execute_with(|| { System::set_block_number(3); let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_noop!( Collective::vote(Origin::signed(2), hash.clone(), 1, true), Error::::WrongIndex, @@ -830,9 +1404,10 @@ mod tests { fn motions_revoting_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let hash: H256 = proposal.blake2_256().into(); let end = 4; - assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 0, threshold: 2, ayes: vec![1], nays: vec![], end }) @@ -881,11 +1456,14 @@ mod tests { fn motions_reproposing_disapproved_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); + assert_ok!(Collective::close(Origin::signed(2), hash.clone(), 0, proposal_weight, proposal_len)); assert_eq!(Collective::proposals(), vec![]); - assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); assert_eq!(Collective::proposals(), vec![hash]); }); } @@ -894,9 +1472,12 @@ mod tests { fn motions_disapproval_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); + assert_ok!(Collective::close(Origin::signed(2), hash.clone(), 0, proposal_weight, proposal_len)); assert_eq!(System::events(), vec![ EventRecord { @@ -921,6 +1502,13 @@ mod tests { )), topics: vec![], }, + EventRecord { + phase: Phase::Initialization, + event: Event::collective_Instance1(RawEvent::Closed( + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), 1, 1, + )), + topics: vec![], + }, EventRecord { phase: Phase::Initialization, event: Event::collective_Instance1(RawEvent::Disapproved( @@ -936,9 +1524,12 @@ mod tests { fn motions_approval_works() { new_test_ext().execute_with(|| { let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let proposal_weight = proposal.get_dispatch_info().weight; let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + assert_ok!(Collective::close(Origin::signed(2), hash.clone(), 0, proposal_weight, proposal_len)); assert_eq!(System::events(), vec![ EventRecord { @@ -962,6 +1553,13 @@ mod tests { )), topics: vec![], }, + EventRecord { + phase: Phase::Initialization, + event: Event::collective_Instance1(RawEvent::Closed( + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), 2, 0, + )), + topics: vec![], + }, EventRecord { phase: Phase::Initialization, event: Event::collective_Instance1(RawEvent::Approved( @@ -973,11 +1571,60 @@ mod tests { phase: Phase::Initialization, event: Event::collective_Instance1(RawEvent::Executed( hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - false, + Err(DispatchError::BadOrigin), )), topics: vec![], } ]); }); } + + #[test] + fn close_disapprove_does_not_care_about_weight_or_len() { + // This test confirms that if you close a proposal that would be disapproved, + // we do not care about the proposal length or proposal weight since it will + // not be read from storage or executed. + new_test_ext().execute_with(|| { + let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); + // First we make the proposal succeed + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + // It will not close with bad weight/len information + assert_noop!( + Collective::close(Origin::signed(2), hash.clone(), 0, 0, 0), + Error::::WrongProposalLength, + ); + assert_noop!( + Collective::close(Origin::signed(2), hash.clone(), 0, 0, proposal_len), + Error::::WrongProposalWeight, + ); + // Now we make the proposal fail + assert_ok!(Collective::vote(Origin::signed(1), hash.clone(), 0, false)); + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); + // It can close even if the weight/len information is bad + assert_ok!(Collective::close(Origin::signed(2), hash.clone(), 0, 0, 0)); + }) + } + + #[test] + fn disapprove_proposal_works() { + new_test_ext().execute_with(|| { + let proposal = make_proposal(42); + let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()), proposal_len)); + // Proposal would normally succeed + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + // But Root can disapprove and remove it anyway + assert_ok!(Collective::disapprove_proposal(Origin::ROOT, hash.clone())); + let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; + assert_eq!(System::events(), vec![ + record(Event::collective_Instance1(RawEvent::Proposed(1, 0, hash.clone(), 2))), + record(Event::collective_Instance1(RawEvent::Voted(2, hash.clone(), true, 2, 0))), + record(Event::collective_Instance1(RawEvent::Disapproved(hash.clone()))), + ]); + }) + } } diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 4e1128000e33894f218f3f94a42442c255bcada5..656836df374d28e45fd267d05b107a08c62fca9f 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-contracts" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for WASM contracts" @@ -17,23 +17,23 @@ pwasm-utils = { version = "0.12.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } parity-wasm = { version = "0.41.0", default-features = false } wasmi-validation = { version = "0.3.0", default-features = false } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-sandbox = { version = "0.8.0-dev", default-features = false, path = "../../primitives/sandbox" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-contracts-primitives = { version = "2.0.0-dev", default-features = false, path = "common" } -pallet-transaction-payment = { version = "2.0.0-dev", default-features = false, path = "../transaction-payment" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-sandbox = { version = "0.8.0-rc2", default-features = false, path = "../../primitives/sandbox" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-contracts-primitives = { version = "2.0.0-rc2", default-features = false, path = "common" } +pallet-transaction-payment = { version = "2.0.0-rc2", default-features = false, path = "../transaction-payment" } [dev-dependencies] wabt = "0.9.2" assert_matches = "1.3.0" hex-literal = "0.2.1" -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -pallet-timestamp = { version = "2.0.0-dev", path = "../timestamp" } -pallet-randomness-collective-flip = { version = "2.0.0-dev", path = "../randomness-collective-flip" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +pallet-timestamp = { version = "2.0.0-rc2", path = "../timestamp" } +pallet-randomness-collective-flip = { version = "2.0.0-rc2", path = "../randomness-collective-flip" } [features] default = ["std"] diff --git a/frame/contracts/common/Cargo.toml b/frame/contracts/common/Cargo.toml index edf1867be0a7109b968f2645b2b034749fe8a5a3..c358a877347f053417474fb91534296fcbde817a 100644 --- a/frame/contracts/common/Cargo.toml +++ b/frame/contracts/common/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-contracts-primitives" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "A crate that hosts a common definitions that are relevant for the pallet-contracts." @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # This crate should not rely on any of the frame primitives. codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/runtime" } [features] default = ["std"] diff --git a/frame/contracts/tests/caller_contract.wat b/frame/contracts/fixtures/caller_contract.wat similarity index 100% rename from frame/contracts/tests/caller_contract.wat rename to frame/contracts/fixtures/caller_contract.wat diff --git a/frame/contracts/tests/check_default_rent_allowance.wat b/frame/contracts/fixtures/check_default_rent_allowance.wat similarity index 100% rename from frame/contracts/tests/check_default_rent_allowance.wat rename to frame/contracts/fixtures/check_default_rent_allowance.wat diff --git a/frame/contracts/tests/crypto_hashes.wat b/frame/contracts/fixtures/crypto_hashes.wat similarity index 100% rename from frame/contracts/tests/crypto_hashes.wat rename to frame/contracts/fixtures/crypto_hashes.wat diff --git a/frame/contracts/tests/destroy_and_transfer.wat b/frame/contracts/fixtures/destroy_and_transfer.wat similarity index 100% rename from frame/contracts/tests/destroy_and_transfer.wat rename to frame/contracts/fixtures/destroy_and_transfer.wat diff --git a/frame/contracts/tests/dispatch_call.wat b/frame/contracts/fixtures/dispatch_call.wat similarity index 100% rename from frame/contracts/tests/dispatch_call.wat rename to frame/contracts/fixtures/dispatch_call.wat diff --git a/frame/contracts/tests/dispatch_call_then_trap.wat b/frame/contracts/fixtures/dispatch_call_then_trap.wat similarity index 100% rename from frame/contracts/tests/dispatch_call_then_trap.wat rename to frame/contracts/fixtures/dispatch_call_then_trap.wat diff --git a/frame/contracts/tests/drain.wat b/frame/contracts/fixtures/drain.wat similarity index 100% rename from frame/contracts/tests/drain.wat rename to frame/contracts/fixtures/drain.wat diff --git a/frame/contracts/tests/get_runtime_storage.wat b/frame/contracts/fixtures/get_runtime_storage.wat similarity index 100% rename from frame/contracts/tests/get_runtime_storage.wat rename to frame/contracts/fixtures/get_runtime_storage.wat diff --git a/frame/contracts/tests/restoration.wat b/frame/contracts/fixtures/restoration.wat similarity index 100% rename from frame/contracts/tests/restoration.wat rename to frame/contracts/fixtures/restoration.wat diff --git a/frame/contracts/tests/return_from_start_fn.wat b/frame/contracts/fixtures/return_from_start_fn.wat similarity index 100% rename from frame/contracts/tests/return_from_start_fn.wat rename to frame/contracts/fixtures/return_from_start_fn.wat diff --git a/frame/contracts/tests/return_with_data.wat b/frame/contracts/fixtures/return_with_data.wat similarity index 100% rename from frame/contracts/tests/return_with_data.wat rename to frame/contracts/fixtures/return_with_data.wat diff --git a/frame/contracts/tests/run_out_of_gas.wat b/frame/contracts/fixtures/run_out_of_gas.wat similarity index 100% rename from frame/contracts/tests/run_out_of_gas.wat rename to frame/contracts/fixtures/run_out_of_gas.wat diff --git a/frame/contracts/tests/self_destruct.wat b/frame/contracts/fixtures/self_destruct.wat similarity index 100% rename from frame/contracts/tests/self_destruct.wat rename to frame/contracts/fixtures/self_destruct.wat diff --git a/frame/contracts/tests/self_destructing_constructor.wat b/frame/contracts/fixtures/self_destructing_constructor.wat similarity index 100% rename from frame/contracts/tests/self_destructing_constructor.wat rename to frame/contracts/fixtures/self_destructing_constructor.wat diff --git a/frame/contracts/fixtures/set_empty_storage.wat b/frame/contracts/fixtures/set_empty_storage.wat new file mode 100644 index 0000000000000000000000000000000000000000..d550eb2314b86d0dbb187887f23c8894a18f7348 --- /dev/null +++ b/frame/contracts/fixtures/set_empty_storage.wat @@ -0,0 +1,15 @@ +;; This module stores a KV pair into the storage +(module + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32))) + (import "env" "memory" (memory 16 16)) + + (func (export "call") + ) + (func (export "deploy") + (call $ext_set_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 0) ;; Pointer to value + (i32.load (i32.const 0)) ;; Size of value + ) + ) +) diff --git a/frame/contracts/tests/set_rent.wat b/frame/contracts/fixtures/set_rent.wat similarity index 100% rename from frame/contracts/tests/set_rent.wat rename to frame/contracts/fixtures/set_rent.wat diff --git a/frame/contracts/tests/storage_size.wat b/frame/contracts/fixtures/storage_size.wat similarity index 100% rename from frame/contracts/tests/storage_size.wat rename to frame/contracts/fixtures/storage_size.wat diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index 66d75759f1a25cdb2ff9b6757f44fa6ec79919e3..8ed233ed79f7d3b1ed246af4a0dcb820eca3f30f 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-contracts-rpc" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Node-specific RPC methods for interaction with contracts." @@ -16,14 +16,14 @@ codec = { package = "parity-scale-codec", version = "1.3.0" } jsonrpc-core = "14.0.3" jsonrpc-core-client = "14.0.5" jsonrpc-derive = "14.0.3" -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-rpc = { version = "2.0.0-dev", path = "../../../primitives/rpc" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-rpc = { version = "2.0.0-rc2", path = "../../../primitives/rpc" } serde = { version = "1.0.101", features = ["derive"] } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -pallet-contracts-primitives = { version = "2.0.0-dev", path = "../common" } -pallet-contracts-rpc-runtime-api = { version = "0.8.0-dev", path = "./runtime-api" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +pallet-contracts-primitives = { version = "2.0.0-rc2", path = "../common" } +pallet-contracts-rpc-runtime-api = { version = "0.8.0-rc2", path = "./runtime-api" } [dev-dependencies] serde_json = "1.0.41" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml index 81c6ce3760129a58a753d0bd47519ff117fda388..b998befcc8474e0a0ba6f97dcc4ca4286594ca2b 100644 --- a/frame/contracts/rpc/runtime-api/Cargo.toml +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-contracts-rpc-runtime-api" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Runtime API definition required by Contracts RPC extensions." @@ -12,11 +12,11 @@ description = "Runtime API definition required by Contracts RPC extensions." targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-api = { version = "2.0.0-dev", default-features = false, path = "../../../../primitives/api" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../../../../primitives/api" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } -pallet-contracts-primitives = { version = "2.0.0-dev", default-features = false, path = "../../common" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../../primitives/runtime" } +pallet-contracts-primitives = { version = "2.0.0-rc2", default-features = false, path = "../../common" } [features] default = ["std"] diff --git a/frame/contracts/rpc/runtime-api/src/lib.rs b/frame/contracts/rpc/runtime-api/src/lib.rs index 6fb629b02458129e0bc8ffe13bdf363cd45479e1..84fd66826d8b3c225dc84c8a8ea5db6e287640f5 100644 --- a/frame/contracts/rpc/runtime-api/src/lib.rs +++ b/frame/contracts/rpc/runtime-api/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime API definition required by Contracts RPC extensions. //! diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs index 53e8d938703c866de09d1234e2a34ebb51122e09..89f43f42c3ad1b1512f02312742d7f1644140dc0 100644 --- a/frame/contracts/rpc/src/lib.rs +++ b/frame/contracts/rpc/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Node-specific RPC methods for interaction with contracts. diff --git a/frame/contracts/src/account_db.rs b/frame/contracts/src/account_db.rs index aae853d2ff9965c146eca1f816d6c59ed58c459d..5e1b0c34b573439427f941e13bf2fafaa31d9392 100644 --- a/frame/contracts/src/account_db.rs +++ b/frame/contracts/src/account_db.rs @@ -26,7 +26,7 @@ use sp_std::collections::btree_map::{BTreeMap, Entry}; use sp_std::prelude::*; use sp_io::hashing::blake2_256; use sp_runtime::traits::{Bounded, Zero}; -use frame_support::traits::{Currency, Get, Imbalance, SignedImbalance}; +use frame_support::traits::{Currency, Imbalance, SignedImbalance}; use frame_support::{storage::child, StorageMap}; use frame_system; @@ -108,7 +108,12 @@ pub trait AccountDb { /// /// Trie id is None iff account doesn't have an associated trie id in >. /// Because DirectAccountDb bypass the lookup for this association. - fn get_storage(&self, account: &T::AccountId, trie_id: Option<&TrieId>, location: &StorageKey) -> Option>; + fn get_storage( + &self, + account: &T::AccountId, + trie_id: Option<&TrieId>, + location: &StorageKey, + ) -> Option>; /// If account has an alive contract then return the code hash associated. fn get_code_hash(&self, account: &T::AccountId) -> Option>; /// If account has an alive contract then return the rent allowance associated. @@ -126,9 +131,10 @@ impl AccountDb for DirectAccountDb { &self, _account: &T::AccountId, trie_id: Option<&TrieId>, - location: &StorageKey + location: &StorageKey, ) -> Option> { - trie_id.and_then(|id| child::get_raw(&crate::child_trie_info(&id[..]), &blake2_256(location))) + trie_id + .and_then(|id| child::get_raw(&crate::child_trie_info(&id[..]), &blake2_256(location))) } fn get_code_hash(&self, account: &T::AccountId) -> Option> { >::get(account).and_then(|i| i.as_alive().map(|i| i.code_hash)) @@ -176,7 +182,9 @@ impl AccountDb for DirectAccountDb { child::kill_storage(&info.child_trie_info()); AliveContractInfo:: { code_hash, - storage_size: T::StorageSizeOffset::get(), + storage_size: 0, + empty_pair_count: 0, + total_pair_count: 0, trie_id: ::TrieIdGenerator::trie_id(&address), deduct_block: >::block_number(), rent_allowance: >::max_value(), @@ -184,16 +192,16 @@ impl AccountDb for DirectAccountDb { } } // New contract is being instantiated. - (_, None, Some(code_hash)) => { - AliveContractInfo:: { - code_hash, - storage_size: T::StorageSizeOffset::get(), - trie_id: ::TrieIdGenerator::trie_id(&address), - deduct_block: >::block_number(), - rent_allowance: >::max_value(), - last_write: None, - } - } + (_, None, Some(code_hash)) => AliveContractInfo:: { + code_hash, + storage_size: 0, + empty_pair_count: 0, + total_pair_count: 0, + trie_id: ::TrieIdGenerator::trie_id(&address), + deduct_block: >::block_number(), + rent_allowance: >::max_value(), + last_write: None, + }, // There is no existing at the address nor a new one to be instantiated. (_, None, None) => continue, }; @@ -210,18 +218,69 @@ impl AccountDb for DirectAccountDb { new_info.last_write = Some(>::block_number()); } - for (k, v) in changed.storage.into_iter() { - if let Some(value) = child::get_raw( - &new_info.child_trie_info(), - &blake2_256(&k), - ) { - new_info.storage_size -= value.len() as u32; + // NB: this call allocates internally. To keep allocations to the minimum we cache + // the child trie info here. + let child_trie_info = new_info.child_trie_info(); + + // Here we iterate over all storage key-value pairs that were changed throughout the + // execution of a contract and apply them to the substrate storage. + for (key, opt_new_value) in changed.storage.into_iter() { + let hashed_key = blake2_256(&key); + + // In order to correctly update the book keeping we need to fetch the previous + // value of the key-value pair. + // + // It might be a bit more clean if we had an API that supported getting the size + // of the value without going through the loading of it. But at the moment of + // writing, there is no such API. + // + // That's not a show stopper in any case, since the performance cost is + // dominated by the trie traversal anyway. + let opt_prev_value = child::get_raw(&child_trie_info, &hashed_key); + + // Update the total number of KV pairs and the number of empty pairs. + match (&opt_prev_value, &opt_new_value) { + (Some(prev_value), None) => { + new_info.total_pair_count -= 1; + if prev_value.is_empty() { + new_info.empty_pair_count -= 1; + } + }, + (None, Some(new_value)) => { + new_info.total_pair_count += 1; + if new_value.is_empty() { + new_info.empty_pair_count += 1; + } + }, + (Some(prev_value), Some(new_value)) => { + if prev_value.is_empty() { + new_info.empty_pair_count -= 1; + } + if new_value.is_empty() { + new_info.empty_pair_count += 1; + } + } + (None, None) => {} } - if let Some(value) = v { - new_info.storage_size += value.len() as u32; - child::put_raw(&new_info.child_trie_info(), &blake2_256(&k), &value[..]); - } else { - child::kill(&new_info.child_trie_info(), &blake2_256(&k)); + + // Update the total storage size. + let prev_value_len = opt_prev_value + .as_ref() + .map(|old_value| old_value.len() as u32) + .unwrap_or(0); + let new_value_len = opt_new_value + .as_ref() + .map(|new_value| new_value.len() as u32) + .unwrap_or(0); + new_info.storage_size = new_info + .storage_size + .saturating_add(new_value_len) + .saturating_sub(prev_value_len); + + // Finally, perform the change on the storage. + match opt_new_value { + Some(new_value) => child::put_raw(&child_trie_info, &hashed_key, &new_value[..]), + None => child::kill(&child_trie_info, &hashed_key), } } @@ -239,12 +298,14 @@ impl AccountDb for DirectAccountDb { // 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!"), + 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>, underlying: &'a dyn AccountDb, @@ -267,7 +328,8 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { location: StorageKey, value: Option>, ) { - self.local.borrow_mut() + self.local + .borrow_mut() .entry(account.clone()) .or_insert(Default::default()) .storage @@ -285,7 +347,7 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { } let mut local = self.local.borrow_mut(); - let contract = local.entry(account.clone()).or_insert_with(|| Default::default()); + let contract = local.entry(account.clone()).or_default(); contract.code_hash = Some(code_hash); contract.rent_allowance = Some(>::max_value()); @@ -301,7 +363,7 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { ChangeEntry { reset: true, ..Default::default() - } + }, ); } @@ -327,7 +389,7 @@ impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { &self, account: &T::AccountId, trie_id: Option<&TrieId>, - location: &StorageKey + location: &StorageKey, ) -> Option> { self.local .borrow() diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index df53cf0a0eadd3f0bc9c30520a35a01591808653..8f90f557cae13187ffd0f8b983099e4399ceb8c4 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -203,8 +203,15 @@ pub type AliveContractInfo = pub struct RawAliveContractInfo { /// Unique ID for the subtree encoded as a bytes vector. pub trie_id: TrieId, - /// The size of stored value in octet. + /// The total number of bytes used by this contract. + /// + /// It is a sum of each key-value pair stored by this contract. pub storage_size: u32, + /// The number of key-value pairs that have values of zero length. + /// The condition `empty_pair_count ≤ total_pair_count` always holds. + pub empty_pair_count: u32, + /// The total number of key-value pairs in storage of this contract. + pub total_pair_count: u32, /// The code associated with a given account. pub code_hash: CodeHash, /// Pay rent at most up to this value. @@ -338,8 +345,11 @@ pub trait Trait: frame_system::Trait + pallet_transaction_payment::Trait { /// The minimum amount required to generate a tombstone. type TombstoneDeposit: Get>; - /// Size of a contract at the time of instantiation. This is a simple way to ensure - /// that empty contracts eventually gets deleted. + /// A size offset for an contract. A just created account with untouched storage will have that + /// much of storage from the perspective of the state rent. + /// + /// This is a simple way to ensure that contracts with empty storage eventually get deleted by + /// making them pay rent. This creates an incentive to remove them early in order to save rent. type StorageSizeOffset: Get; /// Price of a byte of storage per one block interval. Should be greater than 0. @@ -420,8 +430,12 @@ decl_module! { /// The minimum amount required to generate a tombstone. const TombstoneDeposit: BalanceOf = T::TombstoneDeposit::get(); - /// Size of a contract at the time of instantiation. This is a simple way to ensure that - /// empty contracts eventually gets deleted. + /// A size offset for an contract. A just created account with untouched storage will have that + /// much of storage from the perspective of the state rent. + /// + /// This is a simple way to ensure that contracts with empty storage eventually get deleted + /// by making them pay rent. This creates an incentive to remove them early in order to save + /// rent. const StorageSizeOffset: u32 = T::StorageSizeOffset::get(); /// Price of a byte of storage per one block interval. Should be greater than 0. @@ -697,7 +711,7 @@ impl Module { dest: T::AccountId, code_hash: CodeHash, rent_allowance: BalanceOf, - delta: Vec + delta: Vec, ) -> DispatchResult { let mut origin_contract = >::get(&origin) .and_then(|c| c.get_alive()) @@ -764,6 +778,8 @@ impl Module { >::insert(&dest, ContractInfo::Alive(RawAliveContractInfo { trie_id: origin_contract.trie_id, storage_size: origin_contract.storage_size, + empty_pair_count: origin_contract.empty_pair_count, + total_pair_count: origin_contract.total_pair_count, code_hash, rent_allowance, deduct_block: current_block, @@ -836,6 +852,8 @@ decl_storage! { /// The subtrie counter. pub AccountCounter: u64 = 0; /// The code associated with a given account. + /// + /// TWOX-NOTE: SAFE since `AccountId` is a secure hash. pub ContractInfoOf: map hasher(twox_64_concat) T::AccountId => Option>; } } diff --git a/frame/contracts/src/rent.rs b/frame/contracts/src/rent.rs index 1aa52fff314356e4758947e128139e92a4961c73..1d8f47462731b20e79cff2b479248bd3d1968d84 100644 --- a/frame/contracts/src/rent.rs +++ b/frame/contracts/src/rent.rs @@ -92,8 +92,13 @@ fn compute_fee_per_block( .checked_div(&T::RentDepositOffset::get()) .unwrap_or_else(Zero::zero); - let effective_storage_size = - >::from(contract.storage_size).saturating_sub(free_storage); + // For now, we treat every empty KV pair as if it was one byte long. + let empty_pairs_equivalent = contract.empty_pair_count; + + let effective_storage_size = >::from( + contract.storage_size + T::StorageSizeOffset::get() + empty_pairs_equivalent, + ) + .saturating_sub(free_storage); effective_storage_size .checked_mul(&T::RentByteFee::get()) diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 218a5c99372d40d78ba6c68a099d89faf3f79200..307b3118890b091b77d75ecd115dac4669341301 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -14,33 +14,27 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -// TODO: #1417 Add more integration tests -// also remove the #![allow(unused)] below. - -#![allow(unused)] - use crate::{ - BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, - Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, Schedule, - TrieIdGenerator, account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}, + BalanceOf, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, Module, + RawAliveContractInfo, RawEvent, Trait, TrieId, Schedule, TrieIdGenerator, + account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}, gas::Gas, }; use assert_matches::assert_matches; use hex_literal::*; -use codec::{Decode, Encode, KeyedVec}; +use codec::Encode; use sp_runtime::{ - Perbill, BuildStorage, transaction_validity::{InvalidTransaction, ValidTransaction}, - traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension, Convert}, - testing::{Digest, DigestItem, Header, UintAuthorityId, H256}, + Perbill, + traits::{BlakeTwo256, Hash, IdentityLookup, Convert}, + testing::{Header, H256}, }; use frame_support::{ - assert_ok, assert_err, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event, - impl_outer_origin, parameter_types, - storage::child, StorageMap, StorageValue, traits::{Currency, Get}, - weights::{DispatchInfo, DispatchClass, Weight, PostDispatchInfo, Pays}, + assert_ok, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event, + impl_outer_origin, parameter_types, StorageMap, StorageValue, + traits::{Currency, Get}, + weights::{Weight, PostDispatchInfo, IdentityFee}, }; -use std::{cell::RefCell, sync::atomic::{AtomicUsize, Ordering}}; -use sp_core::storage::well_known_keys; +use std::cell::RefCell; use frame_system::{self as system, EventRecord, Phase}; mod contracts { @@ -48,7 +42,7 @@ mod contracts { // needs to give a name for the current crate. // This hack is required for `impl_outer_event!`. pub use super::super::*; - use frame_support::impl_outer_event; + pub use frame_support::impl_outer_event; } use pallet_balances as balances; @@ -103,6 +97,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -151,7 +146,7 @@ impl pallet_transaction_payment::Trait for Test { type Currency = Balances; type OnTransactionPayment = (); type TransactionByteFee = TransactionByteFee; - type WeightToFee = Test; + type WeightToFee = IdentityFee>; type FeeMultiplierUpdate = (); } @@ -189,8 +184,6 @@ impl ContractAddressFor for DummyContractAddressFor { pub struct DummyTrieIdGenerator; impl TrieIdGenerator for DummyTrieIdGenerator { fn trie_id(account_id: &u64) -> TrieId { - use sp_core::storage::well_known_keys; - let new_seed = super::AccountCounter::mutate(|v| { *v = v.wrapping_add(1); *v @@ -203,13 +196,6 @@ impl TrieIdGenerator for DummyTrieIdGenerator { } } -pub struct DummyComputeDispatchFee; -impl ComputeDispatchFee for DummyComputeDispatchFee { - fn compute_dispatch_fee(call: &Call) -> u64 { - 69 - } -} - const ALICE: u64 = 1; const BOB: u64 = 2; const CHARLIE: u64 = 3; @@ -253,14 +239,24 @@ impl ExtBuilder { } } -/// Generate Wasm binary and code hash from wabt source. -fn compile_module(wabt_module: &str) - -> Result<(Vec, ::Output), wabt::Error> - where T: frame_system::Trait +/// Load a given wasm module represented by a .wat file and returns a wasm binary contents along +/// with it's hash. +/// +/// The fixture files are located under the `fixtures/` directory. +fn compile_module( + fixture_name: &str, +) -> Result<(Vec, ::Output), wabt::Error> +where + T: frame_system::Trait, { - let wasm = wabt::wat2wasm(wabt_module)?; - let code_hash = T::Hashing::hash(&wasm); - Ok((wasm, code_hash)) + use std::fs; + + let fixture_path = ["fixtures/", fixture_name, ".wat"].concat(); + let module_wat_source = + fs::read_to_string(&fixture_path).expect(&format!("Unable to find {} fixture", fixture_name)); + let wasm_binary = wabt::wat2wasm(module_wat_source)?; + let code_hash = T::Hashing::hash(&wasm_binary); + Ok((wasm_binary, code_hash)) } // Perform a simple transfer to a non-existent account. @@ -268,7 +264,7 @@ fn compile_module(wabt_module: &str) #[test] fn returns_base_call_cost() { ExtBuilder::default().build().execute_with(|| { - Balances::deposit_creating(&ALICE, 100_000_000); + let _ = Balances::deposit_creating(&ALICE, 100_000_000); assert_eq!( Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, Vec::new()), @@ -291,10 +287,12 @@ fn account_removal_does_not_remove_storage() { // Set up two accounts with free balance above the existential threshold. { - Balances::deposit_creating(&1, 110); + let _ = Balances::deposit_creating(&1, 110); ContractInfoOf::::insert(1, &ContractInfo::Alive(RawAliveContractInfo { trie_id: trie_id1.clone(), - storage_size: ::StorageSizeOffset::get(), + storage_size: 0, + empty_pair_count: 0, + total_pair_count: 0, deduct_block: System::block_number(), code_hash: H256::repeat_byte(1), rent_allowance: 40, @@ -306,10 +304,12 @@ fn account_removal_does_not_remove_storage() { overlay.set_storage(&1, key2.clone(), Some(b"2".to_vec())); DirectAccountDb.commit(overlay.into_change_set()); - Balances::deposit_creating(&2, 110); + let _ = Balances::deposit_creating(&2, 110); ContractInfoOf::::insert(2, &ContractInfo::Alive(RawAliveContractInfo { trie_id: trie_id2.clone(), - storage_size: ::StorageSizeOffset::get(), + storage_size: 0, + empty_pair_count: 0, + total_pair_count: 0, deduct_block: System::block_number(), code_hash: H256::repeat_byte(2), rent_allowance: 40, @@ -356,71 +356,73 @@ fn account_removal_does_not_remove_storage() { #[test] fn instantiate_and_call_and_deposit_event() { - let (wasm, code_hash) = compile_module::(&load_wasm("return_from_start_fn.wat")) - .unwrap(); + let (wasm, code_hash) = compile_module::("return_from_start_fn").unwrap(); - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); + ExtBuilder::default() + .existential_deposit(100) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // Check at the end to get hash on error easily - let creation = Contracts::instantiate( - Origin::signed(ALICE), - 100, - GAS_LIMIT, - code_hash.into(), - vec![], - ); + // Check at the end to get hash on error easily + let creation = Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, + code_hash.into(), + vec![], + ); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::ContractExecution(BOB, vec![1, 2, 3, 4])), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - } - ]); + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances( + pallet_balances::RawEvent::Endowed(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::ContractExecution(BOB, vec![1, 2, 3, 4])), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + } + ]); - assert_ok!(creation); - assert!(ContractInfoOf::::contains_key(BOB)); - }); + assert_ok!(creation); + assert!(ContractInfoOf::::contains_key(BOB)); + }); } #[test] @@ -430,118 +432,120 @@ fn dispatch_call() { let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - let (wasm, code_hash) = compile_module::(&load_wasm("dispatch_call.wat")) - .unwrap(); + let (wasm, code_hash) = compile_module::("dispatch_call").unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // 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::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - - assert_ok!(Contracts::call( - Origin::signed(ALICE), - BOB, // newly created account - 0, - GAS_LIMIT, - vec![], - )); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - }, + // 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::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); - // Dispatching the call. - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(CHARLIE, 50) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Transfer(BOB, CHARLIE, 50) - ), - topics: vec![], - }, + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, + code_hash.into(), + vec![], + )); - // Event emitted as a result of dispatch. - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Dispatched(BOB, true)), - topics: vec![], - } - ]); - }); + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, // newly created account + 0, + GAS_LIMIT, + vec![], + )); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances( + pallet_balances::RawEvent::Endowed(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + }, + + // Dispatching the call. + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances( + pallet_balances::RawEvent::Endowed(CHARLIE, 50) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances( + pallet_balances::RawEvent::Transfer(BOB, CHARLIE, 50) + ), + topics: vec![], + }, + + // Event emitted as a result of dispatch. + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Dispatched(BOB, true)), + topics: vec![], + } + ]); + }); } #[test] @@ -551,107 +555,108 @@ fn dispatch_call_not_dispatched_after_top_level_transaction_failure() { let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - let (wasm, code_hash) = compile_module::(&load_wasm("dispatch_call_then_trap.wat")) - .unwrap(); + let (wasm, code_hash) = compile_module::("dispatch_call_then_trap").unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // 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::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - - // Call the newly instantiated contract. The contract is expected to dispatch a call - // and then trap. - assert_err_ignore_postinfo!( - Contracts::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::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - BOB, // newly created account - 0, + 100, GAS_LIMIT, + code_hash.into(), vec![], - ), - "contract trapped during execution" - ); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances( - pallet_balances::RawEvent::Endowed(BOB, 100) + )); + + // Call the newly instantiated contract. The contract is expected to dispatch a call + // and then trap. + assert_err_ignore_postinfo!( + Contracts::call( + Origin::signed(ALICE), + BOB, // newly created account + 0, + GAS_LIMIT, + vec![], ), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - }, - // ABSENCE of events which would be caused by dispatched Balances::transfer call - ]); - }); + "contract trapped during execution" + ); + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances( + pallet_balances::RawEvent::Endowed(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + }, + // ABSENCE of events which would be caused by dispatched Balances::transfer call + ]); + }); } #[test] fn run_out_of_gas() { - let (wasm, code_hash) = compile_module::(&load_wasm("run_out_of_gas.wat")) - .unwrap(); + let (wasm, code_hash) = compile_module::("run_out_of_gas").unwrap(); ExtBuilder::default() .existential_deposit(50) .build() .execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); + let _ = Balances::deposit_creating(&ALICE, 1_000_000); assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); @@ -695,60 +700,157 @@ fn test_set_rent_code_and_hash() { let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap(); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // 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::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - }); -} + // 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::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + }); +} #[test] fn storage_size() { - let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap(); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); // Storage size - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 30_000, - GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); - - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::set_storage_4_byte())); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4 + 4); - - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::remove_storage_4_byte())); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); - }); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + let bob_contract = ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap(); + assert_eq!( + bob_contract.storage_size, + 4 + ); + assert_eq!( + bob_contract.total_pair_count, + 1, + ); + assert_eq!( + bob_contract.empty_pair_count, + 0, + ); + + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + call::set_storage_4_byte() + )); + let bob_contract = ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap(); + assert_eq!( + bob_contract.storage_size, + 4 + 4 + ); + assert_eq!( + bob_contract.total_pair_count, + 2, + ); + assert_eq!( + bob_contract.empty_pair_count, + 0, + ); + + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + call::remove_storage_4_byte() + )); + let bob_contract = ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap(); + assert_eq!( + bob_contract.storage_size, + 4 + ); + assert_eq!( + bob_contract.total_pair_count, + 1, + ); + assert_eq!( + bob_contract.empty_pair_count, + 0, + ); + }); +} + +#[test] +fn empty_kv_pairs() { + let (wasm, code_hash) = compile_module::("set_empty_storage").unwrap(); + + ExtBuilder::default() + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + code_hash.into(), + vec![], + )); + let bob_contract = ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap(); + + assert_eq!( + bob_contract.storage_size, + 0, + ); + assert_eq!( + bob_contract.total_pair_count, + 1, + ); + assert_eq!( + bob_contract.empty_pair_count, + 1, + ); + }); } fn initialize_block(number: u64) { @@ -763,68 +865,71 @@ fn initialize_block(number: u64) { #[test] fn deduct_blocks() { - let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 30_000, - GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000); - - // Advance 4 blocks - initialize_block(5); - - // Trigger rent through call - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); - - // Check result - let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset - * 4 // rent byte price - * 4; // blocks to rent - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent); - assert_eq!(bob_contract.deduct_block, 5); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent); - - // Advance 7 blocks more - initialize_block(12); - - // Trigger rent through call - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); - - // Check result - let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset - * 4 // rent byte price - * 7; // blocks to rent - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); - assert_eq!(bob_contract.deduct_block, 12); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); - - // Second call on same block should have no effect on rent - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); - - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); - assert_eq!(bob_contract.deduct_block, 12); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); - }); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000); + + // Advance 4 blocks + initialize_block(5); + + // Trigger rent through call + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + + // Check result + let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset + * 4 // rent byte price + * 4; // blocks to rent + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent); + assert_eq!(bob_contract.deduct_block, 5); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent); + + // Advance 7 blocks more + initialize_block(12); + + // Trigger rent through call + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + + // Check result + let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset + * 4 // rent byte price + * 7; // blocks to rent + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); + assert_eq!(bob_contract.deduct_block, 12); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); + + // Second call on same block should have no effect on rent + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); + assert_eq!(bob_contract.deduct_block, 12); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); + }); } #[test] fn call_contract_removals() { removals(|| { // Call on already-removed account might fail, and this is fine. - Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()); + let _ = Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()); true }); } @@ -857,31 +962,34 @@ fn claim_surcharge_malus() { /// Claim surcharge with the given trigger_call at the given blocks. /// If `removes` is true then assert that the contract is a tombstone. fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) { - let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Advance blocks - initialize_block(blocks); - - // Trigger rent through call - assert!(trigger_call()); - - if removes { - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - } else { - assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some()); - } - }); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Advance blocks + initialize_block(blocks); + + // Trigger rent through call + assert!(trigger_call()); + + if removes { + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + } else { + assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some()); + } + }); } /// Test for all kind of removals for the given trigger: @@ -889,194 +997,246 @@ fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) /// * if allowance is exceeded /// * if balance is reached and balance < subsistence threshold fn removals(trigger_call: impl Fn() -> bool) { - let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap(); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); // Balance reached and superior to subsistence threshold - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/; - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(BOB), 100); - - // Advance blocks - initialize_block(10); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(BOB), subsistence_threshold); - - // Advance blocks - initialize_block(20); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(BOB), subsistence_threshold); - }); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/; + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); + assert_eq!(Balances::free_balance(BOB), 100); + + // Advance blocks + initialize_block(10); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + + // Advance blocks + initialize_block(20); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(BOB), subsistence_threshold); + }); // Allowance exceeded - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 1_000, - GAS_LIMIT, code_hash.into(), - ::Balance::from(100u32).encode() // rent allowance - )); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100); - assert_eq!(Balances::free_balance(BOB), 1_000); - - // Advance blocks - initialize_block(10); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - // Balance should be initial balance - initial rent_allowance - assert_eq!(Balances::free_balance(BOB), 900); - - // Advance blocks - initialize_block(20); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(BOB), 900); - }); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 1_000, + GAS_LIMIT, + code_hash.into(), + ::Balance::from(100u32).encode() // rent allowance + )); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!( + ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap() + .rent_allowance, + 100 + ); + assert_eq!(Balances::free_balance(BOB), 1_000); + + // Advance blocks + initialize_block(10); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB) + .unwrap() + .get_tombstone() + .is_some()); + // Balance should be initial balance - initial rent_allowance + assert_eq!(Balances::free_balance(BOB), 900); + + // Advance blocks + initialize_block(20); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB) + .unwrap() + .get_tombstone() + .is_some()); + assert_eq!(Balances::free_balance(BOB), 900); + }); // Balance reached and inferior to subsistence threshold - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 50+Balances::minimum_balance(), - GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(BOB), 50 + Balances::minimum_balance()); - - // Transfer funds - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::transfer())); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance()); - - // Advance blocks - initialize_block(10); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).is_none()); - assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance()); - - // Advance blocks - initialize_block(20); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).is_none()); - assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance()); - }); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 50 + Balances::minimum_balance(), + GAS_LIMIT, + code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!( + ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap() + .rent_allowance, + 1_000 + ); + assert_eq!( + Balances::free_balance(BOB), + 50 + Balances::minimum_balance() + ); + + // Transfer funds + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + call::transfer() + )); + assert_eq!( + ContractInfoOf::::get(BOB) + .unwrap() + .get_alive() + .unwrap() + .rent_allowance, + 1_000 + ); + assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance()); + + // Advance blocks + initialize_block(10); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).is_none()); + assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance()); + + // Advance blocks + initialize_block(20); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).is_none()); + assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance()); + }); } #[test] fn call_removed_contract() { - let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap(); + let (wasm, code_hash) = compile_module::("set_rent").unwrap(); // Balance reached and superior to subsistence threshold - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - GAS_LIMIT, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Calling contract should succeed. - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); - - // Advance blocks - initialize_block(10); - - // Calling contract should remove contract and fail. - assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), - "contract has been evicted" - ); - // Calling a contract that is about to evict shall emit an event. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), - topics: vec![], - }, - ]); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone())); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); - // Subsequent contract calls should also fail. - assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), - "contract has been evicted" - ); - }) + // Calling contract should succeed. + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + + // Advance blocks + initialize_block(10); + + // Calling contract should remove contract and fail. + assert_err_ignore_postinfo!( + Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + "contract has been evicted" + ); + // Calling a contract that is about to evict shall emit an event. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), + topics: vec![], + }, + ]); + + // Subsequent contract calls should also fail. + assert_err_ignore_postinfo!( + Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + "contract has been evicted" + ); + }) } #[test] fn default_rent_allowance_on_instantiate() { - let (wasm, code_hash) = compile_module::( - &load_wasm("check_default_rent_allowance.wat")).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 30_000, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, >::max_value()); - - // Advance blocks - initialize_block(5); - - // Trigger rent through call - assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); - - // Check contract is still alive - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive(); - assert!(bob_contract.is_some()) - }); + let (wasm, code_hash) = compile_module::("check_default_rent_allowance").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + code_hash.into(), + vec![], + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, >::max_value()); + + // Advance blocks + initialize_block(5); + + // Trigger rent through call + assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null())); + + // Check contract is still alive + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive(); + assert!(bob_contract.is_some()) + }); } #[test] @@ -1100,571 +1260,586 @@ fn restoration_success() { } fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: bool) { - let (set_rent_wasm, set_rent_code_hash) = - compile_module::(&load_wasm("set_rent.wat")).unwrap(); - let (restoration_wasm, restoration_code_hash) = - compile_module::(&load_wasm("restoration.wat")).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), restoration_wasm)); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), set_rent_wasm)); - - // 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::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(restoration_code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::CodeStored(set_rent_code_hash.into())), - topics: vec![], - }, - ]); - - // Create an account with address `BOB` with code `CODE_SET_RENT`. - // The input parameter sets the rent allowance to 0. - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 30_000, - GAS_LIMIT, - set_rent_code_hash.into(), - ::Balance::from(0u32).encode() - )); - - // Check if `BOB` was created successfully and that the rent allowance is - // set to 0. - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 0); - - if test_different_storage { - assert_ok!(Contracts::call( - Origin::signed(ALICE), - BOB, 0, GAS_LIMIT, - call::set_storage_4_byte()) - ); - } + let (set_rent_wasm, set_rent_code_hash) = compile_module::("set_rent").unwrap(); + let (restoration_wasm, restoration_code_hash) = compile_module::("restoration").unwrap(); - // Advance 4 blocks, to the 5th. - initialize_block(5); - - /// Preserve `BOB`'s code hash for later introspection. - let bob_code_hash = ContractInfoOf::::get(BOB).unwrap() - .get_alive().unwrap().code_hash; - // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0 - // we expect that it will get removed leaving tombstone. - assert_err_ignore_postinfo!( - Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), - "contract has been evicted" - ); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts( - RawEvent::Evicted(BOB.clone(), true) - ), - topics: vec![], - }, - ]); - - /// Create another account with the address `DJANGO` with `CODE_RESTORATION`. - /// - /// Note that we can't use `ALICE` for creating `DJANGO` so we create yet another - /// account `CHARLIE` and create `DJANGO` with it. - Balances::deposit_creating(&CHARLIE, 1_000_000); - assert_ok!(Contracts::instantiate( - Origin::signed(CHARLIE), - 30_000, - GAS_LIMIT, - restoration_code_hash.into(), - ::Balance::from(0u32).encode() - )); - - // Before performing a call to `DJANGO` save its original trie id. - let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap() - .get_alive().unwrap().trie_id; - - if !test_restore_to_with_dirty_storage { - // Advance 1 block, to the 6th. - initialize_block(6); - } + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), restoration_wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), set_rent_wasm)); - // Perform a call to `DJANGO`. This should either perform restoration successfully or - // fail depending on the test parameters. - assert_ok!(Contracts::call( - Origin::signed(ALICE), - DJANGO, - 0, - GAS_LIMIT, - vec![], - )); - - if test_different_storage || test_restore_to_with_dirty_storage { - // Parametrization of the test imply restoration failure. Check that `DJANGO` aka - // restoration contract is still in place and also that `BOB` doesn't exist. - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - let django_contract = ContractInfoOf::::get(DJANGO).unwrap() - .get_alive().unwrap(); - assert_eq!(django_contract.storage_size, 16); - assert_eq!(django_contract.trie_id, django_trie_id); - assert_eq!(django_contract.deduct_block, System::block_number()); - match (test_different_storage, test_restore_to_with_dirty_storage) { - (true, false) => { - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts( - RawEvent::Restored(DJANGO, BOB, bob_code_hash, 50, false) - ), - topics: vec![], - }, - ]); - } - (_, true) => { - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(CHARLIE, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::system(frame_system::RawEvent::NewAccount(DJANGO)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(DJANGO, 30_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Transfer(CHARLIE, DJANGO, 30_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Instantiated(CHARLIE, DJANGO)), - topics: vec![], - }, - EventRecord { - phase: Phase::Initialization, - event: MetaEvent::contracts(RawEvent::Restored( - DJANGO, - BOB, - bob_code_hash, - 50, - false, - )), - topics: vec![], - }, - ]); - } - _ => unreachable!(), - } - } else { - // Here we expect that the restoration is succeeded. Check that the restoration - // contract `DJANGO` ceased to exist and that `BOB` returned back. - println!("{:?}", ContractInfoOf::::get(BOB)); - let bob_contract = ContractInfoOf::::get(BOB).unwrap() - .get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 50); - assert_eq!(bob_contract.storage_size, 12); - assert_eq!(bob_contract.trie_id, django_trie_id); - assert_eq!(bob_contract.deduct_block, System::block_number()); - assert!(ContractInfoOf::::get(DJANGO).is_none()); + // 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::Initialization, - event: MetaEvent::system(system::RawEvent::KilledAccount(DJANGO)), + event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(restoration_code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::CodeStored(set_rent_code_hash.into())), topics: vec![], }, + ]); + + // Create an account with address `BOB` with code `CODE_SET_RENT`. + // The input parameter sets the rent allowance to 0. + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + set_rent_code_hash.into(), + ::Balance::from(0u32).encode() + )); + + // Check if `BOB` was created successfully and that the rent allowance is + // set to 0. + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 0); + + if test_different_storage { + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, 0, GAS_LIMIT, + call::set_storage_4_byte()) + ); + } + + // Advance 4 blocks, to the 5th. + initialize_block(5); + + // Preserve `BOB`'s code hash for later introspection. + let bob_code_hash = ContractInfoOf::::get(BOB).unwrap() + .get_alive().unwrap().code_hash; + // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0 + // we expect that it will get removed leaving tombstone. + assert_err_ignore_postinfo!( + Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()), + "contract has been evicted" + ); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(System::events(), vec![ EventRecord { phase: Phase::Initialization, event: MetaEvent::contracts( - RawEvent::Restored(DJANGO, BOB, bob_contract.code_hash, 50, true) + RawEvent::Evicted(BOB.clone(), true) ), topics: vec![], }, ]); - } - }); + + // Create another account with the address `DJANGO` with `CODE_RESTORATION`. + // + // Note that we can't use `ALICE` for creating `DJANGO` so we create yet another + // account `CHARLIE` and create `DJANGO` with it. + let _ = Balances::deposit_creating(&CHARLIE, 1_000_000); + assert_ok!(Contracts::instantiate( + Origin::signed(CHARLIE), + 30_000, + GAS_LIMIT, + restoration_code_hash.into(), + ::Balance::from(0u32).encode() + )); + + // Before performing a call to `DJANGO` save its original trie id. + let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap() + .get_alive().unwrap().trie_id; + + if !test_restore_to_with_dirty_storage { + // Advance 1 block, to the 6th. + initialize_block(6); + } + + // Perform a call to `DJANGO`. This should either perform restoration successfully or + // fail depending on the test parameters. + assert_ok!(Contracts::call( + Origin::signed(ALICE), + DJANGO, + 0, + GAS_LIMIT, + vec![], + )); + + if test_different_storage || test_restore_to_with_dirty_storage { + // Parametrization of the test imply restoration failure. Check that `DJANGO` aka + // restoration contract is still in place and also that `BOB` doesn't exist. + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + let django_contract = ContractInfoOf::::get(DJANGO).unwrap() + .get_alive().unwrap(); + assert_eq!(django_contract.storage_size, 8); + assert_eq!(django_contract.trie_id, django_trie_id); + assert_eq!(django_contract.deduct_block, System::block_number()); + match (test_different_storage, test_restore_to_with_dirty_storage) { + (true, false) => { + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts( + RawEvent::Restored(DJANGO, BOB, bob_code_hash, 50, false) + ), + topics: vec![], + }, + ]); + } + (_, true) => { + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(CHARLIE, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(frame_system::RawEvent::NewAccount(DJANGO)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(DJANGO, 30_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Transfer(CHARLIE, DJANGO, 30_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Instantiated(CHARLIE, DJANGO)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts(RawEvent::Restored( + DJANGO, + BOB, + bob_code_hash, + 50, + false, + )), + topics: vec![], + }, + ]); + } + _ => unreachable!(), + } + } else { + // Here we expect that the restoration is succeeded. Check that the restoration + // contract `DJANGO` ceased to exist and that `BOB` returned back. + println!("{:?}", ContractInfoOf::::get(BOB)); + let bob_contract = ContractInfoOf::::get(BOB).unwrap() + .get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 50); + assert_eq!(bob_contract.storage_size, 4); + assert_eq!(bob_contract.trie_id, django_trie_id); + assert_eq!(bob_contract.deduct_block, System::block_number()); + assert!(ContractInfoOf::::get(DJANGO).is_none()); + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::system(system::RawEvent::KilledAccount(DJANGO)), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: MetaEvent::contracts( + RawEvent::Restored(DJANGO, BOB, bob_contract.code_hash, 50, true) + ), + topics: vec![], + }, + ]); + } + }); } #[test] fn storage_max_value_limit() { - let (wasm, code_hash) = compile_module::(&load_wasm("storage_size.wat")) - .unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 30_000, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, >::max_value()); - - // Call contract with allowed storage value. - assert_ok!(Contracts::call( - Origin::signed(ALICE), - BOB, - 0, - GAS_LIMIT, - Encode::encode(&self::MaxValueSize::get()), - )); - - // Call contract with too large a storage value. - assert_err_ignore_postinfo!( - Contracts::call( + let (wasm, code_hash) = compile_module::("storage_size").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 30_000, + GAS_LIMIT, + code_hash.into(), + vec![], + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, >::max_value()); + + // Call contract with allowed storage value. + assert_ok!(Contracts::call( Origin::signed(ALICE), BOB, 0, GAS_LIMIT, - Encode::encode(&(self::MaxValueSize::get() + 1)), - ), - "contract trapped during execution" - ); - }); + Encode::encode(&self::MaxValueSize::get()), + )); + + // Call contract with too large a storage value. + assert_err_ignore_postinfo!( + Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + Encode::encode(&(self::MaxValueSize::get() + 1)), + ), + "contract trapped during execution" + ); + }); } #[test] fn deploy_and_call_other_contract() { - let (callee_wasm, callee_code_hash) = - compile_module::(&load_wasm("return_with_data.wat")).unwrap(); - let (caller_wasm, caller_code_hash) = - compile_module::(&load_wasm("caller_contract.wat")).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm)); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm)); - - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100_000, - GAS_LIMIT, - caller_code_hash.into(), - vec![], - )); - - // Call BOB contract, which attempts to instantiate and call the callee contract and - // makes various assertions on the results from those calls. - assert_ok!(Contracts::call( - Origin::signed(ALICE), - BOB, - 0, - GAS_LIMIT, - callee_code_hash.as_ref().to_vec(), - )); - }); + let (callee_wasm, callee_code_hash) = compile_module::("return_with_data").unwrap(); + let (caller_wasm, caller_code_hash) = compile_module::("caller_contract").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm)); + + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100_000, + GAS_LIMIT, + caller_code_hash.into(), + vec![], + )); + + // Call BOB contract, which attempts to instantiate and call the callee contract and + // makes various assertions on the results from those calls. + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + callee_code_hash.as_ref().to_vec(), + )); + }); } #[test] fn cannot_self_destruct_through_draning() { - let (wasm, code_hash) = compile_module::(&load_wasm("drain.wat")).unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - - // Instantiate the BOB contract. - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100_000, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - - // Check that the BOB contract has been instantiated. - assert_matches!( - ContractInfoOf::::get(BOB), - Some(ContractInfo::Alive(_)) - ); + let (wasm, code_hash) = compile_module::("drain").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // Call BOB with no input data, forcing it to run until out-of-balance - // and eventually trapping because below existential deposit. - assert_err_ignore_postinfo!( - Contracts::call( + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - BOB, - 0, + 100_000, GAS_LIMIT, + code_hash.into(), vec![], - ), - "contract trapped during execution" - ); - }); + )); + + // Check that the BOB contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB with no input data, forcing it to run until out-of-balance + // and eventually trapping because below existential deposit. + assert_err_ignore_postinfo!( + Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + vec![], + ), + "contract trapped during execution" + ); + }); } #[test] fn cannot_self_destruct_while_live() { - let (wasm, code_hash) = compile_module::(&load_wasm("self_destruct.wat")) - .unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - - // Instantiate the BOB contract. - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100_000, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - - // Check that the BOB contract has been instantiated. - assert_matches!( - ContractInfoOf::::get(BOB), - Some(ContractInfo::Alive(_)) - ); + let (wasm, code_hash) = compile_module::("self_destruct").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // Call BOB with input data, forcing it make a recursive call to itself to - // self-destruct, resulting in a trap. - assert_err_ignore_postinfo!( - Contracts::call( + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - BOB, - 0, + 100_000, GAS_LIMIT, - vec![0], - ), - "contract trapped during execution" - ); + code_hash.into(), + vec![], + )); - // Check that BOB is still alive. - assert_matches!( - ContractInfoOf::::get(BOB), - Some(ContractInfo::Alive(_)) - ); - }); + // Check that the BOB contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB with input data, forcing it make a recursive call to itself to + // self-destruct, resulting in a trap. + assert_err_ignore_postinfo!( + Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + vec![0], + ), + "contract trapped during execution" + ); + + // Check that BOB is still alive. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + }); } #[test] fn self_destruct_works() { - let (wasm, code_hash) = compile_module::(&load_wasm("self_destruct.wat")) - .unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - - // Instantiate the BOB contract. - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100_000, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - - // Check that the BOB contract has been instantiated. - assert_matches!( - ContractInfoOf::::get(BOB), - Some(ContractInfo::Alive(_)) - ); + let (wasm, code_hash) = compile_module::("self_destruct").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - // Call BOB without input data which triggers termination. - assert_matches!( - Contracts::call( + // Instantiate the BOB contract. + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - BOB, - 0, + 100_000, GAS_LIMIT, + code_hash.into(), vec![], - ), - Ok(_) - ); + )); - // Check that account is gone - assert!(ContractInfoOf::::get(BOB).is_none()); + // Check that the BOB contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); - // check that the beneficiary (django) got remaining balance - assert_eq!(Balances::free_balance(DJANGO), 100_000); - }); + // Call BOB without input data which triggers termination. + assert_matches!( + Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + vec![], + ), + Ok(_) + ); + + // Check that account is gone + assert!(ContractInfoOf::::get(BOB).is_none()); + + // check that the beneficiary (django) got remaining balance + assert_eq!(Balances::free_balance(DJANGO), 100_000); + }); } // This tests that one contract cannot prevent another from self-destructing by sending it // additional funds after it has been drained. #[test] fn destroy_contract_and_transfer_funds() { - let (callee_wasm, callee_code_hash) = - compile_module::(&load_wasm("self_destruct.wat")).unwrap(); - let (caller_wasm, caller_code_hash) = - compile_module::(&load_wasm("destroy_and_transfer.wat")).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm)); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm)); - - // This deploys the BOB contract, which in turn deploys the CHARLIE contract during - // construction. - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 200_000, - GAS_LIMIT, - caller_code_hash.into(), - callee_code_hash.as_ref().to_vec(), - )); - - // Check that the CHARLIE contract has been instantiated. - assert_matches!( - ContractInfoOf::::get(CHARLIE), - Some(ContractInfo::Alive(_)) - ); + let (callee_wasm, callee_code_hash) = compile_module::("self_destruct").unwrap(); + let (caller_wasm, caller_code_hash) = compile_module::("destroy_and_transfer").unwrap(); - // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. - assert_ok!(Contracts::call( - Origin::signed(ALICE), - BOB, - 0, - GAS_LIMIT, - CHARLIE.encode(), - )); - - // Check that CHARLIE has moved on to the great beyond (ie. died). - assert!(ContractInfoOf::::get(CHARLIE).is_none()); - }); -} + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + // Create + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm)); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm)); -#[test] -fn cannot_self_destruct_in_constructor() { - let (wasm, code_hash) = - compile_module::(&load_wasm("self_destructing_constructor.wat")).unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - - // Fail to instantiate the BOB because the call that is issued in the deploy - // function exhausts all balances which puts it below the existential deposit. - assert_err_ignore_postinfo!( - Contracts::instantiate( + // This deploys the BOB contract, which in turn deploys the CHARLIE contract during + // construction. + assert_ok!(Contracts::instantiate( Origin::signed(ALICE), - 100_000, + 200_000, GAS_LIMIT, - code_hash.into(), - vec![], - ), - "contract trapped during execution" - ); - }); + caller_code_hash.into(), + callee_code_hash.as_ref().to_vec(), + )); + + // Check that the CHARLIE contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(CHARLIE), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. + assert_ok!(Contracts::call( + Origin::signed(ALICE), + BOB, + 0, + GAS_LIMIT, + CHARLIE.encode(), + )); + + // Check that CHARLIE has moved on to the great beyond (ie. died). + assert!(ContractInfoOf::::get(CHARLIE).is_none()); + }); } -fn get_runtime_storage() { - let (wasm, code_hash) = compile_module::(&load_wasm("get_runtime_storage.wat")) - .unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - - frame_support::storage::unhashed::put_raw( - &[1, 2, 3, 4], - 0x14144020u32.to_le_bytes().to_vec().as_ref() - ); +#[test] +fn cannot_self_destruct_in_constructor() { + let (wasm, code_hash) = compile_module::("self_destructing_constructor").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - assert_ok!(Contracts::call( - Origin::signed(ALICE), - BOB, - 0, - GAS_LIMIT, - vec![], - )); - }); + // Fail to instantiate the BOB because the call that is issued in the deploy + // function exhausts all balances which puts it below the existential deposit. + assert_err_ignore_postinfo!( + Contracts::instantiate( + Origin::signed(ALICE), + 100_000, + GAS_LIMIT, + code_hash.into(), + vec![], + ), + "contract trapped during execution" + ); + }); } #[test] -fn crypto_hashes() { - let (wasm, code_hash) = compile_module::(&load_wasm("crypto_hashes.wat")).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); - - // Instantiate the CRYPTO_HASHES contract. - assert_ok!(Contracts::instantiate( - Origin::signed(ALICE), - 100_000, - GAS_LIMIT, - code_hash.into(), - vec![], - )); - // Perform the call. - let input = b"_DEAD_BEEF"; - use sp_io::hashing::*; - // Wraps a hash function into a more dynamic form usable for testing. - macro_rules! dyn_hash_fn { - ($name:ident) => { - Box::new(|input| $name(input).as_ref().to_vec().into_boxed_slice()) - }; - } - // All hash functions and their associated output byte lengths. - let test_cases: &[(Box Box<[u8]>>, usize)] = &[ - (dyn_hash_fn!(sha2_256), 32), - (dyn_hash_fn!(keccak_256), 32), - (dyn_hash_fn!(blake2_256), 32), - (dyn_hash_fn!(blake2_128), 16), - ]; - // Test the given hash functions for the input: "_DEAD_BEEF" - for (n, (hash_fn, expected_size)) in test_cases.iter().enumerate() { - // We offset data in the contract tables by 1. - let mut params = vec![(n + 1) as u8]; - params.extend_from_slice(input); - let result = >::bare_call( - ALICE, +fn get_runtime_storage() { + let (wasm, code_hash) = compile_module::("get_runtime_storage").unwrap(); + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + + frame_support::storage::unhashed::put_raw( + &[1, 2, 3, 4], + 0x14144020u32.to_le_bytes().to_vec().as_ref() + ); + + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + GAS_LIMIT, + code_hash.into(), + vec![], + )); + assert_ok!(Contracts::call( + Origin::signed(ALICE), BOB, 0, GAS_LIMIT, - params, - ).unwrap(); - assert_eq!(result.status, 0); - let expected = hash_fn(input.as_ref()); - assert_eq!(&result.data[..*expected_size], &*expected); - } - }) + vec![], + )); + }); } -fn load_wasm(file_name: &str) -> String { - let path = ["tests/", file_name].concat(); - std::fs::read_to_string(&path).expect(&format!("Unable to read {} file", path)) +#[test] +fn crypto_hashes() { + let (wasm, code_hash) = compile_module::("crypto_hashes").unwrap(); + + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let _ = Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); + + // Instantiate the CRYPTO_HASHES contract. + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100_000, + GAS_LIMIT, + code_hash.into(), + vec![], + )); + // Perform the call. + let input = b"_DEAD_BEEF"; + use sp_io::hashing::*; + // Wraps a hash function into a more dynamic form usable for testing. + macro_rules! dyn_hash_fn { + ($name:ident) => { + Box::new(|input| $name(input).as_ref().to_vec().into_boxed_slice()) + }; + } + // All hash functions and their associated output byte lengths. + let test_cases: &[(Box Box<[u8]>>, usize)] = &[ + (dyn_hash_fn!(sha2_256), 32), + (dyn_hash_fn!(keccak_256), 32), + (dyn_hash_fn!(blake2_256), 32), + (dyn_hash_fn!(blake2_128), 16), + ]; + // Test the given hash functions for the input: "_DEAD_BEEF" + for (n, (hash_fn, expected_size)) in test_cases.iter().enumerate() { + // We offset data in the contract tables by 1. + let mut params = vec![(n + 1) as u8]; + params.extend_from_slice(input); + let result = >::bare_call( + ALICE, + BOB, + 0, + GAS_LIMIT, + params, + ).unwrap(); + assert_eq!(result.status, 0); + let expected = hash_fn(input.as_ref()); + assert_eq!(&result.data[..*expected_size], &*expected); + } + }) } diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 83caa671cee958d28c68a06b744215b69a351def..433c37e4d8b73bf108210f4331e9b6f766f6b182 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-democracy" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for democracy" @@ -14,18 +14,19 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -pallet-scheduler = { version = "2.0.0-dev", path = "../scheduler" } -sp-storage = { version = "2.0.0-dev", path = "../../primitives/storage" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +pallet-scheduler = { version = "2.0.0-rc2", path = "../scheduler" } +sp-storage = { version = "2.0.0-rc2", path = "../../primitives/storage" } +substrate-test-utils = { version = "2.0.0-rc2", path = "../../test-utils" } hex-literal = "0.2.1" [features] @@ -43,5 +44,6 @@ std = [ runtime-benchmarks = [ "frame-benchmarking", "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/frame/democracy/src/benchmarking.rs b/frame/democracy/src/benchmarking.rs index d56113846545b912f7fd5821fffb75a8f706b684..9fa619a994fa32aca63292b8cffaedc9c79653bb 100644 --- a/frame/democracy/src/benchmarking.rs +++ b/frame/democracy/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Democracy pallet benchmarking. @@ -33,7 +34,6 @@ const MAX_USERS: u32 = 1000; const MAX_REFERENDUMS: u32 = 100; const MAX_PROPOSALS: u32 = 100; const MAX_SECONDERS: u32 = 100; -const MAX_VETOERS: u32 = 100; const MAX_BYTES: u32 = 16_384; fn assert_last_event(generic_event: ::Event) { @@ -55,7 +55,11 @@ fn add_proposal(n: u32) -> Result { let value = T::MinimumDeposit::get(); let proposal_hash: T::Hash = T::Hashing::hash_of(&n); - Democracy::::propose(RawOrigin::Signed(other).into(), proposal_hash, value.into())?; + Democracy::::propose( + RawOrigin::Signed(other).into(), + proposal_hash, + value.into(), + )?; Ok(proposal_hash) } @@ -133,15 +137,15 @@ benchmarks! { // Create s existing "seconds" for i in 0 .. s { let seconder = funded_account::("seconder", i); - Democracy::::second(RawOrigin::Signed(seconder).into(), 0)?; + Democracy::::second(RawOrigin::Signed(seconder).into(), 0, u32::max_value())?; } let deposits = Democracy::::deposit_of(0).ok_or("Proposal not created")?; - assert_eq!(deposits.1.len(), (s + 1) as usize, "Seconds not recorded"); - }: _(RawOrigin::Signed(caller), 0) + assert_eq!(deposits.0.len(), (s + 1) as usize, "Seconds not recorded"); + }: _(RawOrigin::Signed(caller), 0, u32::max_value()) verify { let deposits = Democracy::::deposit_of(0).ok_or("Proposal not created")?; - assert_eq!(deposits.1.len(), (s + 2) as usize, "`second` benchmark did not work"); + assert_eq!(deposits.0.len(), (s + 2) as usize, "`second` benchmark did not work"); } vote_new { @@ -299,7 +303,7 @@ benchmarks! { // Worst case scenario, we external propose a previously blacklisted proposal external_propose { let p in 1 .. MAX_PROPOSALS; - let v in 1 .. MAX_VETOERS; + let v in 1 .. MAX_VETOERS as u32; let origin = T::ExternalOrigin::successful_origin(); let proposal_hash = T::Hashing::hash_of(&p); @@ -360,7 +364,7 @@ benchmarks! { veto_external { // Existing veto-ers - let v in 0 .. MAX_VETOERS; + let v in 0 .. MAX_VETOERS as u32; let proposal_hash: T::Hash = T::Hashing::hash_of(&v); @@ -684,7 +688,7 @@ benchmarks! { assert!(Preimages::::contains_key(proposal_hash)); let caller = funded_account::("caller", 0); - }: _(RawOrigin::Signed(caller), proposal_hash.clone()) + }: _(RawOrigin::Signed(caller), proposal_hash.clone(), u32::max_value()) verify { let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); assert!(!Preimages::::contains_key(proposal_hash)); diff --git a/frame/democracy/src/conviction.rs b/frame/democracy/src/conviction.rs index a057ee2a357503d0a51648874b92a9006c3d1087..bb563e4b74830b24bf789454a3fe36de3a3e0e0c 100644 --- a/frame/democracy/src/conviction.rs +++ b/frame/democracy/src/conviction.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The conviction datatype. diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index a182907aba222856293bd681412ac9669295db89..580e80cce0e676ee4bb50333c0c114ba3ff7d3be 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Democracy Pallet //! @@ -107,8 +108,10 @@ //! Preimage actions: //! - `note_preimage` - Registers the preimage for an upcoming proposal, requires //! a deposit that is returned once the proposal is enacted. +//! - `note_preimage_operational` - same but provided by `T::OperationalPreimageOrigin`. //! - `note_imminent_preimage` - Registers the preimage for an upcoming proposal. //! Does not require a deposit, but the proposal must be in the dispatch queue. +//! - `note_imminent_preimage_operational` - same but provided by `T::OperationalPreimageOrigin`. //! - `reap_preimage` - Removes the preimage for an expired proposal. Will only //! work under the condition that it's the same account that noted it and //! after the voting period, OR it's a different account after the enactment period. @@ -168,14 +171,16 @@ use sp_runtime::{ DispatchResult, DispatchError, RuntimeDebug, traits::{Zero, Hash, Dispatchable, Saturating}, }; -use codec::{Encode, Decode}; +use codec::{Encode, Decode, Input}; use frame_support::{ decl_module, decl_storage, decl_event, decl_error, ensure, Parameter, + storage::IterableStorageMap, weights::{Weight, DispatchClass}, traits::{ Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get, OnUnbalanced, BalanceStatus, schedule::Named as ScheduleNamed, EnsureOrigin - } + }, + dispatch::DispatchResultWithPostInfo, }; use frame_system::{self as system, ensure_signed, ensure_root}; @@ -196,6 +201,11 @@ pub mod benchmarking; const DEMOCRACY_ID: LockIdentifier = *b"democrac"; +/// The maximum number of vetoers on a single proposal used to compute Weight. +/// +/// NOTE: This is not enforced by any logic. +pub const MAX_VETOERS: Weight = 100; + /// A proposal index. pub type PropIndex = u32; @@ -264,6 +274,11 @@ pub trait Trait: frame_system::Trait + Sized { type CancellationOrigin: EnsureOrigin; /// Origin for anyone able to veto proposals. + /// + /// # Warning + /// + /// The number of Vetoers for a proposal must be small, extrinsics are weighted according to + /// [MAX_VETOERS](./const.MAX_VETOERS.html) type VetoOrigin: EnsureOrigin; /// Period in blocks where an external proposal may not be re-submitted after being vetoed. @@ -272,11 +287,20 @@ pub trait Trait: frame_system::Trait + Sized { /// The amount of balance that must be deposited per byte of preimage stored. type PreimageByteDeposit: Get>; + /// An origin that can provide a preimage using operational extrinsics. + type OperationalPreimageOrigin: EnsureOrigin; + /// Handler for the unbalanced reduction when slashing a preimage deposit. type Slash: OnUnbalanced>; /// The Scheduler. type Scheduler: ScheduleNamed; + + /// The maximum number of votes for an account. + /// + /// Also used to compute weight, an overly big value can + /// lead to extrinsic with very big weight: see `delegate` for instance. + type MaxVotes: Get; } #[derive(Clone, Encode, Decode, RuntimeDebug)] @@ -303,6 +327,14 @@ impl PreimageStatus as Democracy { // TODO: Refactor public proposal queue into its own pallet. @@ -312,8 +344,10 @@ decl_storage! { /// The public proposals. Unsorted. The second item is the proposal's hash. pub PublicProps get(fn public_props): Vec<(PropIndex, T::Hash, T::AccountId)>; /// Those who have locked a deposit. + /// + /// TWOX-NOTE: Safe, as increasing integer keys are safe. pub DepositOf get(fn deposit_of): - map hasher(twox_64_concat) PropIndex => Option<(BalanceOf, Vec)>; + map hasher(twox_64_concat) PropIndex => Option<(Vec, BalanceOf)>; /// Map of hashes to the proposal preimage, along with who registered it and their deposit. /// The block number is the block at which it was deposited. @@ -330,22 +364,30 @@ decl_storage! { pub LowestUnbaked get(fn lowest_unbaked) build(|_| 0 as ReferendumIndex): ReferendumIndex; /// Information concerning any given referendum. + /// + /// TWOX-NOTE: SAFE as indexes are not under an attacker’s control. pub ReferendumInfoOf get(fn referendum_info): map hasher(twox_64_concat) ReferendumIndex => Option>>; /// All votes for a particular voter. We store the balance for the number of votes that we /// have recorded. The second item is the total amount of delegations, that will be added. + /// + /// TWOX-NOTE: SAFE as `AccountId`s are crypto hashes anyway. pub VotingOf: map hasher(twox_64_concat) T::AccountId => Voting, T::AccountId, T::BlockNumber>; /// Who is able to vote for whom. Value is the fund-holding account, key is the /// vote-transaction-sending account. + /// + /// TWOX-NOTE: OK ― `AccountId` is a secure hash. // TODO: Refactor proxy into its own pallet. // https://github.com/paritytech/substrate/issues/5322 pub Proxy get(fn proxy): map hasher(twox_64_concat) T::AccountId => Option>; /// Accounts for which there are locks in action which may be removed at some point in the /// future. The value is the block number at which the lock expires and may be removed. + /// + /// TWOX-NOTE: OK ― `AccountId` is a secure hash. pub Locks get(fn locks): map hasher(twox_64_concat) T::AccountId => Option; /// True if the last referendum tabled was submitted externally. False if it was a public @@ -367,6 +409,11 @@ decl_storage! { /// Record of all proposals that have been subject to emergency cancellation. pub Cancellations: map hasher(identity) T::Hash => bool; + + /// Storage version of the pallet. + /// + /// New networks start with last version. + StorageVersion build(|_| Some(Releases::V1)): Option; } } @@ -491,6 +538,88 @@ decl_error! { InstantNotAllowed, /// Delegation to oneself makes no sense. Nonsense, + /// Invalid upper bound. + WrongUpperBound, + /// Maximum number of votes reached. + MaxVotesReached, + } +} + +/// Functions for calcuating the weight of some dispatchables. +mod weight_for { + use frame_support::{traits::Get, weights::Weight}; + use super::Trait; + + /// Calculate the weight for `delegate`. + /// - Db reads: 2*`VotingOf`, `balances locks` + /// - Db writes: 2*`VotingOf`, `balances locks` + /// - Db reads per votes: `ReferendumInfoOf` + /// - Db writes per votes: `ReferendumInfoOf` + /// - Base Weight: 65.78 + 8.229 * R µs + // NOTE: weight must cover an incorrect voting of origin with 100 votes. + pub fn delegate(votes: Weight) -> Weight { + T::DbWeight::get().reads_writes(votes.saturating_add(3), votes.saturating_add(3)) + .saturating_add(66_000_000) + .saturating_add(votes.saturating_mul(8_100_000)) + } + + /// Calculate the weight for `undelegate`. + /// - Db reads: 2*`VotingOf` + /// - Db writes: 2*`VotingOf` + /// - Db reads per votes: `ReferendumInfoOf` + /// - Db writes per votes: `ReferendumInfoOf` + /// - Base Weight: 33.29 + 8.104 * R µs + pub fn undelegate(votes: Weight) -> Weight { + T::DbWeight::get().reads_writes(votes.saturating_add(2), votes.saturating_add(2)) + .saturating_add(33_000_000) + .saturating_add(votes.saturating_mul(8_000_000)) + } + + /// Calculate the weight for `proxy_delegate`. + /// same as `delegate with additional: + /// - Db reads: `Proxy`, `proxy account` + /// - Db writes: `proxy account` + /// - Base Weight: 68.61 + 8.039 * R µs + pub fn proxy_delegate(votes: Weight) -> Weight { + T::DbWeight::get().reads_writes(votes.saturating_add(5), votes.saturating_add(4)) + .saturating_add(69_000_000) + .saturating_add(votes.saturating_mul(8_000_000)) + } + + /// Calculate the weight for `proxy_undelegate`. + /// same as `undelegate with additional: + /// Db reads: `Proxy` + /// Base Weight: 39 + 7.958 * R µs + pub fn proxy_undelegate(votes: Weight) -> Weight { + T::DbWeight::get().reads_writes(votes.saturating_add(3), votes.saturating_add(2)) + .saturating_add(40_000_000) + .saturating_add(votes.saturating_mul(8_000_000)) + } + + /// Calculate the weight for `note_preimage`. + /// # + /// - Complexity: `O(E)` with E size of `encoded_proposal` (protected by a required deposit). + /// - Db reads: `Preimages` + /// - Db writes: `Preimages` + /// - Base Weight: 37.93 + .004 * b µs + /// # + pub fn note_preimage(encoded_proposal_len: Weight) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + .saturating_add(38_000_000) + .saturating_add(encoded_proposal_len.saturating_mul(4_000)) + } + + /// Calculate the weight for `note_imminent_preimage`. + /// # + /// - Complexity: `O(E)` with E size of `encoded_proposal` (protected by a required deposit). + /// - Db reads: `Preimages` + /// - Db writes: `Preimages` + /// - Base Weight: 28.04 + .003 * b µs + /// # + pub fn note_imminent_preimage(encoded_proposal_len: Weight) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + .saturating_add(28_000_000) + .saturating_add(encoded_proposal_len.saturating_mul(3_000)) } } @@ -523,8 +652,27 @@ decl_module! { /// The amount of balance that must be deposited per byte of preimage stored. const PreimageByteDeposit: BalanceOf = T::PreimageByteDeposit::get(); + /// The maximum number of votes for an account. + const MaxVotes: u32 = T::MaxVotes::get(); + fn deposit_event() = default; + fn on_runtime_upgrade() -> Weight { + if let None = StorageVersion::get() { + StorageVersion::put(Releases::V1); + + DepositOf::::translate::< + (BalanceOf, Vec), _ + >(|_, (balance, accounts)| { + Some((accounts, balance)) + }); + + T::MaximumBlockWeight::get() + } else { + T::DbWeight::get().reads(1) + } + } + /// Propose a sensitive action to be taken. /// /// The dispatch origin of this call must be _Signed_ and the sender must @@ -536,22 +684,22 @@ decl_module! { /// Emits `Proposed`. /// /// # - /// - `O(P)` - /// - P is the number proposals in the `PublicProps` vec. - /// - Two DB changes, one DB entry. + /// - Complexity: `O(1)` + /// - Db reads: `PublicPropCount`, `PublicProps` + /// - Db writes: `PublicPropCount`, `PublicProps`, `DepositOf` + /// ------------------- + /// Base Weight: 42.58 + .127 * P µs with `P` the number of proposals `PublicProps` /// # - #[weight = 5_000_000_000] - fn propose(origin, - proposal_hash: T::Hash, - #[compact] value: BalanceOf - ) { + #[weight = 50_000_000 + T::DbWeight::get().reads_writes(2, 3)] + fn propose(origin, proposal_hash: T::Hash, #[compact] value: BalanceOf) { let who = ensure_signed(origin)?; ensure!(value >= T::MinimumDeposit::get(), Error::::ValueLow); + T::Currency::reserve(&who, value)?; let index = Self::public_prop_count(); PublicPropCount::put(index + 1); - >::insert(index, (value, &[&who][..])); + >::insert(index, (&[&who][..], value)); >::append((index, proposal_hash, who)); @@ -564,19 +712,30 @@ decl_module! { /// must have funds to cover the deposit, equal to the original deposit. /// /// - `proposal`: The index of the proposal to second. + /// - `seconds_upper_bound`: an upper bound on the current number of seconds on this + /// proposal. Extrinsic is weighted according to this value with no refund. /// /// # - /// - `O(S)`. - /// - S is the number of seconds a proposal already has. - /// - One DB entry. + /// - Complexity: `O(S)` where S is the number of seconds a proposal already has. + /// - Db reads: `DepositOf` + /// - Db writes: `DepositOf` + /// --------- + /// - Base Weight: 22.28 + .229 * S µs /// # - #[weight = 5_000_000_000] - fn second(origin, #[compact] proposal: PropIndex) { + #[weight = 23_000_000 + .saturating_add(230_000.saturating_mul(Weight::from(*seconds_upper_bound))) + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) + ] + fn second(origin, #[compact] proposal: PropIndex, #[compact] seconds_upper_bound: u32) { let who = ensure_signed(origin)?; + + let seconds = Self::len_of_deposit_of(proposal) + .ok_or_else(|| Error::::ProposalMissing)?; + ensure!(seconds <= seconds_upper_bound, Error::::WrongUpperBound); let mut deposit = Self::deposit_of(proposal) .ok_or(Error::::ProposalMissing)?; - T::Currency::reserve(&who, deposit.0)?; - deposit.1.push(who); + T::Currency::reserve(&who, deposit.1)?; + deposit.0.push(who); >::insert(proposal, deposit); } @@ -589,11 +748,16 @@ decl_module! { /// - `vote`: The vote configuration. /// /// # - /// - `O(R)`. - /// - R is the number of referendums the voter has voted on. - /// - One DB change, one DB entry. + /// - Complexity: `O(R)` where R is the number of referendums the voter has voted on. + /// weight is charged as if maximum votes. + /// - Db reads: `ReferendumInfoOf`, `VotingOf`, `balances locks` + /// - Db writes: `ReferendumInfoOf`, `VotingOf`, `balances locks` + /// -------------------- + /// - Base Weight: + /// - Vote New: 49.24 + .333 * R µs + /// - Vote Existing: 49.94 + .343 * R µs /// # - #[weight = 200_000_000] + #[weight = 50_000_000 + 350_000 * Weight::from(T::MaxVotes::get()) + T::DbWeight::get().reads_writes(3, 3)] fn vote(origin, #[compact] ref_index: ReferendumIndex, vote: AccountVote>, @@ -611,10 +775,16 @@ decl_module! { /// - `vote`: The vote configuration. /// /// # - /// - `O(1)`. - /// - One DB change, one DB entry. + /// - Complexity: `O(R)` where R is the number of referendums the proxy has voted on. + /// weight is charged as if maximum votes. + /// - Db reads: `ReferendumInfoOf`, `VotingOf`, `balances locks`, `Proxy`, `proxy account` + /// - Db writes: `ReferendumInfoOf`, `VotingOf`, `balances locks` + /// ------------ + /// - Base Weight: + /// - Proxy Vote New: 54.35 + .344 * R µs + /// - Proxy Vote Existing: 54.35 + .35 * R µs /// # - #[weight = 200_000_000] + #[weight = 55_000_000 + 350_000 * Weight::from(T::MaxVotes::get()) + T::DbWeight::get().reads_writes(5, 3)] fn proxy_vote(origin, #[compact] ref_index: ReferendumIndex, vote: AccountVote>, @@ -632,9 +802,13 @@ decl_module! { /// -`ref_index`: The index of the referendum to cancel. /// /// # - /// - `O(1)`. + /// - Complexity: `O(1)`. + /// - Db reads: `ReferendumInfoOf`, `Cancellations` + /// - Db writes: `ReferendumInfoOf`, `Cancellations` + /// ------------- + /// - Base Weight: 34.25 µs /// # - #[weight = (500_000_000, DispatchClass::Operational)] + #[weight = (35_000_000 + T::DbWeight::get().reads_writes(2, 2), DispatchClass::Operational)] fn emergency_cancel(origin, ref_index: ReferendumIndex) { T::CancellationOrigin::ensure_origin(origin)?; @@ -654,10 +828,13 @@ decl_module! { /// - `proposal_hash`: The preimage hash of the proposal. /// /// # - /// - `O(1)`. - /// - One DB change. + /// - Complexity `O(V)` with V number of vetoers in the blacklist of proposal. + /// Decoding vec of length V. Charged as maximum + /// - Db reads: `NextExternal`, `Blacklist` + /// - Db writes: `NextExternal` + /// - Base Weight: 13.8 + .106 * V µs /// # - #[weight = 5_000_000_000] + #[weight = 15_000_000 + 110_000 * MAX_VETOERS + T::DbWeight::get().reads_writes(2, 1)] fn external_propose(origin, proposal_hash: T::Hash) { T::ExternalOrigin::ensure_origin(origin)?; ensure!(!>::exists(), Error::::DuplicateProposal); @@ -681,10 +858,11 @@ decl_module! { /// pre-scheduled `external_propose` call. /// /// # - /// - `O(1)`. - /// - One DB change. + /// - Complexity: `O(1)` + /// - Db write: `NextExternal` + /// - Base Weight: 3.065 µs /// # - #[weight = 5_000_000_000] + #[weight = 3_100_000 + T::DbWeight::get().writes(1)] fn external_propose_majority(origin, proposal_hash: T::Hash) { T::ExternalMajorityOrigin::ensure_origin(origin)?; >::put((proposal_hash, VoteThreshold::SimpleMajority)); @@ -701,10 +879,11 @@ decl_module! { /// pre-scheduled `external_propose` call. /// /// # - /// - `O(1)`. - /// - One DB change. + /// - Complexity: `O(1)` + /// - Db write: `NextExternal` + /// - Base Weight: 3.087 µs /// # - #[weight = 5_000_000_000] + #[weight = 3_100_000 + T::DbWeight::get().writes(1)] fn external_propose_default(origin, proposal_hash: T::Hash) { T::ExternalDefaultOrigin::ensure_origin(origin)?; >::put((proposal_hash, VoteThreshold::SuperMajorityAgainst)); @@ -725,11 +904,12 @@ decl_module! { /// Emits `Started`. /// /// # - /// - One DB clear. - /// - One DB change. - /// - One extra DB entry. + /// - Complexity: `O(1)` + /// - Db reads: `NextExternal`, `ReferendumCount` + /// - Db writes: `NextExternal`, `ReferendumCount`, `ReferendumInfoOf` + /// - Base Weight: 30.1 µs /// # - #[weight = 200_000_000] + #[weight = 30_000_000 + T::DbWeight::get().reads_writes(2, 3)] fn fast_track(origin, proposal_hash: T::Hash, voting_period: T::BlockNumber, @@ -774,13 +954,13 @@ decl_module! { /// Emits `Vetoed`. /// /// # - /// - Two DB entries. - /// - One DB clear. - /// - Performs a binary search on `existing_vetoers` which should not - /// be very large. - /// - O(log v), v is number of `existing_vetoers` + /// - Complexity: `O(V + log(V))` where V is number of `existing vetoers` + /// Performs a binary search on `existing_vetoers` which should not be very large. + /// - Db reads: `NextExternal`, `Blacklist` + /// - Db writes: `NextExternal`, `Blacklist` + /// - Base Weight: 29.87 + .188 * V µs /// # - #[weight = 200_000_000] + #[weight = 30_000_000 + 180_000 * MAX_VETOERS + T::DbWeight::get().reads_writes(2, 2)] fn veto_external(origin, proposal_hash: T::Hash) { let who = T::VetoOrigin::ensure_origin(origin)?; @@ -811,9 +991,11 @@ decl_module! { /// - `ref_index`: The index of the referendum to cancel. /// /// # - /// - `O(1)`. + /// - Complexity: `O(1)`. + /// - Db writes: `ReferendumInfoOf` + /// - Base Weight: 21.57 µs /// # - #[weight = (0, DispatchClass::Operational)] + #[weight = (22_000_000 + T::DbWeight::get().writes(1), DispatchClass::Operational)] fn cancel_referendum(origin, #[compact] ref_index: ReferendumIndex) { ensure_root(origin)?; Self::internal_cancel_referendum(ref_index); @@ -826,22 +1008,24 @@ decl_module! { /// - `which`: The index of the referendum to cancel. /// /// # - /// - One DB change. - /// - O(d) where d is the items in the dispatch queue. + /// - `O(D)` where `D` is the items in the dispatch queue. Weighted as `D = 10`. + /// - Db reads: `scheduler lookup`, scheduler agenda` + /// - Db writes: `scheduler lookup`, scheduler agenda` + /// - Base Weight: 36.78 + 3.277 * D µs /// # - #[weight = (0, DispatchClass::Operational)] + #[weight = (68_000_000 + T::DbWeight::get().reads_writes(2, 2), DispatchClass::Operational)] fn cancel_queued(origin, which: ReferendumIndex) { ensure_root(origin)?; T::Scheduler::cancel_named((DEMOCRACY_ID, which).encode()) .map_err(|_| Error::::ProposalMissing)?; } + /// Weight: see `begin_block` fn on_initialize(n: T::BlockNumber) -> Weight { - if let Err(e) = Self::begin_block(n) { + Self::begin_block(n).unwrap_or_else(|e| { sp_runtime::print(e); - } - - 0 + 0 + }) } /// Specify a proxy that is already open to us. Called by the stash. @@ -853,9 +1037,12 @@ decl_module! { /// - `proxy`: The account that will be activated as proxy. /// /// # - /// - One extra DB entry. + /// - Complexity: `O(1)` + /// - Db reads: `Proxy` + /// - Db writes: `Proxy` + /// - Base Weight: 7.972 µs /// # - #[weight = 100_000_000] + #[weight = 8_000_000 + T::DbWeight::get().reads_writes(1, 1)] fn activate_proxy(origin, proxy: T::AccountId) { let who = ensure_signed(origin)?; Proxy::::try_mutate(&proxy, |a| match a.take() { @@ -876,9 +1063,12 @@ decl_module! { /// The dispatch origin of this call must be _Signed_. /// /// # - /// - One DB clear. + /// - Complexity: `O(1)` + /// - Db reads: `Proxy`, `sender account` + /// - Db writes: `Proxy`, `sender account` + /// - Base Weight: 15.41 µs /// # - #[weight = 100_000_000] + #[weight = 16_000_000 + T::DbWeight::get().reads_writes(1, 1)] fn close_proxy(origin) { let who = ensure_signed(origin)?; Proxy::::mutate(&who, |a| { @@ -900,9 +1090,12 @@ decl_module! { /// - `proxy`: The account that will be deactivated as proxy. /// /// # - /// - One DB clear. + /// - Complexity: `O(1)` + /// - Db reads: `Proxy` + /// - Db writes: `Proxy` + /// - Base Weight: 8.03 µs /// # - #[weight = 100_000_000] + #[weight = 8_000_000 + T::DbWeight::get().reads_writes(1, 1)] fn deactivate_proxy(origin, proxy: T::AccountId) { let who = ensure_signed(origin)?; Proxy::::try_mutate(&proxy, |a| match a.take() { @@ -934,11 +1127,26 @@ decl_module! { /// Emits `Delegated`. /// /// # + /// - Complexity: `O(R)` where R is the number of referendums the voter delegating to has + /// voted on. Weight is charged as if maximum votes. + /// - Db reads: 2*`VotingOf`, `balances locks` + /// - Db writes: 2*`VotingOf`, `balances locks` + /// - Db reads per votes: `ReferendumInfoOf` + /// - Db writes per votes: `ReferendumInfoOf` + /// - Base Weight: 65.78 + 8.229 * R µs + // NOTE: weight must cover an incorrect voting of origin with 100 votes. /// # - #[weight = 500_000_000] - pub fn delegate(origin, to: T::AccountId, conviction: Conviction, balance: BalanceOf) { + #[weight = weight_for::delegate::(T::MaxVotes::get().into())] + pub fn delegate( + origin, + to: T::AccountId, + conviction: Conviction, + balance: BalanceOf + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - Self::try_delegate(who, to, conviction, balance)?; + let votes = Self::try_delegate(who, to, conviction, balance)?; + + Ok(Some(weight_for::delegate::(votes.into())).into()) } /// Undelegate the voting power of the sending account. @@ -952,12 +1160,20 @@ decl_module! { /// Emits `Undelegated`. /// /// # - /// - O(1). + /// - Complexity: `O(R)` where R is the number of referendums the voter delegating to has + /// voted on. Weight is charged as if maximum votes. + /// - Db reads: 2*`VotingOf` + /// - Db writes: 2*`VotingOf` + /// - Db reads per votes: `ReferendumInfoOf` + /// - Db writes per votes: `ReferendumInfoOf` + /// - Base Weight: 33.29 + 8.104 * R µs + // NOTE: weight must cover an incorrect voting of origin with 100 votes. /// # - #[weight = 500_000_000] - fn undelegate(origin) { + #[weight = weight_for::undelegate::(T::MaxVotes::get().into())] + fn undelegate(origin) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - Self::try_undelegate(who)?; + let votes = Self::try_undelegate(who)?; + Ok(Some(weight_for::undelegate::(votes.into())).into()) } /// Clears all public proposals. @@ -966,12 +1182,12 @@ decl_module! { /// /// # /// - `O(1)`. - /// - One DB clear. + /// - Db writes: `PublicProps` + /// - Base Weight: 2.505 µs /// # - #[weight = 0] + #[weight = 2_500_000 + T::DbWeight::get().writes(1)] fn clear_public_proposals(origin) { ensure_root(origin)?; - >::kill(); } @@ -985,30 +1201,21 @@ decl_module! { /// Emits `PreimageNoted`. /// /// # - /// - Dependent on the size of `encoded_proposal` but protected by a - /// required deposit. + /// see `weight_for::note_preimage` /// # - #[weight = 100_000_000] + #[weight = weight_for::note_preimage::((encoded_proposal.len() as u32).into())] fn note_preimage(origin, encoded_proposal: Vec) { - let who = ensure_signed(origin)?; - let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); - ensure!(!>::contains_key(&proposal_hash), Error::::DuplicatePreimage); - - let deposit = >::from(encoded_proposal.len() as u32) - .saturating_mul(T::PreimageByteDeposit::get()); - T::Currency::reserve(&who, deposit)?; - - let now = >::block_number(); - let a = PreimageStatus::Available { - data: encoded_proposal, - provider: who.clone(), - deposit, - since: now, - expiry: None, - }; - >::insert(proposal_hash, a); + Self::note_preimage_inner(ensure_signed(origin)?, encoded_proposal)?; + } - Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, deposit)); + /// Same as `note_preimage` but origin is `OperationalPreimageOrigin`. + #[weight = ( + weight_for::note_preimage::((encoded_proposal.len() as u32).into()), + DispatchClass::Operational, + )] + fn note_preimage_operational(origin, encoded_proposal: Vec) { + let who = T::OperationalPreimageOrigin::ensure_origin(origin)?; + Self::note_preimage_inner(who, encoded_proposal)?; } /// Register the preimage for an upcoming proposal. This requires the proposal to be @@ -1021,27 +1228,21 @@ decl_module! { /// Emits `PreimageNoted`. /// /// # - /// - Dependent on the size of `encoded_proposal` and length of dispatch queue. + /// see `weight_for::note_preimage` /// # - #[weight = 100_000_000] + #[weight = weight_for::note_imminent_preimage::((encoded_proposal.len() as u32).into())] fn note_imminent_preimage(origin, encoded_proposal: Vec) { - let who = ensure_signed(origin)?; - let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); - let status = Preimages::::get(&proposal_hash).ok_or(Error::::NotImminent)?; - let expiry = status.to_missing_expiry().ok_or(Error::::DuplicatePreimage)?; - - let now = >::block_number(); - let free = >::zero(); - let a = PreimageStatus::Available { - data: encoded_proposal, - provider: who.clone(), - deposit: Zero::zero(), - since: now, - expiry: Some(expiry), - }; - >::insert(proposal_hash, a); + Self::note_imminent_preimage_inner(ensure_signed(origin)?, encoded_proposal)?; + } - Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, free)); + /// Same as `note_imminent_preimage` but origin is `OperationalPreimageOrigin`. + #[weight = ( + weight_for::note_imminent_preimage::((encoded_proposal.len() as u32).into()), + DispatchClass::Operational, + )] + fn note_imminent_preimage_operational(origin, encoded_proposal: Vec) { + let who = T::OperationalPreimageOrigin::ensure_origin(origin)?; + Self::note_imminent_preimage_inner(who, encoded_proposal)?; } /// Remove an expired proposal preimage and collect the deposit. @@ -1049,6 +1250,8 @@ decl_module! { /// The dispatch origin of this call must be _Signed_. /// /// - `proposal_hash`: The preimage hash of a proposal. + /// - `proposal_length_upper_bound`: an upper bound on length of the proposal. + /// Extrinsic is weighted according to this value with no refund. /// /// This will only work after `VotingPeriod` blocks from the time that the preimage was /// noted, if it's the same account doing it. If it's a different account, then it'll only @@ -1057,11 +1260,21 @@ decl_module! { /// Emits `PreimageReaped`. /// /// # - /// - One DB clear. + /// - Complexity: `O(D)` where D is length of proposal. + /// - Db reads: `Preimages` + /// - Db writes: `Preimages` + /// - Base Weight: 39.31 + .003 * b µs /// # - #[weight = 0] - fn reap_preimage(origin, proposal_hash: T::Hash) { + #[weight = (39_000_000 + T::DbWeight::get().reads_writes(1, 1)) + .saturating_add(3_000.saturating_mul(Weight::from(*proposal_len_upper_bound)))] + fn reap_preimage(origin, proposal_hash: T::Hash, #[compact] proposal_len_upper_bound: u32) { let who = ensure_signed(origin)?; + + ensure!( + Self::pre_image_data_len(proposal_hash)? <= proposal_len_upper_bound, + Error::::WrongUpperBound, + ); + let (provider, deposit, since, expiry) = >::get(&proposal_hash) .and_then(|m| match m { PreimageStatus::Available { provider, deposit, since, expiry, .. } @@ -1087,9 +1300,15 @@ decl_module! { /// - `target`: The account to remove the lock on. /// /// # - /// - `O(1)`. + /// - Complexity `O(R)` with R number of vote of target. + /// - Db reads: `VotingOf`, `balances locks`, `target account` + /// - Db writes: `VotingOf`, `balances locks`, `target account` + /// - Base Weight: + /// - Unlock Remove: 42.96 + .048 * R + /// - Unlock Set: 37.63 + .327 * R /// # - #[weight = 0] + #[weight = 43_000_000 + 330_000 * Weight::from(T::MaxVotes::get()) + + T::DbWeight::get().reads_writes(3, 3)] fn unlock(origin, target: T::AccountId) { ensure_signed(origin)?; Self::update_lock(&target); @@ -1106,9 +1325,12 @@ decl_module! { /// `close_proxy` must be called before the account can be destroyed. /// /// # - /// - One extra DB entry. + /// - Complexity: O(1) + /// - Db reads: `Proxy`, `proxy account` + /// - Db writes: `Proxy`, `proxy account` + /// - Base Weight: 14.86 µs /// # - #[weight = 100_000_000] + #[weight = 15_000_000 + T::DbWeight::get().reads_writes(2, 2)] fn open_proxy(origin, target: T::AccountId) { let who = ensure_signed(origin)?; Proxy::::mutate(&who, |a| { @@ -1146,8 +1368,12 @@ decl_module! { /// /// # /// - `O(R + log R)` where R is the number of referenda that `target` has voted on. + /// Weight is calculated for the maximum number of vote. + /// - Db reads: `ReferendumInfoOf`, `VotingOf` + /// - Db writes: `ReferendumInfoOf`, `VotingOf` + /// - Base Weight: 21.03 + .359 * R /// # - #[weight = 0] + #[weight = 21_000_000 + 360_000 * Weight::from(T::MaxVotes::get()) + T::DbWeight::get().reads_writes(2, 2)] fn remove_vote(origin, index: ReferendumIndex) -> DispatchResult { let who = ensure_signed(origin)?; Self::try_remove_vote(&who, index, UnvoteScope::Any) @@ -1168,8 +1394,12 @@ decl_module! { /// /// # /// - `O(R + log R)` where R is the number of referenda that `target` has voted on. + /// Weight is calculated for the maximum number of vote. + /// - Db reads: `ReferendumInfoOf`, `VotingOf` + /// - Db writes: `ReferendumInfoOf`, `VotingOf` + /// - Base Weight: 19.15 + .372 * R /// # - #[weight = 0] + #[weight = 19_000_000 + 370_000 * Weight::from(T::MaxVotes::get()) + T::DbWeight::get().reads_writes(2, 2)] fn remove_other_vote(origin, target: T::AccountId, index: ReferendumIndex) -> DispatchResult { let who = ensure_signed(origin)?; let scope = if target == who { UnvoteScope::Any } else { UnvoteScope::OnlyExpired }; @@ -1199,16 +1429,22 @@ decl_module! { /// Emits `Delegated`. /// /// # + /// same as `delegate with additional: + /// - Db reads: `Proxy`, `proxy account` + /// - Db writes: `proxy account` + /// - Base Weight: 68.61 + 8.039 * R µs /// # - #[weight = 500_000_000] + #[weight = weight_for::proxy_delegate::(T::MaxVotes::get().into())] pub fn proxy_delegate(origin, to: T::AccountId, conviction: Conviction, balance: BalanceOf, - ) { + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let target = Self::proxy(who).and_then(|a| a.as_active()).ok_or(Error::::NotProxy)?; - Self::try_delegate(target, to, conviction, balance)?; + let votes = Self::try_delegate(target, to, conviction, balance)?; + + Ok(Some(weight_for::proxy_delegate::(votes.into())).into()) } /// Undelegate the voting power of a proxied account. @@ -1222,13 +1458,17 @@ decl_module! { /// Emits `Undelegated`. /// /// # - /// - O(1). + /// same as `undelegate with additional: + /// Db reads: `Proxy` + /// Base Weight: 39 + 7.958 * R µs /// # - #[weight = 500_000_000] - fn proxy_undelegate(origin) { + #[weight = weight_for::proxy_undelegate::(T::MaxVotes::get().into())] + fn proxy_undelegate(origin) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let target = Self::proxy(who).and_then(|a| a.as_active()).ok_or(Error::::NotProxy)?; - Self::try_undelegate(target)?; + let votes = Self::try_undelegate(target)?; + + Ok(Some(weight_for::proxy_undelegate::(votes.into())).into()) } /// Remove a proxied vote for a referendum. @@ -1243,8 +1483,12 @@ decl_module! { /// /// # /// - `O(R + log R)` where R is the number of referenda that `target` has voted on. + /// Weight is calculated for the maximum number of vote. + /// - Db reads: `ReferendumInfoOf`, `VotingOf`, `Proxy` + /// - Db writes: `ReferendumInfoOf`, `VotingOf` + /// - Base Weight: 26.35 + .36 * R µs /// # - #[weight = 0] + #[weight = 26_000_000 + 360_000 * Weight::from(T::MaxVotes::get()) + T::DbWeight::get().reads_writes(2, 3)] fn proxy_remove_vote(origin, index: ReferendumIndex) -> DispatchResult { let who = ensure_signed(origin)?; let target = Self::proxy(who).and_then(|a| a.as_active()).ok_or(Error::::NotProxy)?; @@ -1266,7 +1510,7 @@ impl Module { /// Get the amount locked in support of `proposal`; `None` if proposal isn't a valid proposal /// index. pub fn backing_for(proposal: PropIndex) -> Option> { - Self::deposit_of(proposal).map(|(d, l)| d * (l.len() as u32).into()) + Self::deposit_of(proposal).map(|(l, d)| d * (l.len() as u32).into()) } /// Get all referenda ready for tally at block `n`. @@ -1275,7 +1519,14 @@ impl Module { ) -> Vec<(ReferendumIndex, ReferendumStatus>)> { let next = Self::lowest_unbaked(); let last = Self::referendum_count(); - (next..last).into_iter() + Self::maturing_referenda_at_inner(n, next..last) + } + + fn maturing_referenda_at_inner( + n: T::BlockNumber, + range: core::ops::Range, + ) -> Vec<(ReferendumIndex, ReferendumStatus>)> { + range.into_iter() .map(|i| (i, Self::referendum_info(i))) .filter_map(|(i, maybe_info)| match maybe_info { Some(ReferendumInfo::Ongoing(status)) => Some((i, status)), @@ -1352,7 +1603,10 @@ impl Module { } votes[i].1 = vote; } - Err(i) => votes.insert(i, (ref_index, vote)), + Err(i) => { + ensure!(votes.len() as u32 <= T::MaxVotes::get(), Error::::MaxVotesReached); + votes.insert(i, (ref_index, vote)); + } } // Shouldn't be possible to fail, but we handle it gracefully. status.tally.add(vote).ok_or(Error::::Overflow)?; @@ -1415,11 +1669,14 @@ impl Module { Ok(()) } - fn increase_upstream_delegation(who: &T::AccountId, amount: Delegations>) { + /// Return the number of votes for `who` + fn increase_upstream_delegation(who: &T::AccountId, amount: Delegations>) -> u32 { VotingOf::::mutate(who, |voting| match voting { - Voting::Delegating { delegations, .. } => + Voting::Delegating { delegations, .. } => { // We don't support second level delegating, so we don't need to do anything more. - *delegations = delegations.saturating_add(amount), + *delegations = delegations.saturating_add(amount); + 1 + }, Voting::Direct { votes, delegations, .. } => { *delegations = delegations.saturating_add(amount); for &(ref_index, account_vote) in votes.iter() { @@ -1431,15 +1688,19 @@ impl Module { ); } } + votes.len() as u32 } }) } - fn reduce_upstream_delegation(who: &T::AccountId, amount: Delegations>) { + /// Return the number of votes for `who` + fn reduce_upstream_delegation(who: &T::AccountId, amount: Delegations>) -> u32 { VotingOf::::mutate(who, |voting| match voting { - Voting::Delegating { delegations, .. } => - // We don't support second level delegating, so we don't need to do anything more. - *delegations = delegations.saturating_sub(amount), + Voting::Delegating { delegations, .. } => { + // We don't support second level delegating, so we don't need to do anything more. + *delegations = delegations.saturating_sub(amount); + 1 + } Voting::Direct { votes, delegations, .. } => { *delegations = delegations.saturating_sub(amount); for &(ref_index, account_vote) in votes.iter() { @@ -1451,20 +1712,23 @@ impl Module { ); } } + votes.len() as u32 } }) } /// Attempt to delegate `balance` times `conviction` of voting power from `who` to `target`. + /// + /// Return the upstream number of votes. fn try_delegate( who: T::AccountId, target: T::AccountId, conviction: Conviction, balance: BalanceOf, - ) -> DispatchResult { + ) -> Result { ensure!(who != target, Error::::Nonsense); ensure!(balance <= T::Currency::free_balance(&who), Error::::InsufficientFunds); - VotingOf::::try_mutate(&who, |voting| -> DispatchResult { + let votes = VotingOf::::try_mutate(&who, |voting| -> Result { let mut old = Voting::Delegating { balance, target: target.clone(), @@ -1485,7 +1749,7 @@ impl Module { voting.set_common(delegations, prior); } } - Self::increase_upstream_delegation(&target, conviction.votes(balance)); + let votes = Self::increase_upstream_delegation(&target, conviction.votes(balance)); // Extend the lock to `balance` (rather than setting it) since we don't know what other // votes are in place. T::Currency::extend_lock( @@ -1494,15 +1758,17 @@ impl Module { balance, WithdrawReason::Transfer.into() ); - Ok(()) + Ok(votes) })?; Self::deposit_event(Event::::Delegated(who, target)); - Ok(()) + Ok(votes) } /// Attempt to end the current delegation. - fn try_undelegate(who: T::AccountId) -> DispatchResult { - VotingOf::::try_mutate(&who, |voting| -> DispatchResult { + /// + /// Return the number of votes of upstream. + fn try_undelegate(who: T::AccountId) -> Result { + let votes = VotingOf::::try_mutate(&who, |voting| -> Result { let mut old = Voting::default(); sp_std::mem::swap(&mut old, voting); match old { @@ -1514,20 +1780,21 @@ impl Module { mut prior, } => { // remove any delegation votes to our current target. - Self::reduce_upstream_delegation(&target, conviction.votes(balance)); + let votes = Self::reduce_upstream_delegation(&target, conviction.votes(balance)); let now = system::Module::::block_number(); let lock_periods = conviction.lock_periods().into(); prior.accumulate(now + T::EnactmentPeriod::get() * lock_periods, balance); voting.set_common(delegations, prior); + + Ok(votes) } Voting::Direct { .. } => { - return Err(Error::::NotDelegating.into()) + Err(Error::::NotDelegating.into()) } } - Ok(()) })?; Self::deposit_event(Event::::Undelegated(who)); - Ok(()) + Ok(votes) } /// Rejig the lock on an account. It will never get more stringent (since that would indicate @@ -1597,7 +1864,7 @@ impl Module { let (prop_index, proposal, _) = public_props.swap_remove(winner_index); >::put(public_props); - if let Some((deposit, depositors)) = >::take(prop_index) { + if let Some((depositors, deposit)) = >::take(prop_index) { // refund depositors for d in &depositors { T::Currency::unreserve(d, deposit); @@ -1676,19 +1943,179 @@ impl Module { } /// Current era is ending; we should finish up any proposals. - fn begin_block(now: T::BlockNumber) -> DispatchResult { + /// + /// + /// # + /// If a referendum is launched or maturing take full block weight. Otherwise: + /// - Complexity: `O(R)` where `R` is the number of unbaked referenda. + /// - Db reads: `LastTabledWasExternal`, `NextExternal`, `PublicProps`, `account`, + /// `ReferendumCount`, `LowestUnbaked` + /// - Db writes: `PublicProps`, `account`, `ReferendumCount`, `DepositOf`, `ReferendumInfoOf` + /// - Db reads per R: `DepositOf`, `ReferendumInfoOf` + /// - Base Weight: 58.58 + 10.9 * R µs + /// # + fn begin_block(now: T::BlockNumber) -> Result { + let mut weight = 60_000_000 + T::DbWeight::get().reads_writes(6, 5); + // pick out another public referendum if it's time. if (now % T::LaunchPeriod::get()).is_zero() { // Errors come from the queue being empty. we don't really care about that, and even if // we did, there is nothing we can do here. let _ = Self::launch_next(now); + weight = T::MaximumBlockWeight::get(); } // tally up votes for any expiring referenda. - for (index, info) in Self::maturing_referenda_at(now).into_iter() { + let next = Self::lowest_unbaked(); + let last = Self::referendum_count(); + let r = Weight::from(last.saturating_sub(next)); + weight += 11_000_000 * r + T::DbWeight::get().reads(2 * r); + for (index, info) in Self::maturing_referenda_at_inner(now, next..last).into_iter() { let approved = Self::bake_referendum(now, index, info)?; ReferendumInfoOf::::insert(index, ReferendumInfo::Finished { end: now, approved }); + weight = T::MaximumBlockWeight::get(); + } + + Ok(weight) + } + + /// Reads the length of account in DepositOf without getting the complete value in the runtime. + /// + /// Return 0 if no deposit for this proposal. + fn len_of_deposit_of(proposal: PropIndex) -> Option { + // DepositOf first tuple element is a vec, decoding its len is equivalent to decode a + // `Compact`. + decode_compact_u32_at(&>::hashed_key_for(proposal)) + } + + /// Check that pre image exists and its value is variant `PreimageStatus::Missing`. + /// + /// This check is done without getting the complete value in the runtime to avoid copying a big + /// value in the runtime. + fn check_pre_image_is_missing(proposal_hash: T::Hash) -> DispatchResult { + // To decode the enum variant we only need the first byte. + let mut buf = [0u8; 1]; + let key = >::hashed_key_for(proposal_hash); + let bytes = match sp_io::storage::read(&key, &mut buf, 0) { + Some(bytes) => bytes, + None => return Err(Error::::NotImminent.into()), + }; + // The value may be smaller that 1 byte. + let mut input = &buf[0..buf.len().min(bytes as usize)]; + + match input.read_byte() { + Ok(0) => Ok(()), // PreimageStatus::Missing is variant 0 + Ok(1) => Err(Error::::DuplicatePreimage.into()), + _ => { + sp_runtime::print("Failed to decode `PreimageStatus` variant"); + Err(Error::::NotImminent.into()) + } + } + } + + /// Check that pre image exists, its value is variant `PreimageStatus::Available` and decode + /// the length of `data: Vec` fields. + /// + /// This check is done without getting the complete value in the runtime to avoid copying a big + /// value in the runtime. + /// + /// If the pre image is missing variant or doesn't exist then the error `PreimageMissing` is + /// returned. + fn pre_image_data_len(proposal_hash: T::Hash) -> Result { + // To decode the `data` field of Available variant we need: + // * one byte for the variant + // * at most 5 bytes to decode a `Compact` + let mut buf = [0u8; 6]; + let key = >::hashed_key_for(proposal_hash); + let bytes = match sp_io::storage::read(&key, &mut buf, 0) { + Some(bytes) => bytes, + None => return Err(Error::::PreimageMissing.into()), + }; + // The value may be smaller that 6 bytes. + let mut input = &buf[0..buf.len().min(bytes as usize)]; + + match input.read_byte() { + Ok(1) => (), // Check that input exists and is second variant. + Ok(0) => return Err(Error::::PreimageMissing.into()), + _ => { + sp_runtime::print("Failed to decode `PreimageStatus` variant"); + return Err(Error::::PreimageMissing.into()); + } } + + // Decode the length of the vector. + let len = codec::Compact::::decode(&mut input).map_err(|_| { + sp_runtime::print("Failed to decode `PreimageStatus` variant"); + DispatchError::from(Error::::PreimageMissing) + })?.0; + + Ok(len) + } + + // See `note_preimage` + fn note_preimage_inner(who: T::AccountId, encoded_proposal: Vec) -> DispatchResult { + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + ensure!(!>::contains_key(&proposal_hash), Error::::DuplicatePreimage); + + let deposit = >::from(encoded_proposal.len() as u32) + .saturating_mul(T::PreimageByteDeposit::get()); + T::Currency::reserve(&who, deposit)?; + + let now = >::block_number(); + let a = PreimageStatus::Available { + data: encoded_proposal, + provider: who.clone(), + deposit, + since: now, + expiry: None, + }; + >::insert(proposal_hash, a); + + Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, deposit)); + Ok(()) } + + // See `note_imminent_preimage` + fn note_imminent_preimage_inner(who: T::AccountId, encoded_proposal: Vec) -> DispatchResult { + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + Self::check_pre_image_is_missing(proposal_hash)?; + let status = Preimages::::get(&proposal_hash).ok_or(Error::::NotImminent)?; + let expiry = status.to_missing_expiry().ok_or(Error::::DuplicatePreimage)?; + + let now = >::block_number(); + let free = >::zero(); + let a = PreimageStatus::Available { + data: encoded_proposal, + provider: who.clone(), + deposit: Zero::zero(), + since: now, + expiry: Some(expiry), + }; + >::insert(proposal_hash, a); + + Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, free)); + + Ok(()) + } +} + +/// Decode `Compact` from the trie at given key. +fn decode_compact_u32_at(key: &[u8]) -> Option { + // `Compact` takes at most 5 bytes. + let mut buf = [0u8; 5]; + let bytes = match sp_io::storage::read(&key, &mut buf, 0) { + Some(bytes) => bytes, + None => return None, + }; + // The value may be smaller than 5 bytes. + let mut input = &buf[0..buf.len().min(bytes as usize)]; + match codec::Compact::::decode(&mut input) { + Ok(c) => Some(c.0), + Err(_) => { + sp_runtime::print("Failed to decode compact u32 at:"); + sp_runtime::print(key); + None + } + } } diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index a835a0ff6ee1e63491bc4baf51a8a11b60fa6fc1..103ac6a84b6b8a427dea9a006c3b1ece8452207c 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The crate's tests. @@ -41,6 +42,8 @@ mod proxying; mod public_proposals; mod scheduling; mod voting; +mod migration; +mod decoders; const AYE: Vote = Vote { aye: true, conviction: Conviction::None }; const NAY: Vote = Vote { aye: false, conviction: Conviction::None }; @@ -97,6 +100,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -106,7 +110,7 @@ impl frame_system::Trait for Test { type OnKilledAccount = (); } parameter_types! { - pub const MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); } impl pallet_scheduler::Trait for Test { type Event = Event; @@ -131,6 +135,7 @@ parameter_types! { pub const MinimumDeposit: u64 = 1; pub const EnactmentPeriod: u64 = 2; pub const CooloffPeriod: u64 = 2; + pub const MaxVotes: u32 = 100; } ord_parameter_types! { pub const One: u64 = 1; @@ -181,6 +186,8 @@ impl super::Trait for Test { type InstantOrigin = EnsureSignedBy; type InstantAllowed = InstantAllowed; type Scheduler = Scheduler; + type MaxVotes = MaxVotes; + type OperationalPreimageOrigin = EnsureSignedBy; } pub fn new_test_ext() -> sp_io::TestExternalities { @@ -194,6 +201,12 @@ pub fn new_test_ext() -> sp_io::TestExternalities { ext } +/// Execute the function two times, with `true` and with `false`. +pub fn new_test_ext_execute_with_cond(execute: impl FnOnce(bool) -> () + Clone) { + new_test_ext().execute_with(|| (execute.clone())(false)); + new_test_ext().execute_with(|| execute(true)); +} + type System = frame_system::Module; type Balances = pallet_balances::Module; type Scheduler = pallet_scheduler::Module; @@ -231,7 +244,7 @@ fn propose_set_balance(who: u64, value: u64, delay: u64) -> DispatchResult { Democracy::propose( Origin::signed(who), set_balance_proposal_hash(value), - delay + delay, ) } @@ -239,14 +252,14 @@ fn propose_set_balance_and_note(who: u64, value: u64, delay: u64) -> DispatchRes Democracy::propose( Origin::signed(who), set_balance_proposal_hash_and_note(value), - delay + delay, ) } fn next_block() { System::set_block_number(System::block_number() + 1); Scheduler::on_initialize(System::block_number()); - assert_eq!(Democracy::begin_block(System::block_number()), Ok(())); + assert!(Democracy::begin_block(System::block_number()).is_ok()); } fn fast_forward_to(n: u64) { diff --git a/frame/democracy/src/tests/cancellation.rs b/frame/democracy/src/tests/cancellation.rs index 998b0c14d8c8074738f847b8d7b9497e3340b4b5..e75fd281091633d996e4518bd1bd2de5f4e3caaf 100644 --- a/frame/democracy/src/tests/cancellation.rs +++ b/frame/democracy/src/tests/cancellation.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for cancelation functionality. diff --git a/frame/democracy/src/tests/decoders.rs b/frame/democracy/src/tests/decoders.rs new file mode 100644 index 0000000000000000000000000000000000000000..6b8e661ca9fd9715e9dea882eb3c1e580535eb77 --- /dev/null +++ b/frame/democracy/src/tests/decoders.rs @@ -0,0 +1,81 @@ +// Copyright 2020 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 for various partial storage decoders + +use super::*; +use frame_support::storage::{migration, StorageMap, unhashed}; + +#[test] +fn test_decode_compact_u32_at() { + new_test_ext().execute_with(|| { + let v = codec::Compact(u64::max_value()); + migration::put_storage_value(b"test", b"", &[], v); + assert_eq!(decode_compact_u32_at(b"test"), None); + + for v in vec![0, 10, u32::max_value()] { + let compact_v = codec::Compact(v); + unhashed::put(b"test", &compact_v); + assert_eq!(decode_compact_u32_at(b"test"), Some(v)); + } + + unhashed::kill(b"test"); + assert_eq!(decode_compact_u32_at(b"test"), None); + }) +} + +#[test] +fn len_of_deposit_of() { + new_test_ext().execute_with(|| { + for l in vec![0, 1, 200, 1000] { + let value: (Vec, u64) = ((0..l).map(|_| Default::default()).collect(), 3u64); + DepositOf::::insert(2, value); + assert_eq!(Democracy::len_of_deposit_of(2), Some(l)); + } + + DepositOf::::remove(2); + assert_eq!(Democracy::len_of_deposit_of(2), None); + }) +} + +#[test] +fn pre_image() { + new_test_ext().execute_with(|| { + let key = Default::default(); + let missing = PreimageStatus::Missing(0); + Preimages::::insert(key, missing); + assert!(Democracy::pre_image_data_len(key).is_err()); + assert_eq!(Democracy::check_pre_image_is_missing(key), Ok(())); + + Preimages::::remove(key); + assert!(Democracy::pre_image_data_len(key).is_err()); + assert!(Democracy::check_pre_image_is_missing(key).is_err()); + + for l in vec![0, 10, 100, 1000u32] { + let available = PreimageStatus::Available{ + data: (0..l).map(|i| i as u8).collect(), + provider: 0, + deposit: 0, + since: 0, + expiry: None, + }; + + Preimages::::insert(key, available); + assert_eq!(Democracy::pre_image_data_len(key), Ok(l)); + assert!(Democracy::check_pre_image_is_missing(key).is_err()); + } + }) +} diff --git a/frame/democracy/src/tests/delegation.rs b/frame/democracy/src/tests/delegation.rs index 061a48b587798219f5562e8ca13fadd214c4cfe8..34dec6d0b49a6d6805d0e1f8bdf65b3114a90884 100644 --- a/frame/democracy/src/tests/delegation.rs +++ b/frame/democracy/src/tests/delegation.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning delegation. diff --git a/frame/democracy/src/tests/external_proposing.rs b/frame/democracy/src/tests/external_proposing.rs index a249a806ee9edf4af87b6ecc81920783ac29c431..473eac81cdcb08c89bd3583706ccfb9bc0a145fd 100644 --- a/frame/democracy/src/tests/external_proposing.rs +++ b/frame/democracy/src/tests/external_proposing.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning the "external" origin. diff --git a/frame/democracy/src/tests/fast_tracking.rs b/frame/democracy/src/tests/fast_tracking.rs index 5ce9b15baf34cde31d2788679f3bdb106e1e8a84..8df34001cde043231587816bf253632a6f7123c0 100644 --- a/frame/democracy/src/tests/fast_tracking.rs +++ b/frame/democracy/src/tests/fast_tracking.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for fast-tracking functionality. diff --git a/frame/democracy/src/tests/lock_voting.rs b/frame/democracy/src/tests/lock_voting.rs index e83d974a8dc27fc990950ed1ae3895946b643e03..93867030588c31b3e146814bccbc4a428b4756eb 100644 --- a/frame/democracy/src/tests/lock_voting.rs +++ b/frame/democracy/src/tests/lock_voting.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning locking and lock-voting. diff --git a/frame/democracy/src/tests/migration.rs b/frame/democracy/src/tests/migration.rs new file mode 100644 index 0000000000000000000000000000000000000000..cab8f7f5c936c433237d4aaa7e952ada6933da4c --- /dev/null +++ b/frame/democracy/src/tests/migration.rs @@ -0,0 +1,45 @@ +// Copyright 2020 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 tests for migration. + +use super::*; +use frame_support::{storage::migration, Hashable, traits::OnRuntimeUpgrade}; +use substrate_test_utils::assert_eq_uvec; + +#[test] +fn migration() { + new_test_ext().execute_with(|| { + for i in 0..3 { + let k = i.twox_64_concat(); + let v: (BalanceOf, Vec) = (i * 1000, vec![i]); + migration::put_storage_value(b"Democracy", b"DepositOf", &k, v); + } + StorageVersion::kill(); + + Democracy::on_runtime_upgrade(); + + assert_eq!(StorageVersion::get(), Some(Releases::V1)); + assert_eq_uvec!( + DepositOf::::iter().collect::>(), + vec![ + (0, (vec![0u64], >::from(0u32))), + (1, (vec![1u64], >::from(1000u32))), + (2, (vec![2u64], >::from(2000u32))), + ] + ); + }) +} diff --git a/frame/democracy/src/tests/preimage.rs b/frame/democracy/src/tests/preimage.rs index 7d977b0ba83acd514e73fb77d18c485269451161..4100a6a6b6375e7208f8105bcfdb000d10ba8ade 100644 --- a/frame/democracy/src/tests/preimage.rs +++ b/frame/democracy/src/tests/preimage.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The preimage tests. @@ -38,13 +39,14 @@ fn missing_preimage_should_fail() { #[test] fn preimage_deposit_should_be_required_and_returned() { - new_test_ext().execute_with(|| { + new_test_ext_execute_with_cond(|operational| { // fee of 100 is too much. PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 100); assert_noop!( - Democracy::note_preimage(Origin::signed(6), vec![0; 500]), - BalancesError::::InsufficientBalance, - ); + if operational { Democracy::note_preimage_operational(Origin::signed(6), vec![0; 500]) } + else { Democracy::note_preimage(Origin::signed(6), vec![0; 500]) }, + BalancesError::::InsufficientBalance, + ); // fee of 1 is reasonable. PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); let r = Democracy::inject_referendum( @@ -68,19 +70,22 @@ fn preimage_deposit_should_be_required_and_returned() { #[test] fn preimage_deposit_should_be_reapable_earlier_by_owner() { - new_test_ext().execute_with(|| { + new_test_ext_execute_with_cond(|operational| { PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); - assert_ok!(Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2))); + assert_ok!( + if operational { Democracy::note_preimage_operational(Origin::signed(6), set_balance_proposal(2)) } + else { Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2)) } + ); assert_eq!(Balances::reserved_balance(6), 12); next_block(); assert_noop!( - Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2)), - Error::::TooEarly - ); + Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2), u32::max_value()), + Error::::TooEarly + ); next_block(); - assert_ok!(Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2))); + assert_ok!(Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2), u32::max_value())); assert_eq!(Balances::free_balance(6), 60); assert_eq!(Balances::reserved_balance(6), 0); @@ -89,26 +94,29 @@ fn preimage_deposit_should_be_reapable_earlier_by_owner() { #[test] fn preimage_deposit_should_be_reapable() { - new_test_ext().execute_with(|| { + new_test_ext_execute_with_cond(|operational| { assert_noop!( - Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2)), + Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2), u32::max_value()), Error::::PreimageMissing ); PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); - assert_ok!(Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2))); + assert_ok!( + if operational { Democracy::note_preimage_operational(Origin::signed(6), set_balance_proposal(2)) } + else { Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2)) } + ); assert_eq!(Balances::reserved_balance(6), 12); next_block(); next_block(); next_block(); assert_noop!( - Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2)), + Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2), u32::max_value()), Error::::TooEarly ); next_block(); - assert_ok!(Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2))); + assert_ok!(Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2), u32::max_value())); assert_eq!(Balances::reserved_balance(6), 0); assert_eq!(Balances::free_balance(6), 48); assert_eq!(Balances::free_balance(5), 62); @@ -117,7 +125,7 @@ fn preimage_deposit_should_be_reapable() { #[test] fn noting_imminent_preimage_for_free_should_work() { - new_test_ext().execute_with(|| { + new_test_ext_execute_with_cond(|operational| { PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); let r = Democracy::inject_referendum( @@ -129,14 +137,15 @@ fn noting_imminent_preimage_for_free_should_work() { assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); assert_noop!( - Democracy::note_imminent_preimage(Origin::signed(7), set_balance_proposal(2)), - Error::::NotImminent - ); + if operational { Democracy::note_imminent_preimage_operational(Origin::signed(6), set_balance_proposal(2)) } + else { Democracy::note_imminent_preimage(Origin::signed(6), set_balance_proposal(2)) }, + Error::::NotImminent + ); next_block(); // Now we're in the dispatch queue it's all good. - assert_ok!(Democracy::note_imminent_preimage(Origin::signed(7), set_balance_proposal(2))); + assert_ok!(Democracy::note_imminent_preimage(Origin::signed(6), set_balance_proposal(2))); next_block(); @@ -152,6 +161,6 @@ fn reaping_imminent_preimage_should_fail() { assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); next_block(); next_block(); - assert_noop!(Democracy::reap_preimage(Origin::signed(6), h), Error::::Imminent); + assert_noop!(Democracy::reap_preimage(Origin::signed(6), h, u32::max_value()), Error::::Imminent); }); } diff --git a/frame/democracy/src/tests/proxying.rs b/frame/democracy/src/tests/proxying.rs index 412adf6be03e707a22e9cd3bb03df3c8f2e6c6cd..2e39528e75a3b9206328f76b19b959c752e69506 100644 --- a/frame/democracy/src/tests/proxying.rs +++ b/frame/democracy/src/tests/proxying.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning proxying. diff --git a/frame/democracy/src/tests/public_proposals.rs b/frame/democracy/src/tests/public_proposals.rs index 04246e86f1da4fb530fb47a58bb9fbb07120bc43..68ec790baae8610591c8cf768e66644824f4c09a 100644 --- a/frame/democracy/src/tests/public_proposals.rs +++ b/frame/democracy/src/tests/public_proposals.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for the public proposal queue. @@ -34,10 +35,10 @@ fn backing_for_should_work() { fn deposit_for_proposals_should_be_taken() { new_test_ext().execute_with(|| { assert_ok!(propose_set_balance_and_note(1, 2, 5)); - assert_ok!(Democracy::second(Origin::signed(2), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(2), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); assert_eq!(Balances::free_balance(1), 5); assert_eq!(Balances::free_balance(2), 15); assert_eq!(Balances::free_balance(5), 35); @@ -48,10 +49,10 @@ fn deposit_for_proposals_should_be_taken() { fn deposit_for_proposals_should_be_returned() { new_test_ext().execute_with(|| { assert_ok!(propose_set_balance_and_note(1, 2, 5)); - assert_ok!(Democracy::second(Origin::signed(2), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(2), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); + assert_ok!(Democracy::second(Origin::signed(5), 0, u32::max_value())); fast_forward_to(3); assert_eq!(Balances::free_balance(1), 10); assert_eq!(Balances::free_balance(2), 20); @@ -77,7 +78,21 @@ fn poor_proposer_should_not_work() { fn poor_seconder_should_not_work() { new_test_ext().execute_with(|| { assert_ok!(propose_set_balance_and_note(2, 2, 11)); - assert_noop!(Democracy::second(Origin::signed(1), 0), BalancesError::::InsufficientBalance); + assert_noop!( + Democracy::second(Origin::signed(1), 0, u32::max_value()), + BalancesError::::InsufficientBalance + ); + }); +} + +#[test] +fn invalid_seconds_upper_bound_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(propose_set_balance_and_note(1, 2, 5)); + assert_noop!( + Democracy::second(Origin::signed(2), 0, 0), + Error::::WrongUpperBound + ); }); } diff --git a/frame/democracy/src/tests/scheduling.rs b/frame/democracy/src/tests/scheduling.rs index db9724deddc223d8895ce807f91ce65e9c020a8b..5bcfbae9946892596f21c9fc7b568e9db0bbb0d3 100644 --- a/frame/democracy/src/tests/scheduling.rs +++ b/frame/democracy/src/tests/scheduling.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for functionality concerning normal starting, ending and enacting of referenda. diff --git a/frame/democracy/src/tests/voting.rs b/frame/democracy/src/tests/voting.rs index 43aed29a32d8bc8c0cc59ab0d84b7fcef44dd4aa..9ae57797d15dd703f545d5720e1ed78477fd8940 100644 --- a/frame/democracy/src/tests/voting.rs +++ b/frame/democracy/src/tests/voting.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The tests for normal voting functionality. diff --git a/frame/democracy/src/types.rs b/frame/democracy/src/types.rs index 3454326364de60412048467b8602df796110e3fd..efd52361f52a8cd55e11ac0fa9746dd683da1394 100644 --- a/frame/democracy/src/types.rs +++ b/frame/democracy/src/types.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Miscellaneous additional datatypes. diff --git a/frame/democracy/src/vote.rs b/frame/democracy/src/vote.rs index a41eb342aa12cb1ee862a0119a49f97620a0620d..09ff0d71e48ca9cf44142b4c8ab306aedaa4dc39 100644 --- a/frame/democracy/src/vote.rs +++ b/frame/democracy/src/vote.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The vote datatype. diff --git a/frame/democracy/src/vote_threshold.rs b/frame/democracy/src/vote_threshold.rs index fd976b44001cf189d497ec81c9fba789843e72d0..2268a55936c50aafa47fc5281e71d7dad5299607 100644 --- a/frame/democracy/src/vote_threshold.rs +++ b/frame/democracy/src/vote_threshold.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Voting thresholds. diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml index f9d681b7608e66dd1b615c5524ca8ea8740e796e..bea1e0dfc4173ec472d30f0380a29344813adbc4 100644 --- a/frame/elections-phragmen/Cargo.toml +++ b/frame/elections-phragmen/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-elections-phragmen" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME election pallet for PHRAGMEN" @@ -14,19 +14,19 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-phragmen = { version = "2.0.0-dev", default-features = false, path = "../../primitives/phragmen" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-phragmen = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/phragmen" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } hex-literal = "0.2.1" -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -pallet-scheduler = { version = "2.0.0-dev", path = "../scheduler" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -substrate-test-utils = { version = "2.0.0-dev", path = "../../test-utils" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +substrate-test-utils = { version = "2.0.0-rc2", path = "../../test-utils" } [features] default = ["std"] @@ -39,4 +39,8 @@ std = [ "frame-system/std", "sp-std/std", ] -runtime-benchmarks = ["frame-support/runtime-benchmarks"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] diff --git a/frame/elections-phragmen/src/benchmarking.rs b/frame/elections-phragmen/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..6de9ad57e244fa080c41815436be290546885fb4 --- /dev/null +++ b/frame/elections-phragmen/src/benchmarking.rs @@ -0,0 +1,600 @@ +// Copyright 2020 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 . + +//! Elections-Phragmen pallet benchmarking. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use frame_system::RawOrigin; +use frame_benchmarking::{benchmarks, account}; +use frame_support::traits::OnInitialize; + +use crate::Module as Elections; + +const BALANCE_FACTOR: u32 = 250; +const MAX_VOTERS: u32 = 500; +const MAX_CANDIDATES: u32 = 100; + +type Lookup = <::Lookup as StaticLookup>::Source; + +/// grab new account with infinite balance. +fn endowed_account(name: &'static str, index: u32) -> T::AccountId { + let account: T::AccountId = account(name, index, 0); + let amount = default_stake::(BALANCE_FACTOR); + let _ = T::Currency::make_free_balance_be(&account, amount); + // important to increase the total issuance since T::CurrencyToVote will need it to be sane for + // phragmen to work. + T::Currency::issue(amount); + account +} + +/// Account to lookup type of system trait. +fn as_lookup(account: T::AccountId) -> Lookup { + T::Lookup::unlookup(account) +} + +/// Get a reasonable amount of stake based on the execution trait's configuration +fn default_stake(factor: u32) -> BalanceOf { + let factor = BalanceOf::::from(factor); + T::Currency::minimum_balance() * factor +} + +/// Get the current number of candidates. +fn candidate_count() -> u32 { + >::decode_len().unwrap_or(0usize) as u32 +} + +/// Get the number of votes of a voter. +fn vote_count_of(who: &T::AccountId) -> u32 { + >::get(who).1.len() as u32 +} + +/// A `DefunctVoter` struct with correct value +fn defunct_for(who: T::AccountId) -> DefunctVoter> { + DefunctVoter { + who: as_lookup::(who.clone()), + candidate_count: candidate_count::(), + vote_count: vote_count_of::(&who), + } +} + +/// Add `c` new candidates. +fn submit_candidates(c: u32, prefix: &'static str) + -> Result, &'static str> +{ + (0..c).map(|i| { + let account = endowed_account::(prefix, i); + >::submit_candidacy( + RawOrigin::Signed(account.clone()).into(), + candidate_count::(), + ).map_err(|_| "failed to submit candidacy")?; + Ok(account) + }).collect::>() +} + +/// Add `c` new candidates with self vote. +fn submit_candidates_with_self_vote(c: u32, prefix: &'static str) + -> Result, &'static str> +{ + let candidates = submit_candidates::(c, prefix)?; + let stake = default_stake::(BALANCE_FACTOR); + let _ = candidates.iter().map(|c| + submit_voter::(c.clone(), vec![c.clone()], stake) + ).collect::>()?; + Ok(candidates) +} + + +/// Submit one voter. +fn submit_voter(caller: T::AccountId, votes: Vec, stake: BalanceOf) + -> Result<(), &'static str> +{ + >::vote(RawOrigin::Signed(caller).into(), votes, stake) + .map_err(|_| "failed to submit vote") +} + +/// create `num_voter` voters who randomly vote for at most `votes` of `all_candidates` if +/// available. +fn distribute_voters(mut all_candidates: Vec, num_voters: u32, votes: usize) + -> Result<(), &'static str> +{ + let stake = default_stake::(BALANCE_FACTOR); + for i in 0..num_voters { + // to ensure that votes are different + all_candidates.rotate_left(1); + let votes = all_candidates + .iter() + .cloned() + .take(votes) + .collect::>(); + let voter = endowed_account::("voter", i); + submit_voter::(voter, votes, stake)?; + } + Ok(()) +} + +/// Fill the seats of members and runners-up up until `m`. Note that this might include either only +/// members, or members and runners-up. +fn fill_seats_up_to(m: u32) -> Result, &'static str> { + let candidates = submit_candidates_with_self_vote::(m, "fill_seats_up_to")?; + assert_eq!(>::candidates().len() as u32, m, "wrong number of candidates."); + >::do_phragmen(); + assert_eq!(>::candidates().len(), 0, "some candidates remaining."); + assert_eq!( + >::members().len() + >::runners_up().len(), + m as usize, + "wrong number of members and runners-up", + ); + Ok(candidates) +} + +/// removes all the storage items to reverse any genesis state. +fn clean() { + >::kill(); + >::kill(); + >::kill(); + let _ = >::drain(); +} + +benchmarks! { + _ { + // User account seed + let u in 0 .. 1000 => (); + } + + // -- Signed ones + vote { + let u in ...; + // we fix the number of voted candidates to max + let v = MAXIMUM_VOTE; + clean::(); + + // create a bunch of candidates. + let all_candidates = submit_candidates::(MAXIMUM_VOTE as u32, "candidates")?; + + let caller = endowed_account::("caller", u); + let stake = default_stake::(BALANCE_FACTOR); + + // vote for all of them. + let votes = all_candidates.into_iter().take(v).collect(); + + }: _(RawOrigin::Signed(caller), votes, stake) + + vote_update { + let u in ...; + // we fix the number of voted candidates to max + let v = MAXIMUM_VOTE; + clean::(); + + // create a bunch of candidates. + let all_candidates = submit_candidates::(MAXIMUM_VOTE as u32, "candidates")?; + + let caller = endowed_account::("caller", u); + let stake = default_stake::(BALANCE_FACTOR); + + // original votes. + let mut votes = all_candidates.into_iter().take(v).collect::>(); + submit_voter::(caller.clone(), votes.clone(), stake)?; + // new votes. + votes.rotate_left(1); + }: vote(RawOrigin::Signed(caller), votes, stake) + + remove_voter { + let u in ...; + // we fix the number of voted candidates to max + let v = MAXIMUM_VOTE as u32; + clean::(); + + // create a bunch of candidates. + let all_candidates = submit_candidates::(v, "candidates")?; + + let caller = endowed_account::("caller", u); + + let stake = default_stake::(BALANCE_FACTOR); + submit_voter::(caller.clone(), all_candidates, stake)?; + + }: _(RawOrigin::Signed(caller)) + + report_defunct_voter_correct { + // number of already existing candidates that may or may not be voted by the reported + // account. + let c in 1 .. MAX_CANDIDATES; + // number of candidates that the reported voter voted for. The worse case of search here is + // basically `c * v`. + let v in 1 .. (MAXIMUM_VOTE as u32); + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + clean::(); + + let stake = default_stake::(BALANCE_FACTOR); + + // create m members and runners combined. + let _ = fill_seats_up_to::(m)?; + + // create a bunch of candidates as well. + let bailing_candidates = submit_candidates::(v, "bailing_candidates")?; + let all_candidates = submit_candidates::(c, "all_candidates")?; + + // account 1 is the reporter and it doesn't matter how many it votes. But it has to be a + // voter. + let account_1 = endowed_account::("caller", 0); + submit_voter::( + account_1.clone(), + all_candidates.iter().take(1).cloned().collect(), + stake, + )?; + + // account 2 votes for all of the mentioned candidates. + let account_2 = endowed_account::("caller_2", 1); + submit_voter::( + account_2.clone(), + bailing_candidates.clone(), + stake, + )?; + + // all the bailers go away. + bailing_candidates.into_iter().for_each(|b| { + let count = candidate_count::(); + assert!(>::renounce_candidacy( + RawOrigin::Signed(b).into(), + Renouncing::Candidate(count), + ).is_ok()); + }); + let defunct = defunct_for::(account_2.clone()); + }: report_defunct_voter(RawOrigin::Signed(account_1.clone()), defunct) + verify { + assert!(>::is_voter(&account_1)); + assert!(!>::is_voter(&account_2)); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + report_defunct_voter_incorrect { + // number of already existing candidates that may or may not be voted by the reported + // account. + let c in 1 .. MAX_CANDIDATES; + // number of candidates that the reported voter voted for. The worse case of search here is + // basically `c * v`. + let v in 1 .. (MAXIMUM_VOTE as u32); + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + + clean::(); + let stake = default_stake::(BALANCE_FACTOR); + + // create m members and runners combined. + let _ = fill_seats_up_to::(m)?; + + // create a bunch of candidates as well. + let all_candidates = submit_candidates::(c, "candidates")?; + + // account 1 is the reporter and it doesn't matter how many it votes. + let account_1 = endowed_account::("caller", 0); + submit_voter::( + account_1.clone(), + all_candidates.iter().take(1).cloned().collect(), + stake, + )?; + + // account 2 votes for a bunch of crap, and finally a correct candidate. + let account_2 = endowed_account::("caller_2", 1); + let mut invalid: Vec = + (0..(v-1)).map(|seed| account::("invalid", 0, seed).clone()).collect(); + invalid.push(all_candidates.last().unwrap().clone()); + submit_voter::( + account_2.clone(), + invalid, + stake, + )?; + + let defunct = defunct_for::(account_2.clone()); + // no one bails out. account_1 is slashed and removed as voter now. + }: report_defunct_voter(RawOrigin::Signed(account_1.clone()), defunct) + verify { + assert!(!>::is_voter(&account_1)); + assert!(>::is_voter(&account_2)); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + submit_candidacy { + // number of already existing candidates. + let c in 1 .. MAX_CANDIDATES; + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + + clean::(); + let stake = default_stake::(BALANCE_FACTOR); + + // create m members and runners combined. + let _ = fill_seats_up_to::(m)?; + + // create previous candidates; + let _ = submit_candidates::(c, "candidates")?; + + // we assume worse case that: extrinsic is successful and candidate is not duplicate. + let candidate_account = endowed_account::("caller", 0); + }: _(RawOrigin::Signed(candidate_account.clone()), candidate_count::()) + verify { + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + renounce_candidacy_candidate { + // this will check members, runners-up and candidate for removal. Members and runners-up are + // limited by the runtime bound, nonetheless we fill them by `m`. + // number of already existing candidates. + let c in 1 .. MAX_CANDIDATES; + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + + clean::(); + + // create m members and runners combined. + let _ = fill_seats_up_to::(m)?; + let all_candidates = submit_candidates::(c, "caller")?; + + let bailing = all_candidates[0].clone(); // Should be ("caller", 0) + let count = candidate_count::(); + }: renounce_candidacy(RawOrigin::Signed(bailing), Renouncing::Candidate(count)) + verify { + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + renounce_candidacy_member_runner_up { + // removing members and runners will be cheaper than a candidate. + // we fix the number of members to when members and runners-up to the desired. We'll be in + // this state almost always. + let u in ...; + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + clean::(); + + // create m members and runners combined. + let members_and_runners_up = fill_seats_up_to::(m)?; + + let bailing = members_and_runners_up[0].clone(); + let renouncing = if >::is_member(&bailing) { + Renouncing::Member + } else if >::is_runner_up(&bailing) { + Renouncing::RunnerUp + } else { + panic!("Bailing must be a member or runner-up for this bench to be sane."); + }; + }: renounce_candidacy(RawOrigin::Signed(bailing.clone()), renouncing) + verify { + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + // -- Root ones + remove_member_without_replacement { + // worse case is when we remove a member and we have no runner as a replacement. This + // triggers phragmen again. The only parameter is how many candidates will compete for the + // new slot. + let c in 1 .. MAX_CANDIDATES; + clean::(); + + // fill only desired members. no runners-up. + let all_members = fill_seats_up_to::(T::DesiredMembers::get())?; + assert_eq!(>::members().len() as u32, T::DesiredMembers::get()); + + // submit a new one to compensate, with self-vote. + let replacements = submit_candidates_with_self_vote::(c, "new_candidate")?; + + // create some voters for these replacements. + distribute_voters::(replacements, MAX_VOTERS, MAXIMUM_VOTE)?; + + let to_remove = as_lookup::(all_members[0].clone()); + }: remove_member(RawOrigin::Root, to_remove, false) + verify { + // must still have the desired number of members members. + assert_eq!(>::members().len() as u32, T::DesiredMembers::get()); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + remove_member_with_replacement { + // easy case. We have a runner up. Nothing will have that much of an impact. m will be + // number of members and runners. There is always at least one runner. + let u in ...; + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + clean::(); + + let _ = fill_seats_up_to::(m)?; + let removing = as_lookup::(>::members_ids()[0].clone()); + }: remove_member(RawOrigin::Root, removing, true) + verify { + // must still have enough members. + assert_eq!(>::members().len() as u32, T::DesiredMembers::get()); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + remove_member_wrong_refund { + // The root call by mistake indicated that this will have no replacement, while it has! + // this has now consumed a lot of weight and need to refund. + let u in ...; + let m = T::DesiredMembers::get() + T::DesiredRunnersUp::get(); + clean::(); + + let _ = fill_seats_up_to::(m)?; + let removing = as_lookup::(>::members_ids()[0].clone()); + }: { + assert_eq!( + >::remove_member(RawOrigin::Root.into(), removing, false).unwrap_err().error, + Error::::InvalidReplacement.into(), + ); + } + verify { + // must still have enough members. + assert_eq!(>::members().len() as u32, T::DesiredMembers::get()); + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + on_initialize { + // if n % TermDuration is zero, then we run phragmen. The weight function must and should + // check this as it is cheap to do so. TermDuration is not a storage item, it is a constant + // encoded in the runtime. + let c in 1 .. MAX_CANDIDATES; + clean::(); + + // create c candidates. + let all_candidates = submit_candidates_with_self_vote::(c, "candidates")?; + // create 500 voters, each voting the maximum 16 + distribute_voters::(all_candidates, MAX_VOTERS, MAXIMUM_VOTE)?; + }: { + // elect + >::on_initialize(T::TermDuration::get()); + } + verify { + assert_eq!(>::members().len() as u32, T::DesiredMembers::get().min(c)); + assert_eq!( + >::runners_up().len() as u32, + T::DesiredRunnersUp::get().min(c.saturating_sub(T::DesiredMembers::get())), + ); + + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } + + phragmen { + // This is just to focus on phragmen in the context of this module. We always select 20 + // members, this is hard-coded in the runtime and cannot be trivially changed at this stage. + // Yet, change the number of voters, candidates and edge per voter to see the impact. Note + // that we give all candidates a self vote to make sure they are all considered. + let c in 1 .. MAX_CANDIDATES; + let v in 1 .. MAX_VOTERS; + let e in 1 .. (MAXIMUM_VOTE as u32); + clean::(); + + let all_candidates = submit_candidates_with_self_vote::(c, "candidates")?; + let _ = distribute_voters::(all_candidates, v, e as usize)?; + }: { + >::on_initialize(T::TermDuration::get()); + } + verify { + assert_eq!(>::members().len() as u32, T::DesiredMembers::get().min(c)); + assert_eq!( + >::runners_up().len() as u32, + T::DesiredRunnersUp::get().min(c.saturating_sub(T::DesiredMembers::get())), + ); + + #[cfg(test)] + { + // reset members in between benchmark tests. + use crate::tests::MEMBERS; + MEMBERS.with(|m| *m.borrow_mut() = vec![]); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{ExtBuilder, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks_elections_phragmen() { + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_vote::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_remove_voter::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_report_defunct_voter_correct::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_report_defunct_voter_incorrect::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_submit_candidacy::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_renounce_candidacy_candidate::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_renounce_candidacy_member_runner_up::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_remove_member_without_replacement::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_remove_member_with_replacement::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_on_initialize::()); + }); + + ExtBuilder::default().desired_members(13).desired_runners_up(7).build_and_execute(|| { + assert_ok!(test_benchmark_phragmen::()); + }); + } +} diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 040ef00ac27cd0563a5333651e38bbbb82a8dcd6..5d7d2bf503bc2a4d88473d11c158539c2a8b2b80 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Phragmen Election Module. //! @@ -82,14 +83,17 @@ #![cfg_attr(not(feature = "std"), no_std)] +use codec::{Encode, Decode}; use sp_std::prelude::*; use sp_runtime::{ - print, DispatchResult, DispatchError, Perbill, traits::{Zero, StaticLookup, Convert}, + DispatchError, RuntimeDebug, Perbill, + traits::{Zero, StaticLookup, Convert}, }; use frame_support::{ decl_storage, decl_event, ensure, decl_module, decl_error, - weights::{Weight, DispatchClass}, + weights::{Weight, constants::{WEIGHT_PER_MICROS, WEIGHT_PER_NANOS}}, storage::{StorageMap, IterableStorageMap}, + dispatch::{DispatchResultWithPostInfo, WithPostDispatchInfo}, traits::{ Currency, Get, LockableCurrency, LockIdentifier, ReservableCurrency, WithdrawReasons, ChangeMembers, OnUnbalanced, WithdrawReason, Contains, BalanceStatus, InitializeMembers, @@ -99,13 +103,40 @@ use frame_support::{ use sp_phragmen::{build_support_map, ExtendedBalance, VoteWeight, PhragmenResult}; use frame_system::{self as system, ensure_signed, ensure_root}; +mod benchmarking; + /// The maximum votes allowed per voter. pub const MAXIMUM_VOTE: usize = 16; -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; +/// An indication that the renouncing account currently has which of the below roles. +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +pub enum Renouncing { + /// A member is renouncing. + Member, + /// A runner-up is renouncing. + RunnerUp, + /// A candidate is renouncing, while the given total number of candidates exists. + Candidate(#[codec(compact)] u32), +} + +/// Information needed to prove the defunct-ness of a voter. +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +pub struct DefunctVoter { + /// the voter's who's being challenged for being defunct + pub who: AccountId, + /// The number of votes that `who` has placed. + #[codec(compact)] + pub vote_count: u32, + /// The number of current active candidates. + #[codec(compact)] + pub candidate_count: u32 +} + pub trait Trait: frame_system::Trait { /// The overarching event type.c type Event: From> + Into<::Event>; @@ -166,6 +197,8 @@ decl_storage! { pub ElectionRounds get(fn election_rounds): u32 = Zero::zero(); /// Votes and locked stake of a particular voter. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash pub Voting get(fn voting): map hasher(twox_64_concat) T::AccountId => (BalanceOf, Vec); /// The present candidate list. Sorted based on account-id. A current member or runner-up @@ -238,10 +271,16 @@ decl_error! { RunnerSubmit, /// Candidate does not have enough funds. InsufficientCandidateFunds, - /// Origin is not a candidate, member or a runner up. - InvalidOrigin, /// Not a member. NotMember, + /// The provided count of number of candidates is incorrect. + InvalidCandidateCount, + /// The provided count of number of votes is incorrect. + InvalidVoteCount, + /// The renouncing origin presented a wrong `Renouncing` parameter. + InvalidRenouncing, + /// Prediction regarding replacement after member removal is wrong. + InvalidReplacement, } } @@ -258,46 +297,60 @@ decl_module! { const TermDuration: T::BlockNumber = T::TermDuration::get(); const ModuleId: LockIdentifier = T::ModuleId::get(); - /// Vote for a set of candidates for the upcoming round of election. + /// Vote for a set of candidates for the upcoming round of election. This can be called to + /// set the initial votes, or update already existing votes. + /// + /// Upon initial voting, `value` units of `who`'s balance is locked and a bond amount is + /// reserved. /// /// The `votes` should: /// - not be empty. - /// - be less than the number of candidates. + /// - be less than the number of possible candidates. Note that all current members and + /// runners-up are also automatically candidates for the next round. /// - /// Upon voting, `value` units of `who`'s balance is locked and a bond amount is reserved. /// It is the responsibility of the caller to not place all of their balance into the lock /// and keep some for further transactions. /// /// # - /// #### State - /// Reads: O(1) - /// Writes: O(V) given `V` votes. V is bounded by 16. + /// Base weight: 47.93 µs + /// State reads: + /// - Candidates.len() + Members.len() + RunnersUp.len() + /// - Voting (is_voter) + /// - [AccountBalance(who) (unreserve + total_balance)] + /// State writes: + /// - Voting + /// - Lock + /// - [AccountBalance(who) (unreserve -- only when creating a new voter)] /// # - #[weight = 100_000_000] - fn vote(origin, votes: Vec, #[compact] value: BalanceOf) { + #[weight = 50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)] + fn vote( + origin, + votes: Vec, + #[compact] value: BalanceOf, + ) { let who = ensure_signed(origin)?; - let candidates_count = >::decode_len().unwrap_or(0) as usize; - let members_count = >::decode_len().unwrap_or(0) as usize; - let runners_up_count = >::decode_len().unwrap_or(0) as usize; + ensure!(votes.len() <= MAXIMUM_VOTE, Error::::MaximumVotesExceeded); + ensure!(!votes.is_empty(), Error::::NoVotes); + + let candidates_count = >::decode_len().unwrap_or(0); + let members_count = >::decode_len().unwrap_or(0); + let runners_up_count = >::decode_len().unwrap_or(0); + // addition is valid: candidates, members and runners-up will never overlap. let allowed_votes = candidates_count + members_count + runners_up_count; ensure!(!allowed_votes.is_zero(), Error::::UnableToVote); ensure!(votes.len() <= allowed_votes, Error::::TooManyVotes); - ensure!(votes.len() <= MAXIMUM_VOTE, Error::::MaximumVotesExceeded); - ensure!(!votes.is_empty(), Error::::NoVotes); - ensure!( - value > T::Currency::minimum_balance(), - Error::::LowBalance, - ); + ensure!(value > T::Currency::minimum_balance(), Error::::LowBalance); + // first time voter. Reserve bond. if !Self::is_voter(&who) { - // first time voter. Reserve bond. T::Currency::reserve(&who, T::VotingBond::get()) .map_err(|_| Error::::UnableToPayBond)?; } + // Amount to be locked up. let locked_balance = value.min(T::Currency::total_balance(&who)); @@ -315,14 +368,19 @@ decl_module! { /// Remove `origin` as a voter. This removes the lock and returns the bond. /// /// # - /// #### State - /// Reads: O(1) - /// Writes: O(1) + /// Base weight: 36.8 µs + /// All state access is from do_remove_voter. + /// State reads: + /// - Voting + /// - [AccountData(who)] + /// State writes: + /// - Voting + /// - Locks + /// - [AccountData(who)] /// # - #[weight = 0] + #[weight = 35 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 2)] fn remove_voter(origin) { let who = ensure_signed(origin)?; - ensure!(Self::is_voter(&who), Error::::MustBeVoter); Self::do_remove_voter(&who, true); @@ -334,27 +392,62 @@ decl_module! { /// /// A defunct voter is defined to be: /// - a voter whose current submitted votes are all invalid. i.e. all of them are no - /// longer a candidate nor an active member. + /// longer a candidate nor an active member or a runner-up. + /// + /// + /// The origin must provide the number of current candidates and votes of the reported target + /// for the purpose of accurate weight calculation. /// /// # - /// #### State - /// Reads: O(NLogM) given M current candidates and N votes for `target`. - /// Writes: O(1) + /// No Base weight based on min square analysis. + /// Complexity of candidate_count: 1.755 µs + /// Complexity of vote_count: 18.51 µs + /// State reads: + /// - Voting(reporter) + /// - Candidate.len() + /// - Voting(Target) + /// - Candidates, Members, RunnersUp (is_defunct_voter) + /// State writes: + /// - Lock(reporter || target) + /// - [AccountBalance(reporter)] + AccountBalance(target) + /// - Voting(reporter || target) + /// Note: the db access is worse with respect to db, which is when the report is correct. /// # - #[weight = 1_000_000_000] - fn report_defunct_voter(origin, target: ::Source) { + #[weight = + Weight::from(defunct.candidate_count).saturating_mul(2 * WEIGHT_PER_MICROS) + .saturating_add(Weight::from(defunct.vote_count).saturating_mul(19 * WEIGHT_PER_MICROS)) + .saturating_add(T::DbWeight::get().reads_writes(6, 3)) + ] + fn report_defunct_voter( + origin, + defunct: DefunctVoter<::Source>, + ) { let reporter = ensure_signed(origin)?; - let target = T::Lookup::lookup(target)?; + let target = T::Lookup::lookup(defunct.who)?; ensure!(reporter != target, Error::::ReportSelf); ensure!(Self::is_voter(&reporter), Error::::MustBeVoter); - // Checking if someone is a candidate and a member here is O(LogN), making the whole - // function O(MLonN) with N candidates in total and M of them being voted by `target`. - // We could easily add another mapping to be able to check if someone is a candidate in - // `O(1)` but that would make the process of removing candidates at the end of each - // round slightly harder. Note that for now we have a bound of number of votes (`N`). - let valid = Self::is_defunct_voter(&target); + let DefunctVoter { candidate_count, vote_count, .. } = defunct; + + ensure!( + >::decode_len().unwrap_or(0) as u32 <= candidate_count, + Error::::InvalidCandidateCount, + ); + + let (_, votes) = >::get(&target); + // indirect way to ensure target is a voter. We could call into `::contains()`, but it + // would have the same effect with one extra db access. Note that votes cannot be + // submitted with length 0. Hence, a non-zero length means that the target is a voter. + ensure!(votes.len() > 0, Error::::MustBeVoter); + + // ensure that the size of votes that need to be searched is correct. + ensure!( + votes.len() as u32 <= vote_count, + Error::::InvalidVoteCount, + ); + + let valid = Self::is_defunct_voter(&votes); if valid { // reporter will get the voting bond of the target T::Currency::repatriate_reserved(&target, &reporter, T::VotingBond::get(), BalanceStatus::Free)?; @@ -370,7 +463,6 @@ decl_module! { Self::deposit_event(RawEvent::VoterReported(target, reporter, valid)); } - /// Submit oneself for candidacy. /// /// A candidate will either: @@ -380,21 +472,40 @@ decl_module! { /// removed. /// /// # - /// #### State - /// Reads: O(LogN) Given N candidates. - /// Writes: O(1) + /// Base weight = 33.33 µs + /// Complexity of candidate_count: 0.375 µs + /// State reads: + /// - Candidates.len() + /// - Candidates + /// - Members + /// - RunnersUp + /// - [AccountBalance(who)] + /// State writes: + /// - [AccountBalance(who)] + /// - Candidates /// # - #[weight = 500_000_000] - fn submit_candidacy(origin) { + #[weight = + (35 * WEIGHT_PER_MICROS) + .saturating_add(Weight::from(*candidate_count).saturating_mul(375 * WEIGHT_PER_NANOS)) + .saturating_add(T::DbWeight::get().reads_writes(4, 1)) + ] + fn submit_candidacy(origin, #[compact] candidate_count: u32) { let who = ensure_signed(origin)?; + let actual_count = >::decode_len().unwrap_or(0); + ensure!( + actual_count as u32 <= candidate_count, + Error::::InvalidCandidateCount, + ); + let is_candidate = Self::is_candidate(&who); ensure!(is_candidate.is_err(), Error::::DuplicatedCandidate); + // assured to be an error, error always contains the index. let index = is_candidate.unwrap_err(); ensure!(!Self::is_member(&who), Error::::MemberSubmit); - ensure!(!Self::is_runner(&who), Error::::RunnerSubmit); + ensure!(!Self::is_runner_up(&who), Error::::RunnerSubmit); T::Currency::reserve(&who, T::CandidacyBond::get()) .map_err(|_| Error::::InsufficientCandidateFunds)?; @@ -406,55 +517,93 @@ decl_module! { /// outcomes exist: /// - `origin` is a candidate and not elected in any set. In this case, the bond is /// unreserved, returned and origin is removed as a candidate. - /// - `origin` is a current runner up. In this case, the bond is unreserved, returned and - /// origin is removed as a runner. + /// - `origin` is a current runner-up. In this case, the bond is unreserved, returned and + /// origin is removed as a runner-up. /// - `origin` is a current member. In this case, the bond is unreserved and origin is /// removed as a member, consequently not being a candidate for the next round anymore. /// Similar to [`remove_voter`], if replacement runners exists, they are immediately used. - #[weight = (2_000_000_000, DispatchClass::Operational)] - fn renounce_candidacy(origin) { - let who = ensure_signed(origin)?; - - // NOTE: this function attempts the 3 conditions (being a candidate, member, runner) and - // fails if none are matched. Unlike other Palette functions and modules where checks - // happen first and then execution happens, this function is written the other way - // around. The main intention is that reading all of the candidates, members and runners - // from storage is expensive. Furthermore, we know (soft proof) that they are always - // mutually exclusive. Hence, we try one, and only then decode more storage. - - if let Ok(_replacement) = Self::remove_and_replace_member(&who) { - T::Currency::unreserve(&who, T::CandidacyBond::get()); - Self::deposit_event(RawEvent::MemberRenounced(who.clone())); - - // safety guard to make sure we do only one arm. Better to read runners later. - return Ok(()); - } - - let mut runners_up_with_stake = Self::runners_up(); - if let Some(index) = runners_up_with_stake.iter() - .position(|(ref r, ref _s)| r == &who) - { - runners_up_with_stake.remove(index); - // unreserve the bond - T::Currency::unreserve(&who, T::CandidacyBond::get()); - // update storage. - >::put(runners_up_with_stake); - // safety guard to make sure we do only one arm. Better to read runners later. - return Ok(()); - } - - let mut candidates = Self::candidates(); - if let Ok(index) = candidates.binary_search(&who) { - candidates.remove(index); - // unreserve the bond - T::Currency::unreserve(&who, T::CandidacyBond::get()); - // update storage. - >::put(candidates); - // safety guard to make sure we do only one arm. Better to read runners later. - return Ok(()); + /// + /// If a candidate is renouncing: + /// Base weight: 17.28 µs + /// Complexity of candidate_count: 0.235 µs + /// State reads: + /// - Candidates + /// - [AccountBalance(who) (unreserve)] + /// State writes: + /// - Candidates + /// - [AccountBalance(who) (unreserve)] + /// If member is renouncing: + /// Base weight: 46.25 µs + /// State reads: + /// - Members, RunnersUp (remove_and_replace_member), + /// - [AccountData(who) (unreserve)] + /// State writes: + /// - Members, RunnersUp (remove_and_replace_member), + /// - [AccountData(who) (unreserve)] + /// If runner is renouncing: + /// Base weight: 46.25 µs + /// State reads: + /// - RunnersUp (remove_and_replace_member), + /// - [AccountData(who) (unreserve)] + /// State writes: + /// - RunnersUp (remove_and_replace_member), + /// - [AccountData(who) (unreserve)] + /// + /// Weight note: The call into changeMembers need to be accounted for. + /// + #[weight = match *renouncing { + Renouncing::Candidate(count) => { + (18 * WEIGHT_PER_MICROS) + .saturating_add(Weight::from(count).saturating_mul(235 * WEIGHT_PER_NANOS)) + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) + }, + Renouncing::Member => { + 46 * WEIGHT_PER_MICROS + + T::DbWeight::get().reads_writes(2, 2) + }, + Renouncing::RunnerUp => { + 46 * WEIGHT_PER_MICROS + + T::DbWeight::get().reads_writes(1, 1) } - - Err(Error::::InvalidOrigin)? + }] + fn renounce_candidacy(origin, renouncing: Renouncing) { + let who = ensure_signed(origin)?; + match renouncing { + Renouncing::Member => { + // returns NoMember error in case of error. + let _ = Self::remove_and_replace_member(&who)?; + T::Currency::unreserve(&who, T::CandidacyBond::get()); + Self::deposit_event(RawEvent::MemberRenounced(who.clone())); + }, + Renouncing::RunnerUp => { + let mut runners_up_with_stake = Self::runners_up(); + if let Some(index) = runners_up_with_stake + .iter() + .position(|(ref r, ref _s)| r == &who) + { + runners_up_with_stake.remove(index); + // unreserve the bond + T::Currency::unreserve(&who, T::CandidacyBond::get()); + // update storage. + >::put(runners_up_with_stake); + } else { + Err(Error::::InvalidRenouncing)?; + } + } + Renouncing::Candidate(count) => { + let mut candidates = Self::candidates(); + ensure!(count >= candidates.len() as u32, Error::::InvalidRenouncing); + if let Some(index) = candidates.iter().position(|x| *x == who) { + candidates.remove(index); + // unreserve the bond + T::Currency::unreserve(&who, T::CandidacyBond::get()); + // update storage. + >::put(candidates); + } else { + Err(Error::::InvalidRenouncing)?; + } + } + }; } /// Remove a particular member from the set. This is effective immediately and the bond of @@ -466,34 +615,57 @@ decl_module! { /// Note that this does not affect the designated block number of the next election. /// /// # - /// #### State - /// Reads: O(do_phragmen) - /// Writes: O(do_phragmen) + /// If we have a replacement: + /// - Base weight: 50.93 µs + /// - State reads: + /// - RunnersUp.len() + /// - Members, RunnersUp (remove_and_replace_member) + /// - State writes: + /// - Members, RunnersUp (remove_and_replace_member) + /// Else, since this is a root call and will go into phragmen, we assume full block for now. /// # - #[weight = (2_000_000_000, DispatchClass::Operational)] - fn remove_member(origin, who: ::Source) -> DispatchResult { + #[weight = if *has_replacement { + 50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(3, 2) + } else { + T::MaximumBlockWeight::get() + }] + fn remove_member( + origin, + who: ::Source, + has_replacement: bool, + ) -> DispatchResultWithPostInfo { ensure_root(origin)?; let who = T::Lookup::lookup(who)?; + let will_have_replacement = >::decode_len().unwrap_or(0) > 0; + if will_have_replacement != has_replacement { + // In both cases, we will change more weight than neede. Refund and abort. + return Err(Error::::InvalidReplacement.with_weight( + // refund. The weight value comes from a benchmark which is special to this. + // 5.751 µs + 6 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 0) + )); + } // else, prediction was correct. + Self::remove_and_replace_member(&who).map(|had_replacement| { let (imbalance, _) = T::Currency::slash_reserved(&who, T::CandidacyBond::get()); T::KickedMember::on_unbalanced(imbalance); Self::deposit_event(RawEvent::MemberKicked(who.clone())); if !had_replacement { + // if we end up here, we will charge a full block weight. Self::do_phragmen(); } - }) + + // no refund needed. + None.into() + }).map_err(|e| e.into()) } /// What to do at the end of each block. Checks if an election needs to happen or not. fn on_initialize(n: T::BlockNumber) -> Weight { - if let Err(e) = Self::end_block(n) { - print("Guru meditation"); - print(e); - } - - 0 + // returns the correct weight. + Self::end_block(n) } } } @@ -523,13 +695,19 @@ decl_event!( ); impl Module { - /// Attempts to remove a member `who`. If a runner up exists, it is used as the replacement. + /// Attempts to remove a member `who`. If a runner-up exists, it is used as the replacement and + /// Ok(true). is returned. + /// /// Otherwise, `Ok(false)` is returned to signal the caller. /// - /// In both cases, [`Members`], [`ElectionRounds`] and [`RunnersUp`] storage are updated - /// accordingly. Furthermore, the membership change is reported. + /// If a replacement exists, `Members` and `RunnersUp` storage is updated, where the first + /// element of `RunnersUp` is used as the replacement and `Ok(true)` is returned. Else, + /// `Ok(false)` is returned with no storage updated. /// - /// O(phragmen) in the worse case. + /// Note that this function _will_ call into `T::ChangeMembers` in case any change happens + /// (`Ok(true)`). + /// + /// If replacement exists, this will read and write from/into both `Members` and `RunnersUp`. fn remove_and_replace_member(who: &T::AccountId) -> Result { let mut members_with_stake = Self::members(); if let Ok(index) = members_with_stake.binary_search_by(|(ref m, ref _s)| m.cmp(who)) { @@ -562,7 +740,7 @@ impl Module { /// Check if `who` is a candidate. It returns the insert index if the element does not exists as /// an error. /// - /// State: O(LogN) given N candidates. + /// O(LogN) given N candidates. fn is_candidate(who: &T::AccountId) -> Result<(), usize> { Self::candidates().binary_search(who).map(|_| ()) } @@ -576,15 +754,15 @@ impl Module { /// Check if `who` is currently an active member. /// - /// Limited number of members. Binary search. Constant time factor. O(1) + /// O(LogN) given N members. Since members are limited, O(1). fn is_member(who: &T::AccountId) -> bool { Self::members().binary_search_by(|(a, _b)| a.cmp(who)).is_ok() } - /// Check if `who` is currently an active runner. + /// Check if `who` is currently an active runner-up. /// - /// Limited number of runners-up. Binary search. Constant time factor. O(1) - fn is_runner(who: &T::AccountId) -> bool { + /// O(LogN) given N runners-up. Since runners-up are limited, O(1). + fn is_runner_up(who: &T::AccountId) -> bool { Self::runners_up().iter().position(|(a, _b)| a == who).is_some() } @@ -613,25 +791,24 @@ impl Module { Self::runners_up().into_iter().map(|(r, _)| r).collect::>() } - /// Check if `who` is a defunct voter. - /// - /// Note that false is returned if `who` is not a voter at all. + /// Check if `votes` will correspond to a defunct voter. As no origin is part of the inputs, + /// this function does not check the origin at all. /// /// O(NLogM) with M candidates and `who` having voted for `N` of them. - fn is_defunct_voter(who: &T::AccountId) -> bool { - if Self::is_voter(who) { - Self::votes_of(who) - .iter() - .all(|v| !Self::is_member(v) && !Self::is_runner(v) && !Self::is_candidate(v).is_ok()) - } else { - false - } + /// Reads Members, RunnersUp, Candidates and Voting(who) from database. + fn is_defunct_voter(votes: &[T::AccountId]) -> bool { + votes.iter().all(|v| + !Self::is_member(v) && !Self::is_runner_up(v) && !Self::is_candidate(v).is_ok() + ) } /// Remove a certain someone as a voter. /// /// This will clean always clean the storage associated with the voter, and remove the balance /// lock. Optionally, it would also return the reserved voting bond if indicated by `unreserve`. + /// If unreserve is true, has 3 storage reads and 1 reads. + /// + /// DB access: Voting and Lock are always written to, if unreserve, then 1 read and write added. fn do_remove_voter(who: &T::AccountId, unreserve: bool) { // remove storage and lock. Voting::::remove(who); @@ -647,22 +824,18 @@ impl Module { Voting::::get(who).0 } - /// The locked stake of a voter. - fn votes_of(who: &T::AccountId) -> Vec { - Voting::::get(who).1 - } - /// Check there's nothing to do this block. /// /// Runs phragmen election and cleans all the previous candidate state. The voter state is NOT /// cleaned and voters must themselves submit a transaction to retract. - fn end_block(block_number: T::BlockNumber) -> DispatchResult { + fn end_block(block_number: T::BlockNumber) -> Weight { if !Self::term_duration().is_zero() { if (block_number % Self::term_duration()).is_zero() { Self::do_phragmen(); + return T::MaximumBlockWeight::get() } } - Ok(()) + 0 } /// Run the phragmen election with all required side processes and state updates. @@ -881,11 +1054,13 @@ impl ContainsLengthBound for Module { mod tests { use super::*; use std::cell::RefCell; - use frame_support::{assert_ok, assert_noop, parameter_types, weights::Weight}; + use frame_support::{assert_ok, assert_noop, assert_err_with_weight, parameter_types, + weights::Weight, + }; use substrate_test_utils::assert_eq_uvec; use sp_core::H256; use sp_runtime::{ - Perbill, testing::Header, BuildStorage, + Perbill, testing::Header, BuildStorage, DispatchResult, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, }; use crate as elections_phragmen; @@ -914,6 +1089,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -1000,7 +1176,7 @@ mod tests { new_plus_outgoing.extend_from_slice(outgoing); new_plus_outgoing.sort(); - assert_eq!(old_plus_incoming, new_plus_outgoing); + assert_eq!(old_plus_incoming, new_plus_outgoing, "change members call is incorrect!"); MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); PRIME.with(|p| *p.borrow_mut() = None); @@ -1064,6 +1240,7 @@ mod tests { voter_bond: u64, term_duration: u64, desired_runners_up: u32, + desired_members: u32, } impl Default for ExtBuilder { @@ -1072,8 +1249,9 @@ mod tests { genesis_members: vec![], balance_factor: 1, voter_bond: 2, - desired_runners_up: 0, term_duration: 5, + desired_runners_up: 0, + desired_members: 2, } } } @@ -1095,15 +1273,24 @@ mod tests { self.genesis_members = members; self } + #[cfg(feature = "runtime-benchmarks")] + pub fn desired_members(mut self, count: u32) -> Self { + self.desired_members = count; + self + } pub fn balance_factor(mut self, factor: u64) -> Self { self.balance_factor = factor; self } - pub fn build_and_execute(self, test: impl FnOnce() -> ()) { + fn set_constants(&self) { VOTING_BOND.with(|v| *v.borrow_mut() = self.voter_bond); TERM_DURATION.with(|v| *v.borrow_mut() = self.term_duration); DESIRED_RUNNERS_UP.with(|v| *v.borrow_mut() = self.desired_runners_up); + DESIRED_MEMBERS.with(|m| *m.borrow_mut() = self.desired_members); MEMBERS.with(|m| *m.borrow_mut() = self.genesis_members.iter().map(|(m, _)| m.clone()).collect::>()); + } + pub fn build_and_execute(self, test: impl FnOnce() -> ()) { + self.set_constants(); let mut ext: sp_io::TestExternalities = GenesisConfig { pallet_balances: Some(pallet_balances::GenesisConfig::{ balances: vec![ @@ -1185,6 +1372,33 @@ mod tests { ensure_members_has_approval_stake(); } + fn submit_candidacy(origin: Origin) -> DispatchResult { + Elections::submit_candidacy(origin, Elections::candidates().len() as u32) + } + + fn vote(origin: Origin, votes: Vec, stake: u64) -> DispatchResult { + // historical note: helper function was created in a period of time in which the API of vote + // call was changing. Currently it is a wrapper for the original call and does not do much. + // Nonetheless, totally harmless. + if let Origin::system(frame_system::RawOrigin::Signed(_account)) = origin { + Elections::vote(origin, votes, stake) + } else { + panic!("vote origin must be signed"); + } + } + + fn votes_of(who: &u64) -> Vec { + Voting::::get(who).1 + } + + fn defunct_for(who: u64) -> DefunctVoter { + DefunctVoter { + who, + candidate_count: Elections::candidates().len() as u32, + vote_count: votes_of(&who).len() as u32 + } + } + #[test] fn params_should_work() { ExtBuilder::default().build_and_execute(|| { @@ -1196,11 +1410,11 @@ mod tests { assert_eq!(Elections::runners_up(), vec![]); assert_eq!(Elections::candidates(), vec![]); - assert_eq!(>::decode_len().unwrap(), 0); + assert_eq!(>::decode_len(), None); assert!(Elections::is_candidate(&1).is_err()); assert_eq!(all_voters(), vec![]); - assert_eq!(Elections::votes_of(&1), vec![]); + assert_eq!(votes_of(&1), vec![]); }); } @@ -1215,7 +1429,7 @@ mod tests { // they will persist since they have self vote. System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![1, 2]); }) @@ -1232,7 +1446,7 @@ mod tests { // they will persist since they have self vote. System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![1, 2]); }) @@ -1280,7 +1494,7 @@ mod tests { assert_eq!(Elections::candidates(), vec![]); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![]); assert_eq!(Elections::runners_up(), vec![]); @@ -1296,7 +1510,7 @@ mod tests { assert!(Elections::is_candidate(&2).is_err()); assert_eq!(balances(&1), (10, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(submit_candidacy(Origin::signed(1))); assert_eq!(balances(&1), (7, 3)); assert_eq!(Elections::candidates(), vec![1]); @@ -1305,7 +1519,7 @@ mod tests { assert!(Elections::is_candidate(&2).is_err()); assert_eq!(balances(&2), (20, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(2))); assert_eq!(balances(&2), (17, 3)); assert_eq!(Elections::candidates(), vec![1, 2]); @@ -1320,8 +1534,8 @@ mod tests { ExtBuilder::default().build_and_execute(|| { assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(1))); + assert_ok!(submit_candidacy(Origin::signed(2))); assert!(Elections::is_candidate(&1).is_ok()); assert!(Elections::is_candidate(&2).is_ok()); @@ -1331,7 +1545,7 @@ mod tests { assert_eq!(Elections::runners_up(), vec![]); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert!(Elections::is_candidate(&1).is_err()); assert!(Elections::is_candidate(&2).is_err()); @@ -1346,10 +1560,10 @@ mod tests { fn dupe_candidate_submission_should_not_work() { ExtBuilder::default().build_and_execute(|| { assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(submit_candidacy(Origin::signed(1))); assert_eq!(Elections::candidates(), vec![1]); assert_noop!( - Elections::submit_candidacy(Origin::signed(1)), + submit_candidacy(Origin::signed(1)), Error::::DuplicatedCandidate, ); }); @@ -1359,18 +1573,18 @@ mod tests { fn member_candidacy_submission_should_not_work() { // critically important to make sure that outgoing candidates and losers are not mixed up. ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![5]); assert_eq!(Elections::runners_up(), vec![]); assert_eq!(Elections::candidates(), vec![]); assert_noop!( - Elections::submit_candidacy(Origin::signed(5)), + submit_candidacy(Origin::signed(5)), Error::::MemberSubmit, ); }); @@ -1379,21 +1593,21 @@ mod tests { #[test] fn runner_candidate_submission_should_not_work() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5, 4], 20)); - assert_ok!(Elections::vote(Origin::signed(1), vec![3], 10)); + assert_ok!(vote(Origin::signed(2), vec![5, 4], 20)); + assert_ok!(vote(Origin::signed(1), vec![3], 10)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![3]); assert_noop!( - Elections::submit_candidacy(Origin::signed(3)), + submit_candidacy(Origin::signed(3)), Error::::RunnerSubmit, ); }); @@ -1404,7 +1618,7 @@ mod tests { ExtBuilder::default().build_and_execute(|| { assert_eq!(Elections::candidates(), Vec::::new()); assert_noop!( - Elections::submit_candidacy(Origin::signed(7)), + submit_candidacy(Origin::signed(7)), Error::::InsufficientCandidateFunds, ); }); @@ -1416,8 +1630,8 @@ mod tests { assert_eq!(Elections::candidates(), Vec::::new()); assert_eq!(balances(&2), (20, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); assert_eq!(balances(&2), (18, 2)); assert_eq!(has_lock(&2), 20); @@ -1430,8 +1644,8 @@ mod tests { assert_eq!(Elections::candidates(), Vec::::new()); assert_eq!(balances(&2), (20, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 12)); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(vote(Origin::signed(2), vec![5], 12)); assert_eq!(balances(&2), (18, 2)); assert_eq!(has_lock(&2), 12); @@ -1443,16 +1657,16 @@ mod tests { ExtBuilder::default().build_and_execute(|| { assert_eq!(balances(&2), (20, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); assert_eq!(balances(&2), (18, 2)); assert_eq!(has_lock(&2), 20); assert_eq!(Elections::locked_stake_of(&2), 20); // can update; different stake; different lock and reserve. - assert_ok!(Elections::vote(Origin::signed(2), vec![5, 4], 15)); + assert_ok!(vote(Origin::signed(2), vec![5, 4], 15)); assert_eq!(balances(&2), (18, 2)); assert_eq!(has_lock(&2), 15); assert_eq!(Elections::locked_stake_of(&2), 15); @@ -1463,8 +1677,8 @@ mod tests { fn cannot_vote_for_no_candidate() { ExtBuilder::default().build_and_execute(|| { assert_noop!( - Elections::vote(Origin::signed(2), vec![], 20), - Error::::UnableToVote, + vote(Origin::signed(2), vec![], 20), + Error::::NoVotes, ); }); } @@ -1472,41 +1686,41 @@ mod tests { #[test] fn can_vote_for_old_members_even_when_no_new_candidates() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + assert_ok!(vote(Origin::signed(2), vec![4, 5], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::candidates(), vec![]); - assert_ok!(Elections::vote(Origin::signed(3), vec![4, 5], 10)); + assert_ok!(vote(Origin::signed(3), vec![4, 5], 10)); }); } #[test] fn prime_works() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(1), vec![4, 3], 10)); - assert_ok!(Elections::vote(Origin::signed(2), vec![4], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(1), vec![4, 3], 10)); + assert_ok!(vote(Origin::signed(2), vec![4], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::candidates(), vec![]); - assert_ok!(Elections::vote(Origin::signed(3), vec![4, 5], 10)); + assert_ok!(vote(Origin::signed(3), vec![4, 5], 10)); assert_eq!(PRIME.with(|p| *p.borrow()), Some(4)); }); } @@ -1514,20 +1728,20 @@ mod tests { #[test] fn prime_votes_for_exiting_members_are_removed() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(1), vec![4, 3], 10)); - assert_ok!(Elections::vote(Origin::signed(2), vec![4], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(1), vec![4, 3], 10)); + assert_ok!(vote(Origin::signed(2), vec![4], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::renounce_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Candidate(3))); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![3, 5]); assert_eq!(Elections::candidates(), vec![]); @@ -1544,29 +1758,29 @@ mod tests { .build_and_execute( || { // when we have only candidates - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); assert_noop!( // content of the vote is irrelevant. - Elections::vote(Origin::signed(1), vec![9, 99, 999, 9999], 5), + vote(Origin::signed(1), vec![9, 99, 999, 9999], 5), Error::::TooManyVotes, ); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // now we have 2 members, 1 runner-up, and 1 new candidate - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(1), vec![9, 99, 999, 9999], 5)); + assert_ok!(vote(Origin::signed(1), vec![9, 99, 999, 9999], 5)); assert_noop!( - Elections::vote(Origin::signed(1), vec![9, 99, 999, 9_999, 99_999], 5), + vote(Origin::signed(1), vec![9, 99, 999, 9_999, 99_999], 5), Error::::TooManyVotes, ); }); @@ -1575,11 +1789,11 @@ mod tests { #[test] fn cannot_vote_for_less_than_ed() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); assert_noop!( - Elections::vote(Origin::signed(2), vec![4], 1), + vote(Origin::signed(2), vec![4], 1), Error::::LowBalance, ); }) @@ -1588,10 +1802,10 @@ mod tests { #[test] fn can_vote_for_more_than_total_balance_but_moot() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 30)); + assert_ok!(vote(Origin::signed(2), vec![4, 5], 30)); // you can lie but won't get away with it. assert_eq!(Elections::locked_stake_of(&2), 20); assert_eq!(has_lock(&2), 20); @@ -1601,21 +1815,21 @@ mod tests { #[test] fn remove_voter_should_work() { ExtBuilder::default().voter_bond(8).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![5], 30)); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); + assert_ok!(vote(Origin::signed(3), vec![5], 30)); assert_eq_uvec!(all_voters(), vec![2, 3]); assert_eq!(Elections::locked_stake_of(&2), 20); assert_eq!(Elections::locked_stake_of(&3), 30); - assert_eq!(Elections::votes_of(&2), vec![5]); - assert_eq!(Elections::votes_of(&3), vec![5]); + assert_eq!(votes_of(&2), vec![5]); + assert_eq!(votes_of(&3), vec![5]); assert_ok!(Elections::remove_voter(Origin::signed(2))); assert_eq_uvec!(all_voters(), vec![3]); - assert_eq!(Elections::votes_of(&2), vec![]); + assert_eq!(votes_of(&2), vec![]); assert_eq!(Elections::locked_stake_of(&2), 0); assert_eq!(balances(&2), (20, 0)); @@ -1633,8 +1847,8 @@ mod tests { #[test] fn dupe_remove_should_fail() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); assert_ok!(Elections::remove_voter(Origin::signed(2))); assert_eq!(all_voters(), vec![]); @@ -1646,18 +1860,18 @@ mod tests { #[test] fn removed_voter_should_not_be_counted() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); assert_ok!(Elections::remove_voter(Origin::signed(4))); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![3, 5]); }); @@ -1667,47 +1881,102 @@ mod tests { fn reporter_must_be_voter() { ExtBuilder::default().build_and_execute(|| { assert_noop!( - Elections::report_defunct_voter(Origin::signed(1), 2), + Elections::report_defunct_voter(Origin::signed(1), defunct_for(2)), Error::::MustBeVoter, ); }); } + #[test] + fn reporter_must_provide_lengths() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + // both are defunct. + assert_ok!(vote(Origin::signed(5), vec![99, 999, 9999], 50)); + assert_ok!(vote(Origin::signed(4), vec![999], 40)); + + // 3 candidates! incorrect candidate length. + assert_noop!( + Elections::report_defunct_voter(Origin::signed(4), DefunctVoter { + who: 5, + candidate_count: 2, + vote_count: 3, + }), + Error::::InvalidCandidateCount, + ); + + // 3 votes! incorrect vote length + assert_noop!( + Elections::report_defunct_voter(Origin::signed(4), DefunctVoter { + who: 5, + candidate_count: 3, + vote_count: 2, + }), + Error::::InvalidVoteCount, + ); + + // correct. + assert_ok!(Elections::report_defunct_voter(Origin::signed(4), DefunctVoter { + who: 5, + candidate_count: 3, + vote_count: 3, + })); + }); + } + + #[test] + fn reporter_can_overestimate_length() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + + // both are defunct. + assert_ok!(vote(Origin::signed(5), vec![99], 50)); + assert_ok!(vote(Origin::signed(4), vec![999], 40)); + + // 2 candidates! overestimation is okay. + assert_ok!(Elections::report_defunct_voter(Origin::signed(4), defunct_for(5))); + }); + } + #[test] fn can_detect_defunct_voter() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(6))); - - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); - assert_ok!(Elections::vote(Origin::signed(6), vec![6], 30)); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(6))); + + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(2), vec![4, 5], 20)); + assert_ok!(vote(Origin::signed(6), vec![6], 30)); // will be soon a defunct voter. - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![6]); assert_eq!(Elections::candidates(), vec![]); // all of them have a member or runner-up that they voted for. - assert_eq!(Elections::is_defunct_voter(&5), false); - assert_eq!(Elections::is_defunct_voter(&4), false); - assert_eq!(Elections::is_defunct_voter(&2), false); - assert_eq!(Elections::is_defunct_voter(&6), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&5)), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&4)), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&2)), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&6)), false); // defunct - assert_eq!(Elections::is_defunct_voter(&3), true); + assert_eq!(Elections::is_defunct_voter(&votes_of(&3)), true); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); + assert_ok!(submit_candidacy(Origin::signed(1))); + assert_ok!(vote(Origin::signed(1), vec![1], 10)); // has a candidate voted for. - assert_eq!(Elections::is_defunct_voter(&1), false); + assert_eq!(Elections::is_defunct_voter(&votes_of(&1)), false); }); } @@ -1715,17 +1984,17 @@ mod tests { #[test] fn report_voter_should_work_and_earn_reward() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(2), vec![4, 5], 20)); // will be soon a defunct voter. - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::candidates(), vec![]); @@ -1733,7 +2002,7 @@ mod tests { assert_eq!(balances(&3), (28, 2)); assert_eq!(balances(&5), (45, 5)); - assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 3)); + assert_ok!(Elections::report_defunct_voter(Origin::signed(5), defunct_for(3))); assert!(System::events().iter().any(|event| { event.event == Event::elections_phragmen(RawEvent::VoterReported(3, 5, true)) })); @@ -1746,14 +2015,14 @@ mod tests { #[test] fn report_voter_should_slash_when_bad_report() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::candidates(), vec![]); @@ -1761,7 +2030,7 @@ mod tests { assert_eq!(balances(&4), (35, 5)); assert_eq!(balances(&5), (45, 5)); - assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 4)); + assert_ok!(Elections::report_defunct_voter(Origin::signed(5), defunct_for(4))); assert!(System::events().iter().any(|event| { event.event == Event::elections_phragmen(RawEvent::VoterReported(4, 5, false)) })); @@ -1774,19 +2043,19 @@ mod tests { #[test] fn simple_voting_rounds_should_work() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 15)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); + assert_ok!(vote(Origin::signed(4), vec![4], 15)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); assert_eq_uvec!(all_voters(), vec![2, 3, 4]); - assert_eq!(Elections::votes_of(&2), vec![5]); - assert_eq!(Elections::votes_of(&3), vec![3]); - assert_eq!(Elections::votes_of(&4), vec![4]); + assert_eq!(votes_of(&2), vec![5]); + assert_eq!(votes_of(&3), vec![3]); + assert_eq!(votes_of(&4), vec![4]); assert_eq!(Elections::candidates(), vec![3, 4, 5]); assert_eq!(>::decode_len().unwrap(), 3); @@ -1794,13 +2063,13 @@ mod tests { assert_eq!(Elections::election_rounds(), 0); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members(), vec![(3, 30), (5, 20)]); assert_eq!(Elections::runners_up(), vec![]); assert_eq_uvec!(all_voters(), vec![2, 3, 4]); assert_eq!(Elections::candidates(), vec![]); - assert_eq!(>::decode_len().unwrap(), 0); + assert_eq!(>::decode_len(), None); assert_eq!(Elections::election_rounds(), 1); }); @@ -1809,23 +2078,23 @@ mod tests { #[test] fn defunct_voter_will_be_counted() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(5))); // This guy's vote is pointless for this round. - assert_ok!(Elections::vote(Origin::signed(3), vec![4], 30)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(3), vec![4], 30)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members(), vec![(5, 50)]); assert_eq!(Elections::election_rounds(), 1); // but now it has a valid target. - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(4))); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // candidate 4 is affected by an old vote. assert_eq!(Elections::members(), vec![(4, 30), (5, 50)]); @@ -1837,18 +2106,18 @@ mod tests { #[test] fn only_desired_seats_are_chosen() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::election_rounds(), 1); assert_eq!(Elections::members_ids(), vec![4, 5]); @@ -1858,11 +2127,11 @@ mod tests { #[test] fn phragmen_should_not_self_vote() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::candidates(), vec![]); assert_eq!(Elections::election_rounds(), 1); @@ -1878,18 +2147,18 @@ mod tests { #[test] fn runners_up_should_be_kept() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![2], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); + assert_ok!(vote(Origin::signed(2), vec![3], 20)); + assert_ok!(vote(Origin::signed(3), vec![2], 30)); + assert_ok!(vote(Origin::signed(4), vec![5], 40)); + assert_ok!(vote(Origin::signed(5), vec![4], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // sorted based on account id. assert_eq!(Elections::members_ids(), vec![4, 5]); // sorted based on merit (least -> most) @@ -1905,25 +2174,25 @@ mod tests { #[test] fn runners_up_should_be_next_candidates() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members(), vec![(4, 40), (5, 50)]); assert_eq!(Elections::runners_up(), vec![(2, 20), (3, 30)]); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 15)); + assert_ok!(vote(Origin::signed(5), vec![5], 15)); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members(), vec![(3, 30), (4, 40)]); assert_eq!(Elections::runners_up(), vec![(5, 15), (2, 20)]); }); @@ -1932,25 +2201,25 @@ mod tests { #[test] fn runners_up_lose_bond_once_outgoing() { ExtBuilder::default().desired_runners_up(1).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![2]); assert_eq!(balances(&2), (15, 5)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::runners_up_ids(), vec![3]); assert_eq!(balances(&2), (15, 2)); @@ -1962,21 +2231,21 @@ mod tests { ExtBuilder::default().build_and_execute(|| { assert_eq!(balances(&5), (50, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(5))); assert_eq!(balances(&5), (47, 3)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); assert_eq!(balances(&5), (45, 5)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![5]); assert_ok!(Elections::remove_voter(Origin::signed(5))); assert_eq!(balances(&5), (47, 3)); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![]); assert_eq!(balances(&5), (47, 0)); @@ -1986,16 +2255,16 @@ mod tests { #[test] fn losers_will_lose_the_bond() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + assert_ok!(vote(Origin::signed(4), vec![5], 40)); assert_eq!(balances(&5), (47, 3)); assert_eq!(balances(&3), (27, 3)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![5]); @@ -2009,23 +2278,23 @@ mod tests { #[test] fn current_members_are_always_next_candidate() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::election_rounds(), 1); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(submit_candidacy(Origin::signed(2))); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); assert_ok!(Elections::remove_voter(Origin::signed(4))); @@ -2033,7 +2302,7 @@ mod tests { assert_eq!(Elections::candidates(), vec![2, 3]); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // 4 removed; 5 and 3 are the new best. assert_eq!(Elections::members_ids(), vec![3, 5]); @@ -2045,19 +2314,19 @@ mod tests { // what I mean by uninterrupted: // given no input or stimulants the same members are re-elected. ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); let check_at_block = |b: u32| { System::set_block_number(b.into()); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // we keep re-electing the same folks. assert_eq!(Elections::members(), vec![(4, 40), (5, 50)]); assert_eq!(Elections::runners_up(), vec![(2, 20), (3, 30)]); @@ -2078,22 +2347,22 @@ mod tests { #[test] fn remove_members_triggers_election() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::election_rounds(), 1); // a new candidate - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::remove_member(Origin::ROOT, 4)); + assert_ok!(Elections::remove_member(Origin::ROOT, 4, false)); assert_eq!(balances(&4), (35, 2)); // slashed assert_eq!(Elections::election_rounds(), 2); // new election round @@ -2101,24 +2370,68 @@ mod tests { }); } + #[test] + fn remove_member_should_indicate_replacement() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + assert_eq!(Elections::members_ids(), vec![4, 5]); + + // no replacement yet. + assert_err_with_weight!( + Elections::remove_member(Origin::ROOT, 4, true), + Error::::InvalidReplacement, + Some(6000000), + ); + }); + + ExtBuilder::default().desired_runners_up(1).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![3]); + + // there is a replacement! and this one needs a weight refund. + assert_err_with_weight!( + Elections::remove_member(Origin::ROOT, 4, false), + Error::::InvalidReplacement, + Some(6000000) // only thing that matters for now is that it is NOT the full block. + ); + }); + } + #[test] fn seats_should_be_released_when_no_vote() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(2), vec![3], 20)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); assert_eq!(>::decode_len().unwrap(), 3); assert_eq!(Elections::election_rounds(), 0); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![3, 5]); assert_eq!(Elections::election_rounds(), 1); @@ -2129,7 +2442,7 @@ mod tests { // meanwhile, no one cares to become a candidate again. System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![]); assert_eq!(Elections::election_rounds(), 2); }); @@ -2138,32 +2451,32 @@ mod tests { #[test] fn incoming_outgoing_are_reported() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(1))); + assert_ok!(submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(3))); // 5 will change their vote and becomes an `outgoing` - assert_ok!(Elections::vote(Origin::signed(5), vec![4], 8)); + assert_ok!(vote(Origin::signed(5), vec![4], 8)); // 4 will stay in the set - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); // 3 will become a winner - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); // these two are losers. - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(1), vec![1], 10)); System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // 3, 4 are new members, must still be bonded, nothing slashed. assert_eq!(Elections::members(), vec![(3, 30), (4, 48)]); @@ -2185,15 +2498,15 @@ mod tests { #[test] fn invalid_votes_are_moot() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![10], 50)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![10], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq_uvec!(Elections::members_ids(), vec![3, 4]); assert_eq!(Elections::election_rounds(), 1); @@ -2203,18 +2516,18 @@ mod tests { #[test] fn members_are_sorted_based_on_id_runners_on_merit() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![2], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); + assert_ok!(vote(Origin::signed(2), vec![3], 20)); + assert_ok!(vote(Origin::signed(3), vec![2], 30)); + assert_ok!(vote(Origin::signed(4), vec![5], 40)); + assert_ok!(vote(Origin::signed(5), vec![4], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); // id: low -> high. assert_eq!(Elections::members(), vec![(4, 50), (5, 40)]); // merit: low -> high. @@ -2225,14 +2538,14 @@ mod tests { #[test] fn candidates_are_sorted() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(3))); assert_eq!(Elections::candidates(), vec![3, 5]); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(3), Renouncing::Candidate(4))); assert_eq!(Elections::candidates(), vec![2, 4, 5]); }) @@ -2241,64 +2554,43 @@ mod tests { #[test] fn runner_up_replacement_maintains_members_order() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![2], 50)); + assert_ok!(vote(Origin::signed(2), vec![5], 20)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![2], 50)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![2, 4]); - assert_ok!(Elections::remove_member(Origin::ROOT, 2)); + assert_ok!(Elections::remove_member(Origin::ROOT, 2, true)); assert_eq!(Elections::members_ids(), vec![4, 5]); }); } - #[test] - fn runner_up_replacement_works_when_out_of_order() { - ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![2], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members_ids(), vec![2, 4]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); - }); - } - #[test] fn can_renounce_candidacy_member_with_runners_bond_is_refunded() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![2, 3]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Member)); assert_eq!(balances(&4), (38, 2)); // 2 is voting bond. assert_eq!(Elections::members_ids(), vec![3, 5]); @@ -2309,55 +2601,47 @@ mod tests { #[test] fn can_renounce_candidacy_member_without_runners_bond_is_refunded() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![]); - assert_eq!(Elections::candidates(), vec![2, 3]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Member)); assert_eq!(balances(&4), (38, 2)); // 2 is voting bond. // no replacement assert_eq!(Elections::members_ids(), vec![5]); assert_eq!(Elections::runners_up_ids(), vec![]); - // still candidate - assert_eq!(Elections::candidates(), vec![2, 3]); }) } #[test] fn can_renounce_candidacy_runner() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + assert_ok!(submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(5), vec![4], 50)); + assert_ok!(vote(Origin::signed(4), vec![5], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::runners_up_ids(), vec![2, 3]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(3), Renouncing::RunnerUp)); assert_eq!(balances(&3), (28, 2)); // 2 is voting bond. assert_eq!(Elections::members_ids(), vec![4, 5]); @@ -2365,14 +2649,38 @@ mod tests { }) } + // #[test] + // fn runner_up_replacement_works_when_out_of_order() { + // ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { + // assert_ok!(submit_candidacy(Origin::signed(5))); + // assert_ok!(submit_candidacy(Origin::signed(4))); + // assert_ok!(submit_candidacy(Origin::signed(3))); + // assert_ok!(submit_candidacy(Origin::signed(2))); + + // assert_ok!(vote(Origin::signed(2), vec![5], 20)); + // assert_ok!(vote(Origin::signed(3), vec![3], 30)); + // assert_ok!(vote(Origin::signed(4), vec![4], 40)); + // assert_ok!(vote(Origin::signed(5), vec![2], 50)); + + // System::set_block_number(5); + // Elections::end_block(System::block_number()); + + // assert_eq!(Elections::members_ids(), vec![2, 4]); + // assert_eq!(ELections::runners_up_ids(), vec![3, 5]); + // assert_ok!(Elections::renounce_candidacy(Origin::signed(3), Renouncing::RunnerUp)); + // assert_eq!(Elections::members_ids(), vec![2, 4]); + // assert_eq!(ELections::runners_up_ids(), vec![5]); + // }); + // } + #[test] fn can_renounce_candidacy_candidate() { ExtBuilder::default().build_and_execute(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(5))); assert_eq!(balances(&5), (47, 3)); assert_eq!(Elections::candidates(), vec![5]); - assert_ok!(Elections::renounce_candidacy(Origin::signed(5))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(5), Renouncing::Candidate(1))); assert_eq!(balances(&5), (50, 0)); assert_eq!(Elections::candidates(), vec![]); }) @@ -2382,25 +2690,107 @@ mod tests { fn wrong_renounce_candidacy_should_fail() { ExtBuilder::default().build_and_execute(|| { assert_noop!( - Elections::renounce_candidacy(Origin::signed(5)), - Error::::InvalidOrigin, + Elections::renounce_candidacy(Origin::signed(5), Renouncing::Candidate(0)), + Error::::InvalidRenouncing, + ); + assert_noop!( + Elections::renounce_candidacy(Origin::signed(5), Renouncing::Member), + Error::::NotMember, + ); + assert_noop!( + Elections::renounce_candidacy(Origin::signed(5), Renouncing::RunnerUp), + Error::::InvalidRenouncing, + ); + }) + } + + #[test] + fn non_member_renounce_member_should_fail() { + ExtBuilder::default().desired_runners_up(1).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![3]); + + assert_noop!( + Elections::renounce_candidacy(Origin::signed(3), Renouncing::Member), + Error::::NotMember, + ); + }) + } + + #[test] + fn non_runner_up_renounce_runner_up_should_fail() { + ExtBuilder::default().desired_runners_up(1).build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + assert_ok!(vote(Origin::signed(5), vec![5], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(5); + Elections::end_block(System::block_number()); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![3]); + + assert_noop!( + Elections::renounce_candidacy(Origin::signed(4), Renouncing::RunnerUp), + Error::::InvalidRenouncing, + ); + }) + } + + #[test] + fn wrong_candidate_count_renounce_should_fail() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + + assert_noop!( + Elections::renounce_candidacy(Origin::signed(4), Renouncing::Candidate(2)), + Error::::InvalidRenouncing, ); + + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Candidate(3))); + }) + } + + #[test] + fn renounce_candidacy_count_can_overestimate() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(submit_candidacy(Origin::signed(5))); + assert_ok!(submit_candidacy(Origin::signed(4))); + assert_ok!(submit_candidacy(Origin::signed(3))); + // while we have only 3 candidates. + assert_ok!(Elections::renounce_candidacy(Origin::signed(4), Renouncing::Candidate(4))); }) } #[test] fn behavior_with_dupe_candidate() { ExtBuilder::default().desired_runners_up(2).build_and_execute(|| { - // TODD: this is a demonstration and should be fixed with #4593 >::put(vec![1, 1, 2, 3, 4]); - assert_ok!(Elections::vote(Origin::signed(5), vec![1], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(vote(Origin::signed(5), vec![1], 50)); + assert_ok!(vote(Origin::signed(4), vec![4], 40)); + assert_ok!(vote(Origin::signed(3), vec![3], 30)); + assert_ok!(vote(Origin::signed(2), vec![2], 20)); System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); + Elections::end_block(System::block_number()); assert_eq!(Elections::members_ids(), vec![1, 4]); assert_eq!(Elections::runners_up_ids(), vec![2, 3]); diff --git a/frame/elections/Cargo.toml b/frame/elections/Cargo.toml index 407b5ccfdb1769d503ad1c5270529f3c8cd75470..bd0dc2a1dd8c1de767c61af5ecf7bf74ecbdd99d 100644 --- a/frame/elections/Cargo.toml +++ b/frame/elections/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-elections" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for elections" @@ -14,16 +14,16 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] hex-literal = "0.2.1" -pallet-balances = { version = "2.0.0-dev", path = "../balances" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } [features] default = ["std"] diff --git a/frame/elections/src/lib.rs b/frame/elections/src/lib.rs index a684ce3144d8027154fb3d9fabca6fc607a342ac..10858313733dc815539a70fb6e345c9f80f2658b 100644 --- a/frame/elections/src/lib.rs +++ b/frame/elections/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Election module for stake-weighted membership selection of a collective. //! @@ -236,16 +237,25 @@ decl_storage! { // bit-wise manner. In order to get a human-readable representation (`Vec`), use // [`all_approvals_of`]. Furthermore, each vector of scalars is chunked with the cap of // `APPROVAL_SET_SIZE`. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash and `SetIndex` is not + /// attacker-controlled. pub ApprovalsOf get(fn approvals_of): map hasher(twox_64_concat) (T::AccountId, SetIndex) => Vec; /// The vote index and list slot that the candidate `who` was registered or `None` if they /// are not currently registered. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. pub RegisterInfoOf get(fn candidate_reg_info): map hasher(twox_64_concat) T::AccountId => Option<(VoteIndex, u32)>; /// Basic information about a voter. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. pub VoterInfoOf get(fn voter_info): map hasher(twox_64_concat) T::AccountId => Option>>; /// The present voter list (chunked and capped at [`VOTER_SET_SIZE`]). + /// + /// TWOX-NOTE: OKAY ― `SetIndex` is not user-controlled data. pub Voters get(fn voters): map hasher(twox_64_concat) SetIndex => Vec>; /// the next free set to store a voter in. This will keep growing. pub NextVoterSet get(fn next_nonfull_voter_set): SetIndex = 0; diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs index c779f22a3203b17660ccaf572cd55e685a38855f..9971dac5721876040d8bf0f857484e0ad64be67b 100644 --- a/frame/elections/src/mock.rs +++ b/frame/elections/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock file for election module. @@ -53,6 +54,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/elections/src/tests.rs b/frame/elections/src/tests.rs index 64b01f12e0cfe8c3b9971bee6e3772f4a2fb2adf..590266f7fe2cdce7d0608cee493fa06efced7453 100644 --- a/frame/elections/src/tests.rs +++ b/frame/elections/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for election module. diff --git a/frame/evm/Cargo.toml b/frame/evm/Cargo.toml index eaa5ae3e42baa6b514e4f2e8c50bb23032ebda26..03b213605d1368fe652ef3aa35d19e44748889c0 100644 --- a/frame/evm/Cargo.toml +++ b/frame/evm/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-evm" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME EVM contracts pallet" @@ -14,14 +14,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-timestamp = { version = "2.0.0-dev", default-features = false, path = "../timestamp" } -pallet-balances = { version = "2.0.0-dev", default-features = false, path = "../balances" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../timestamp" } +pallet-balances = { version = "2.0.0-rc2", default-features = false, path = "../balances" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } primitive-types = { version = "0.7.0", default-features = false, features = ["rlp"] } rlp = { version = "0.4", default-features = false } evm = { version = "0.16", default-features = false } diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index c7aa8b8d3a443697aad238a3e5ca061615b84740..eab3c80a93efeb81beb79811bf1a482e91edd542 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! EVM execution module for Substrate @@ -24,6 +25,10 @@ mod backend; pub use crate::backend::{Account, Log, Vicinity, Backend}; use sp_std::{vec::Vec, marker::PhantomData}; +#[cfg(feature = "std")] +use codec::{Encode, Decode}; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; use frame_support::{ensure, decl_module, decl_storage, decl_event, decl_error}; use frame_support::weights::{Weight, DispatchClass, FunctionOf, Pays}; use frame_support::traits::{Currency, WithdrawReason, ExistenceRequirement, Get}; @@ -136,12 +141,43 @@ pub trait Trait: frame_system::Trait + pallet_timestamp::Trait { } } +#[cfg(feature = "std")] +#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, Serialize, Deserialize)] +/// Account definition used for genesis block construction. +pub struct GenesisAccount { + /// Account nonce. + pub nonce: U256, + /// Account balance. + pub balance: U256, + /// Full account storage. + pub storage: std::collections::BTreeMap, + /// Account code. + pub code: Vec, +} + decl_storage! { trait Store for Module as EVM { - Accounts get(fn accounts) config(): map hasher(blake2_128_concat) H160 => Account; + Accounts get(fn accounts): map hasher(blake2_128_concat) H160 => Account; AccountCodes: map hasher(blake2_128_concat) H160 => Vec; AccountStorages: double_map hasher(blake2_128_concat) H160, hasher(blake2_128_concat) H256 => H256; } + + add_extra_genesis { + config(accounts): std::collections::BTreeMap; + build(|config: &GenesisConfig| { + for (address, account) in &config.accounts { + Accounts::insert(address, Account { + balance: account.balance, + nonce: account.nonce, + }); + AccountCodes::insert(address, &account.code); + + for (index, value) in &account.storage { + AccountStorages::insert(address, index, value); + } + } + }); + } } decl_event! { @@ -255,19 +291,14 @@ decl_module! { let sender = ensure_signed(origin)?; let source = T::ConvertAccountId::convert_account_id(&sender); - Self::execute_evm( + Self::execute_call( source, + target, + input, value, gas_limit, gas_price, nonce, - |executor| ((), executor.transact_call( - source, - target, - value, - input, - gas_limit as usize, - )), ).map_err(Into::into) } @@ -290,22 +321,13 @@ decl_module! { let sender = ensure_signed(origin)?; let source = T::ConvertAccountId::convert_account_id(&sender); - let create_address = Self::execute_evm( + let create_address = Self::execute_create( source, + init, value, gas_limit, gas_price, - nonce, - |executor| { - (executor.create_address( - evm::CreateScheme::Legacy { caller: source }, - ), executor.transact_create( - source, - value, - init, - gas_limit as usize, - )) - }, + nonce )?; Module::::deposit_event(Event::::Created(create_address)); @@ -331,24 +353,14 @@ decl_module! { let sender = ensure_signed(origin)?; let source = T::ConvertAccountId::convert_account_id(&sender); - let code_hash = H256::from_slice(Keccak256::digest(&init).as_slice()); - let create_address = Self::execute_evm( + let create_address = Self::execute_create2( source, + init, + salt, value, gas_limit, gas_price, - nonce, - |executor| { - (executor.create_address( - evm::CreateScheme::Create2 { caller: source, code_hash, salt }, - ), executor.transact_create2( - source, - value, - init, - salt, - gas_limit as usize, - )) - }, + nonce )?; Module::::deposit_event(Event::::Created(create_address)); @@ -390,6 +402,91 @@ impl Module { AccountStorages::remove_prefix(address); } + /// Execute a create transaction on behalf of given sender. + pub fn execute_create( + source: H160, + init: Vec, + value: U256, + gas_limit: u32, + gas_price: U256, + nonce: Option + ) -> Result> { + Self::execute_evm( + source, + value, + gas_limit, + gas_price, + nonce, + |executor| { + (executor.create_address( + evm::CreateScheme::Legacy { caller: source }, + ), executor.transact_create( + source, + value, + init, + gas_limit as usize, + )) + }, + ) + } + + /// Execute a create2 transaction on behalf of a given sender. + pub fn execute_create2( + source: H160, + init: Vec, + salt: H256, + value: U256, + gas_limit: u32, + gas_price: U256, + nonce: Option + ) -> Result> { + let code_hash = H256::from_slice(Keccak256::digest(&init).as_slice()); + Self::execute_evm( + source, + value, + gas_limit, + gas_price, + nonce, + |executor| { + (executor.create_address( + evm::CreateScheme::Create2 { caller: source, code_hash, salt }, + ), executor.transact_create2( + source, + value, + init, + salt, + gas_limit as usize, + )) + }, + ) + } + + /// Execute a call transaction on behalf of a given sender. + pub fn execute_call( + source: H160, + target: H160, + input: Vec, + value: U256, + gas_limit: u32, + gas_price: U256, + nonce: Option, + ) -> Result<(), Error> { + Self::execute_evm( + source, + value, + gas_limit, + gas_price, + nonce, + |executor| ((), executor.transact_call( + source, + target, + value, + input, + gas_limit as usize, + )), + ) + } + /// Execute an EVM operation. fn execute_evm( source: H160, diff --git a/frame/example-offchain-worker/Cargo.toml b/frame/example-offchain-worker/Cargo.toml index 30381adb49f171c538e18e9af8e9c64ccf110a2c..0f57832a53859b18c09915116eafa59298c581a0 100644 --- a/frame/example-offchain-worker/Cargo.toml +++ b/frame/example-offchain-worker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-example-offchain-worker" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" @@ -13,13 +13,13 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } serde = { version = "1.0.101", optional = true } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } lite-json = { version = "0.1", default-features = false } [features] diff --git a/frame/example-offchain-worker/src/lib.rs b/frame/example-offchain-worker/src/lib.rs index e2c00990943340492eb0c81d13c60254340f6018..aae51c6f27f68f0105211f2249b6da6c5d539fcf 100644 --- a/frame/example-offchain-worker/src/lib.rs +++ b/frame/example-offchain-worker/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Offchain Worker Example Module //! @@ -45,7 +46,7 @@ use frame_system::{ ensure_signed, ensure_none, offchain::{ - AppCrypto, CreateSignedTransaction, SendUnsignedTransaction, + AppCrypto, CreateSignedTransaction, SendUnsignedTransaction, SendSignedTransaction, SignedPayload, SigningTypes, Signer, SubmitTransaction, } }; @@ -381,8 +382,6 @@ impl Module { /// A helper function to fetch the price and send signed transaction. fn fetch_price_and_send_signed() -> Result<(), &'static str> { - use frame_system::offchain::SendSignedTransaction; - let signer = Signer::::all_accounts(); if !signer.can_sign() { return Err( diff --git a/frame/example-offchain-worker/src/tests.rs b/frame/example-offchain-worker/src/tests.rs index ad0ae01d10ea768bb4be9bcc5a48c6762b868110..30c9c22593035f8940b92873521c11ec8e7cb392 100644 --- a/frame/example-offchain-worker/src/tests.rs +++ b/frame/example-offchain-worker/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::*; @@ -68,6 +69,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/example/Cargo.toml b/frame/example/Cargo.toml index d12b1e7c83f88c2437fa0287ceef9af9f32c5a62..f150a6fa2fb6a6fa8b1b3d35d7851c3b8fe2c39b 100644 --- a/frame/example/Cargo.toml +++ b/frame/example/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-example" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" @@ -14,17 +14,17 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-balances = { version = "2.0.0-dev", default-features = false, path = "../balances" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-balances = { version = "2.0.0-rc2", default-features = false, path = "../balances" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 78ff803d37aaf5a52b21b6adc9f1a6c7aefb1dea..6b3d6b5e5fc9f443cf01e74cb4022e2bbd739dc3 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Example Pallet //! @@ -753,6 +754,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 3e0e1c938a89ab01d44d6beb7e4575e450fc8b14..1484e14588671f5c5ecf21c54ace94803a136ae5 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-executive" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME executives engine" @@ -13,22 +13,22 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } serde = { version = "1.0.101", optional = true } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-tracing = { version = "2.0.0-dev", default-features = false, path = "../../primitives/tracing" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-tracing = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/tracing" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } [dev-dependencies] hex-literal = "0.2.1" -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-io ={ path = "../../primitives/io", version = "2.0.0-dev"} -pallet-indices = { version = "2.0.0-dev", path = "../indices" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -pallet-transaction-payment = { version = "2.0.0-dev", path = "../transaction-payment" } -sp-version = { version = "2.0.0-dev", path = "../../primitives/version" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../primitives/io" } +pallet-indices = { version = "2.0.0-rc2", path = "../indices" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +pallet-transaction-payment = { version = "2.0.0-rc2", path = "../transaction-payment" } +sp-version = { version = "2.0.0-rc2", path = "../../primitives/version" } [features] default = ["std"] diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 742397b62476364e7a3c366fdb1339c0a31f57e4..04e095fec43646ba1f950abe31bda76d41ea1828 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Executive Module //! @@ -116,8 +117,9 @@ use sp_std::{prelude::*, marker::PhantomData}; use frame_support::{ - storage::StorageValue, weights::{GetDispatchInfo, DispatchInfo}, + storage::StorageValue, weights::{GetDispatchInfo, DispatchInfo, DispatchClass}, traits::{OnInitialize, OnFinalize, OnRuntimeUpgrade, OffchainWorker}, + dispatch::PostDispatchInfo, }; use sp_runtime::{ generic::Digest, ApplyExtrinsicResult, @@ -173,7 +175,7 @@ where CheckedOf: Applyable + GetDispatchInfo, - CallOf: Dispatchable, + CallOf: Dispatchable, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -199,7 +201,7 @@ where CheckedOf: Applyable + GetDispatchInfo, - CallOf: Dispatchable, + CallOf: Dispatchable, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -235,7 +237,7 @@ where let mut weight = as OnRuntimeUpgrade>::on_runtime_upgrade(); weight = weight.saturating_add(COnRuntimeUpgrade::on_runtime_upgrade()); weight = weight.saturating_add(::on_runtime_upgrade()); - >::register_extra_weight_unchecked(weight); + >::register_extra_weight_unchecked(weight, DispatchClass::Mandatory); } >::initialize( block_number, @@ -247,7 +249,7 @@ where as OnInitialize>::on_initialize(*block_number); let weight = >::on_initialize(*block_number) .saturating_add(>::get()); - >::register_extra_weight_unchecked(weight); + >::register_extra_weight_unchecked(weight, DispatchClass::Mandatory); frame_system::Module::::note_finished_initialize(); } @@ -367,9 +369,9 @@ where let dispatch_info = xt.get_dispatch_info(); let r = Applyable::apply::(xt, &dispatch_info, encoded_len)?; - >::note_applied_extrinsic(&r, encoded_len as u32, dispatch_info); + >::note_applied_extrinsic(&r, dispatch_info); - Ok(r) + Ok(r.map(|_| ()).map_err(|e| e.error)) } fn final_checks(header: &System::Header) { @@ -452,12 +454,12 @@ mod tests { use sp_core::H256; use sp_runtime::{ generic::Era, Perbill, DispatchError, testing::{Digest, Header, Block}, - traits::{Header as HeaderT, BlakeTwo256, IdentityLookup, Convert, ConvertInto}, + traits::{Header as HeaderT, BlakeTwo256, IdentityLookup}, transaction_validity::{InvalidTransaction, UnknownTransaction, TransactionValidityError}, }; use frame_support::{ impl_outer_event, impl_outer_origin, parameter_types, impl_outer_dispatch, - weights::{Weight, RuntimeDbWeight}, + weights::{Weight, RuntimeDbWeight, IdentityFee, WeightToFeePolynomial}, traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}, }; use frame_system::{self as system, Call as SystemCall, ChainContext, LastRuntimeUpgradeInfo}; @@ -558,6 +560,7 @@ mod tests { type DbWeight = DbWeight; type BlockExecutionWeight = BlockExecutionWeight; type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = RuntimeVersion; @@ -586,7 +589,7 @@ mod tests { type Currency = Balances; type OnTransactionPayment = (); type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } impl custom::Trait for Runtime {} @@ -672,7 +675,8 @@ mod tests { }.assimilate_storage(&mut t).unwrap(); let xt = TestXt::new(Call::Balances(BalancesCall::transfer(2, 69)), sign_extra(1, 0, 0)); let weight = xt.get_dispatch_info().weight + ::ExtrinsicBaseWeight::get(); - let fee: Balance = ::WeightToFee::convert(weight); + let fee: Balance + = ::WeightToFee::calc(&weight); let mut t = sp_io::TestExternalities::new(t); t.execute_with(|| { Executive::initialize_block(&Header::new( @@ -704,7 +708,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("409fb5a14aeb8b8c59258b503396a56dee45a0ee28a78de3e622db957425e275").into(), + state_root: hex!("05a38fa4a48ca80ffa8482304be7749a484dc8c9c31462a570d0fbadde6a3633").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Digest { logs: vec![], }, }, @@ -785,7 +789,7 @@ mod tests { Digest::default(), )); // Base block execution weight + `on_initialize` weight from the custom module. - assert_eq!(>::all_extrinsics_weight(), base_block_weight); + assert_eq!(>::block_weight().total(), base_block_weight); for nonce in 0..=num_to_exhaust_block { let xt = TestXt::new( @@ -795,7 +799,7 @@ mod tests { if nonce != num_to_exhaust_block { assert!(res.is_ok()); assert_eq!( - >::all_extrinsics_weight(), + >::block_weight().total(), //--------------------- on_initialize + block_execution + extrinsic_base weight (encoded_len + 5) * (nonce + 1) + base_block_weight, ); @@ -815,7 +819,18 @@ mod tests { let len = xt.clone().encode().len() as u32; let mut t = new_test_ext(1); t.execute_with(|| { - assert_eq!(>::all_extrinsics_weight(), 0); + // Block execution weight + on_initialize weight from custom module + let base_block_weight = 175 + ::BlockExecutionWeight::get(); + + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(>::block_weight().total(), base_block_weight); assert_eq!(>::all_extrinsics_len(), 0); assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); @@ -823,16 +838,28 @@ mod tests { assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); // default weight for `TestXt` == encoded length. + let extrinsic_weight = len as Weight + ::ExtrinsicBaseWeight::get(); assert_eq!( - >::all_extrinsics_weight(), - 3 * (len as Weight + ::ExtrinsicBaseWeight::get()), + >::block_weight().total(), + base_block_weight + 3 * extrinsic_weight, ); assert_eq!(>::all_extrinsics_len(), 3 * len); let _ = >::finalize(); - - assert_eq!(>::all_extrinsics_weight(), 0); + // All extrinsics length cleaned on `System::finalize` assert_eq!(>::all_extrinsics_len(), 0); + + // New Block + Executive::initialize_block(&Header::new( + 2, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + // Block weight cleaned up on `System::initialize` + assert_eq!(>::block_weight().total(), base_block_weight); }); } @@ -868,7 +895,8 @@ mod tests { ); let weight = xt.get_dispatch_info().weight + ::ExtrinsicBaseWeight::get(); - let fee: Balance = ::WeightToFee::convert(weight); + let fee: Balance = + ::WeightToFee::calc(&weight); Executive::initialize_block(&Header::new( 1, H256::default(), @@ -903,7 +931,7 @@ mod tests { // NOTE: might need updates over time if new weights are introduced. // For now it only accounts for the base block execution weight and // the `on_initialize` weight defined in the custom test module. - assert_eq!(>::all_extrinsics_weight(), 175 + 10); + assert_eq!(>::block_weight().total(), 175 + 10); }) } diff --git a/frame/finality-tracker/Cargo.toml b/frame/finality-tracker/Cargo.toml index 1b11fbea5ad585a1a34bfa08c22b31d9c8729869..248bf64432cd7e49ad7c05221d880006147d85db 100644 --- a/frame/finality-tracker/Cargo.toml +++ b/frame/finality-tracker/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-finality-tracker" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME Pallet that tracks the last finalized block, as perceived by block authors." @@ -16,17 +16,17 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-finality-tracker = { version = "2.0.0-dev", default-features = false, path = "../../primitives/finality-tracker" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-finality-tracker = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/finality-tracker" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } impl-trait-for-tuples = "0.1.3" [dev-dependencies] -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/finality-tracker/src/lib.rs b/frame/finality-tracker/src/lib.rs index ac306e268998ff925248ff21bc4c72960330ba0a..a9cf9c2b70f6d28ac3b998d980af37e22cd1dec9 100644 --- a/frame/finality-tracker/src/lib.rs +++ b/frame/finality-tracker/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! FRAME Pallet that tracks the last finalized block, as perceived by block authors. @@ -266,6 +267,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/generic-asset/Cargo.toml b/frame/generic-asset/Cargo.toml index c19a7884b3eadb802d25f73fbb4f46ccf90e601c..11576aaeae1589b76e6f8eab0f13fa289fdf3981 100644 --- a/frame/generic-asset/Cargo.toml +++ b/frame/generic-asset/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-generic-asset" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Centrality Developers "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for generic asset management" @@ -14,14 +14,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-io ={ version = "2.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/generic-asset/src/lib.rs b/frame/generic-asset/src/lib.rs index f2507669e537866bc58a54eb1451c4d4ddbc185c..f94c83b5ed59fd728c5124b5989bc3e532dc86ea 100644 --- a/frame/generic-asset/src/lib.rs +++ b/frame/generic-asset/src/lib.rs @@ -442,16 +442,22 @@ pub struct BalanceLock { decl_storage! { trait Store for Module as GenericAsset { /// Total issuance of a given asset. + /// + /// TWOX-NOTE: `AssetId` is trusted. pub TotalIssuance get(fn total_issuance) build(|config: &GenesisConfig| { let issuance = config.initial_balance * (config.endowed_accounts.len() as u32).into(); config.assets.iter().map(|id| (id.clone(), issuance)).collect::>() }): map hasher(twox_64_concat) T::AssetId => T::Balance; /// The free balance of a given asset under an account. + /// + /// TWOX-NOTE: `AssetId` is trusted. pub FreeBalance: double_map hasher(twox_64_concat) T::AssetId, hasher(blake2_128_concat) T::AccountId => T::Balance; /// The reserved balance of a given asset under an account. + /// + /// TWOX-NOTE: `AssetId` is trusted. pub ReservedBalance: double_map hasher(twox_64_concat) T::AssetId, hasher(blake2_128_concat) T::AccountId => T::Balance; @@ -459,6 +465,8 @@ decl_storage! { pub NextAssetId get(fn next_asset_id) config(): T::AssetId; /// Permission options for a given asset. + /// + /// TWOX-NOTE: `AssetId` is trusted. pub Permissions get(fn get_permission): map hasher(twox_64_concat) T::AssetId => PermissionVersions; @@ -1127,6 +1135,7 @@ impl frame_system::Trait for ElevatedTrait { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = T::MaximumBlockWeight; type MaximumBlockLength = T::MaximumBlockLength; type AvailableBlockRatio = T::AvailableBlockRatio; type Version = T::Version; diff --git a/frame/generic-asset/src/mock.rs b/frame/generic-asset/src/mock.rs index 3e3bd892d56880f2a3d512e1120cf71590f513c0..04fd565091b29279f6c7cd4f81fd631731d4d971 100644 --- a/frame/generic-asset/src/mock.rs +++ b/frame/generic-asset/src/mock.rs @@ -60,6 +60,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type BlockHashCount = BlockHashCount; diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index 649b4053d0536cfd730d5a05fbad9d636430bd1a..78a86f23ffba0a7d1cfc89c505478a4fe0793a38 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-grandpa" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for GRANDPA finality gadget" @@ -14,27 +14,27 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-finality-grandpa = { version = "2.0.0-dev", default-features = false, path = "../../primitives/finality-grandpa" } -sp-session = { version = "2.0.0-dev", default-features = false, path = "../../primitives/session" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-session = { version = "2.0.0-dev", default-features = false, path = "../session" } -pallet-finality-tracker = { version = "2.0.0-dev", default-features = false, path = "../finality-tracker" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/application-crypto" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-finality-grandpa = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/finality-grandpa" } +sp-session = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/session" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0-rc2", default-features = false, path = "../session" } +pallet-finality-tracker = { version = "2.0.0-rc2", default-features = false, path = "../finality-tracker" } [dev-dependencies] -grandpa = { package = "finality-grandpa", version = "0.12.2", features = ["derive-codec"] } -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } -sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -pallet-offences = { version = "2.0.0-dev", path = "../offences" } -pallet-staking = { version = "2.0.0-dev", path = "../staking" } -pallet-staking-reward-curve = { version = "2.0.0-dev", path = "../staking/reward-curve" } -pallet-timestamp = { version = "2.0.0-dev", path = "../timestamp" } +grandpa = { package = "finality-grandpa", version = "0.12.3", features = ["derive-codec"] } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +sp-keyring = { version = "2.0.0-rc2", path = "../../primitives/keyring" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +pallet-offences = { version = "2.0.0-rc2", path = "../offences" } +pallet-staking = { version = "2.0.0-rc2", path = "../staking" } +pallet-staking-reward-curve = { version = "2.0.0-rc2", path = "../staking/reward-curve" } +pallet-timestamp = { version = "2.0.0-rc2", path = "../timestamp" } [features] default = ["std"] diff --git a/frame/grandpa/src/equivocation.rs b/frame/grandpa/src/equivocation.rs index f9ae43021673b961c194d72aacf582f91f3222fe..7c6e5c6d66fde9b0395442b0b848565c6c6a8681 100644 --- a/frame/grandpa/src/equivocation.rs +++ b/frame/grandpa/src/equivocation.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! //! An opt-in utility module for reporting equivocations. @@ -29,6 +30,12 @@ //! And in a runtime context, so that the GRANDPA module can validate the //! equivocation proofs in the extrinsic and report the offences. //! +//! IMPORTANT: +//! When using this module for enabling equivocation reporting it is required +//! that the `ValidateEquivocationReport` signed extension is used in the runtime +//! definition. Failure to do so will allow invalid equivocation reports to be +//! accepted by the runtime. +//! use sp_std::prelude::*; @@ -395,12 +402,12 @@ impl GetValidatorCount for frame_support::Void { impl GetSessionNumber for sp_session::MembershipProof { fn session(&self) -> SessionIndex { - self.session() + self.session } } impl GetValidatorCount for sp_session::MembershipProof { fn validator_count(&self) -> sp_session::ValidatorCount { - self.validator_count() + self.validator_count } } diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 16aebe335f9aeb5dd591254b8f58e587490886a6..3432c1102008ba06a8474cff48eaa687c1db0df0 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! GRANDPA Consensus module for runtime. //! @@ -184,6 +185,10 @@ decl_error! { ChangePending, /// Cannot signal forced change so soon after last. TooSoon, + /// A key ownership proof provided as part of an equivocation report is invalid. + InvalidKeyOwnershipProof, + /// A given equivocation report is valid but already previously reported. + DuplicateOffenceReport, } } @@ -207,6 +212,8 @@ decl_storage! { /// A mapping from grandpa set ID to the index of the *most recent* session for which its /// members were responsible. + /// + /// TWOX-NOTE: `SetId` is not under user control. SetIdSession get(fn session_for_set): map hasher(twox_64_concat) SetId => Option; } add_extra_genesis { @@ -228,8 +235,9 @@ decl_module! { /// against the extracted offender. If both are valid, the offence /// will be reported. /// - /// Since the weight is 0 in order to avoid DoS pre-validation is implemented in a - /// `SignedExtension`. + /// Since the weight of the extrinsic is 0, in order to avoid DoS by + /// submission of invalid equivocation reports, a mandatory pre-validation of + /// the extrinsic is implemented in a `SignedExtension`. #[weight = 0] fn report_equivocation( origin, @@ -249,7 +257,7 @@ decl_module! { T::KeyOwnerProofSystem::check_proof( (fg_primitives::KEY_TYPE, equivocation_proof.offender().clone()), key_owner_proof, - ).ok_or("Invalid key ownership proof.")?; + ).ok_or(Error::::InvalidKeyOwnershipProof)?; // the set id and round when the offence happened let set_id = equivocation_proof.set_id(); @@ -265,7 +273,7 @@ decl_module! { set_id, round, ), - ).map_err(|_| "Duplicate offence report.")?; + ).map_err(|_| Error::::DuplicateOffenceReport)?; } fn on_finalize(block_number: T::BlockNumber) { @@ -440,9 +448,9 @@ impl Module { Self::set_grandpa_authorities(authorities); } - // NOTE: initialize first session of first set. this is necessary - // because we only update this `on_new_session` which isn't called - // for the genesis session. + // NOTE: initialize first session of first set. this is necessary for + // the genesis set and session since we only update the set -> session + // mapping whenever a new session starts, i.e. through `on_new_session`. SetIdSession::insert(0, 0); } @@ -454,10 +462,7 @@ impl Module { equivocation_proof: EquivocationProof, key_owner_proof: T::KeyOwnerProof, ) -> Option<()> { - T::HandleEquivocation::submit_equivocation_report(equivocation_proof, key_owner_proof) - .ok()?; - - Some(()) + T::HandleEquivocation::submit_equivocation_report(equivocation_proof, key_owner_proof).ok() } } diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index f307f17fd4d53379cdb7d1a9e07953e2315af0a6..08329fbb70b5964a24c3fff5c75aaa18feae21f1 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -108,6 +109,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -229,10 +231,15 @@ impl staking::Trait for Test { type MaxIterations = (); } +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); +} + impl offences::Trait for Test { type Event = TestEvent; type IdentificationTuple = session::historical::IdentificationTuple; type OnOffenceHandler = Staking; + type WeightSoftLimit = OffencesWeightSoftLimit; } impl Trait for Test { diff --git a/frame/grandpa/src/tests.rs b/frame/grandpa/src/tests.rs index 898c67583565f14874b18574f870bef37b1f5c34..e15021733ffa054a39ade8c5292c9dda0ec1c099 100644 --- a/frame/grandpa/src/tests.rs +++ b/frame/grandpa/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index f20a8c983df24f126bd64da20590e46dc6f56517..d38b6c80f1a5e8de3d206258562c69056297b403 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-identity" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME identity management pallet" @@ -15,16 +15,16 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } [features] default = ["std"] diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 81a9f3e1340cf82458adfd5f71562ecc76afbdef..042f7aa9c79b5453261376965c6cc4508daa9fcb 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Identity pallet benchmarking. diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 194a190ce62f087f4bc22d0fe897146140b1119d..2b58437685556c75ecaab8879d5514adb6b46f21 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Identity Module //! @@ -388,6 +389,8 @@ pub struct RegistrarInfo< decl_storage! { trait Store for Module as Identity { /// Information that is pertinent to identify the entity behind an account. + /// + /// TWOX-NOTE: OK ― `AccountId` is a secure hash. pub IdentityOf get(fn identity): map hasher(twox_64_concat) T::AccountId => Option>>; @@ -399,6 +402,8 @@ decl_storage! { /// Alternative "sub" identities of this account. /// /// The first item is the deposit, the second is a vector of the accounts. + /// + /// TWOX-NOTE: OK ― `AccountId` is a secure hash. pub SubsOf get(fn subs_of): map hasher(twox_64_concat) T::AccountId => (BalanceOf, Vec); @@ -463,97 +468,126 @@ decl_error! { /// Functions for calcuating the weight of dispatchables. mod weight_for { - use frame_support::weights::{RuntimeDbWeight, Weight}; + use frame_support::{traits::Get, weights::Weight}; + use super::Trait; + + /// Weight calculation for `add_registrar`. + /// + /// Based on benchmark: + /// 22.24 + R * 0.371 µs (min squares analysis) + pub(crate) fn add_registrar( + registrars: Weight + ) -> Weight { + T::DbWeight::get().reads_writes(1, 1) + + 23_000_000 // constant + + 380_000 * registrars // R + } /// Weight calculation for `set_identity`. - pub(crate) fn set_identity( - db: RuntimeDbWeight, - judgements: impl Into, - extra_fields: impl Into + /// + /// Based on benchmark: + /// 50.64 + R * 0.215 + X * 1.424 µs (min squares analysis) + pub(crate) fn set_identity( + judgements: Weight, + extra_fields: Weight ) -> Weight { - db.reads_writes(1, 1) - + 61_000_000 // constant - + 400_000 * judgements.into() // R - + 1_500_000 * extra_fields.into() // X + T::DbWeight::get().reads_writes(1, 1) + + 51_000_000 // constant + + 220_000 * judgements // R + + 1_500_000 * extra_fields // X } /// Weight calculation for `set_subs`. - pub(crate) fn set_subs( - db: RuntimeDbWeight, - old_subs: impl Into + Copy, - subs: impl Into + Copy + /// + /// Based on benchmark: + /// 36.21 + P * 2.481 + S * 3.633 µs (min squares analysis) + pub(crate) fn set_subs( + old_subs: Weight, + subs: Weight ) -> Weight { + let db = T::DbWeight::get(); db.reads(1) // storage-exists (`IdentityOf::contains_key`) - + db.reads_writes(1, old_subs.into()) // `SubsOf::get` read + P old DB deletions - + db.writes(subs.into() + 1) // S + 1 new DB writes - + 41_000_000 // constant - + 2_600_000 * old_subs.into() // P - + 3_700_000 * subs.into() // S + .saturating_add(db.reads_writes(1, old_subs)) // `SubsOf::get` read + P old DB deletions + .saturating_add(db.writes(subs + 1)) // S + 1 new DB writes + .saturating_add(37_000_000) // constant + .saturating_add(2_500_000 * old_subs) // P + .saturating_add(subs.saturating_mul(3_700_000)) // S } /// Weight calculation for `clear_identity`. - pub(crate) fn clear_identity( - db: RuntimeDbWeight, - judgements: impl Into, - subs: impl Into + Copy, - extra_fields: impl Into + /// + /// Based on benchmark: + /// 43.19 + R * 0.099 + S * 2.547 + X * 0.875 µs (min squares analysis) + pub(crate) fn clear_identity( + judgements: Weight, + subs: Weight, + extra_fields: Weight ) -> Weight { - db.reads_writes(2, subs.into() + 2) // S + 2 deletions - + 58_000_000 // constant - + 20_000 * judgements.into() // R - + 2_600_000 * subs.into() // S - + 900_000 * extra_fields.into() // X + T::DbWeight::get().reads_writes(2, subs + 2) // S + 2 deletions + + 44_000_000 // constant + + 100_000 * judgements // R + + 2_600_000 * subs // S + + 900_000 * extra_fields // X } /// Weight calculation for `request_judgement`. - pub(crate) fn request_judgement( - db: RuntimeDbWeight, - judgements: impl Into, - extra_fields: impl Into + /// + /// Based on benchmark: + /// 51.51 + R * 0.32 + X * 1.85 µs (min squares analysis) + pub(crate) fn request_judgement( + judgements: Weight, + extra_fields: Weight ) -> Weight { - db.reads_writes(2, 1) - + 60_000_000 // constant - + 510_000 * judgements.into() // R - + 1_700_000 * extra_fields.into() // X + T::DbWeight::get().reads_writes(2, 1) + + 52_000_000 // constant + + 400_000 * judgements // R + + 1_900_000 * extra_fields // X } /// Weight calculation for `cancel_request`. - pub(crate) fn cancel_request( - db: RuntimeDbWeight, - judgements: impl Into, - extra_fields: impl Into + /// + /// Based on benchmark: + /// 40.95 + R * 0.219 + X * 1.655 µs (min squares analysis) + pub(crate) fn cancel_request( + judgements: Weight, + extra_fields: Weight ) -> Weight { - db.reads_writes(1, 1) - + 52_000_000 // constant - + 400_000 * judgements.into() // R - + 1_700_000 * extra_fields.into() // X + T::DbWeight::get().reads_writes(1, 1) + + 41_000_000 // constant + + 300_000 * judgements // R + + 1_700_000 * extra_fields // X } /// Weight calculation for `provide_judgement`. - pub(crate) fn provide_judgement( - db: RuntimeDbWeight, - judgements: impl Into, - extra_fields: impl Into + /// + /// Based on benchmark: + /// 40.77 + R * 0.282 + X * 1.66 µs (min squares analysis) + pub(crate) fn provide_judgement( + judgements: Weight, + extra_fields: Weight ) -> Weight { - db.reads_writes(2, 1) - + 49_000_000 // constant - + 400_000 * judgements.into() // R - + 1_700_000 * extra_fields.into()// X + T::DbWeight::get().reads_writes(2, 1) + + 41_000_000 // constant + + 300_000 * judgements // R + + 1_700_000 * extra_fields// X } /// Weight calculation for `kill_identity`. - pub(crate) fn kill_identity( - db: RuntimeDbWeight, - judgements: impl Into, - subs: impl Into + Copy, - extra_fields: impl Into + /// + /// Based on benchmark: + /// 83.96 + R * 0.122 + S * 2.533 + X * 0.867 µs (min squares analysis) + pub(crate) fn kill_identity( + judgements: Weight, + subs: Weight, + extra_fields: Weight ) -> Weight { - db.reads_writes(2, subs.into() + 2) // 2 `take`s + S deletions + let db = T::DbWeight::get(); + db.reads_writes(2, subs + 2) // 2 `take`s + S deletions + db.reads_writes(1, 1) // balance ops - + 110_000_000 // constant - + 100_000 * judgements.into() // R - + 2_600_000 * subs.into() // S - + 900_000 * extra_fields.into() // X + + 84_000_000 // constant + + 130_000 * judgements // R + + 2_600_000 * subs // S + + 900_000 * extra_fields // X } } @@ -598,27 +632,26 @@ decl_module! { /// - `O(R)` where `R` registrar-count (governance-bounded and code-bounded). /// - One storage mutation (codec `O(R)`). /// - One event. - /// - Benchmark: 24.63 + R * 0.53 µs (min squares analysis) /// # - #[weight = T::DbWeight::get().reads_writes(1, 1) - + 25_000_000 // constant - + 550_000 * T::MaxRegistrars::get() as Weight // R - ] + #[weight = weight_for::add_registrar::(T::MaxRegistrars::get().into()) ] fn add_registrar(origin, account: T::AccountId) -> DispatchResultWithPostInfo { T::RegistrarOrigin::try_origin(origin) .map(|_| ()) .or_else(ensure_root)?; - let (i, registrar_count) = >::try_mutate(|registrars| -> Result<(RegistrarIndex, usize), DispatchError> { - ensure!((registrars.len() as u32) < T::MaxRegistrars::get(), Error::::TooManyRegistrars); - registrars.push(Some(RegistrarInfo { account, fee: Zero::zero(), fields: Default::default() })); - Ok(((registrars.len() - 1) as RegistrarIndex, registrars.len())) - })?; + let (i, registrar_count) = >::try_mutate( + |registrars| -> Result<(RegistrarIndex, usize), DispatchError> { + ensure!(registrars.len() < T::MaxRegistrars::get() as usize, Error::::TooManyRegistrars); + registrars.push(Some(RegistrarInfo { + account, fee: Zero::zero(), fields: Default::default() + })); + Ok(((registrars.len() - 1) as RegistrarIndex, registrars.len())) + } + )?; Self::deposit_event(RawEvent::RegistrarAdded(i)); - Ok(Some(T::DbWeight::get().reads_writes(1, 1) - + 25_000_000 + 550_000 * registrar_count as Weight).into()) + Ok(Some(weight_for::add_registrar::(registrar_count as Weight)).into()) } /// Set an account's identity information and reserve the appropriate deposit. @@ -639,12 +672,10 @@ decl_module! { /// - One balance reserve operation. /// - One storage mutation (codec-read `O(X' + R)`, codec-write `O(X + R)`). /// - One event. - /// - Benchmark: 59.44 + R * 0.389 + X * 1.434 µs (min squares analysis) /// # - #[weight = weight_for::set_identity( - T::DbWeight::get(), - T::MaxRegistrars::get(), // R - T::MaxAdditionalFields::get() // X + #[weight = weight_for::set_identity::( + T::MaxRegistrars::get().into(), // R + T::MaxAdditionalFields::get().into(), // X )] fn set_identity(origin, info: IdentityInfo) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; @@ -675,8 +706,7 @@ decl_module! { >::insert(&sender, id); Self::deposit_event(RawEvent::IdentitySet(sender)); - Ok(Some(weight_for::set_identity( - T::DbWeight::get(), + Ok(Some(weight_for::set_identity::( judgements, // R extra_fields as Weight // X )).into()) @@ -702,11 +732,9 @@ decl_module! { /// - One storage read (codec complexity `O(P)`). /// - One storage write (codec complexity `O(S)`). /// - One storage-exists (`IdentityOf::contains_key`). - /// - Benchmark: 39.43 + P * 2.522 + S * 3.698 µs (min squares analysis) /// # - #[weight = weight_for::set_subs( - T::DbWeight::get(), - T::MaxSubAccounts::get(), // P + #[weight = weight_for::set_subs::( + T::MaxSubAccounts::get().into(), // P subs.len() as Weight // S )] fn set_subs(origin, subs: Vec<(T::AccountId, Data)>) -> DispatchResultWithPostInfo { @@ -740,8 +768,7 @@ decl_module! { >::insert(&sender, (new_deposit, ids)); } - Ok(Some(weight_for::set_subs( - T::DbWeight::get(), + Ok(Some(weight_for::set_subs::( old_ids.len() as Weight, // P new_subs // S )).into()) @@ -764,15 +791,11 @@ decl_module! { /// - One balance-unreserve operation. /// - `2` storage reads and `S + 2` storage deletions. /// - One event. - /// - Benchmarks: - /// - 57.36 + R * 0.019 + S * 2.577 + X * 0.874 µs (median slopes analysis) - /// - 57.06 + R * 0.006 + S * 2.579 + X * 0.878 µs (min squares analysis) /// # - #[weight = weight_for::clear_identity( - T::DbWeight::get(), - T::MaxRegistrars::get(), // R - T::MaxSubAccounts::get(), // S - T::MaxAdditionalFields::get() // X + #[weight = weight_for::clear_identity::( + T::MaxRegistrars::get().into(), // R + T::MaxSubAccounts::get().into(), // S + T::MaxAdditionalFields::get().into(), // X )] fn clear_identity(origin) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; @@ -789,8 +812,7 @@ decl_module! { Self::deposit_event(RawEvent::IdentityCleared(sender, deposit)); - Ok(Some(weight_for::clear_identity( - T::DbWeight::get(), + Ok(Some(weight_for::clear_identity::( id.judgements.len() as Weight, // R sub_ids.len() as Weight, // S id.info.additional.len() as Weight // X @@ -819,12 +841,10 @@ decl_module! { /// - One balance-reserve operation. /// - Storage: 1 read `O(R)`, 1 mutate `O(X + R)`. /// - One event. - /// - Benchmark: 59.02 + R * 0.488 + X * 1.7 µs (min squares analysis) /// # - #[weight = weight_for::request_judgement( - T::DbWeight::get(), - T::MaxRegistrars::get(), // R - T::MaxAdditionalFields::get() // X + #[weight = weight_for::request_judgement::( + T::MaxRegistrars::get().into(), // R + T::MaxAdditionalFields::get().into(), // X )] fn request_judgement(origin, #[compact] reg_index: RegistrarIndex, @@ -855,7 +875,7 @@ decl_module! { Self::deposit_event(RawEvent::JudgementRequested(sender, reg_index)); - Ok(Some(weight_for::request_judgement(T::DbWeight::get(), judgements, extra_fields)).into()) + Ok(Some(weight_for::request_judgement::(judgements, extra_fields)).into()) } /// Cancel a previous request. @@ -873,13 +893,11 @@ decl_module! { /// - `O(R + X)`. /// - One balance-reserve operation. /// - One storage mutation `O(R + X)`. - /// - One event. - /// - Benchmark: 50.05 + R * 0.321 + X * 1.688 µs (min squares analysis) + /// - One event /// # - #[weight = weight_for::cancel_request( - T::DbWeight::get(), - T::MaxRegistrars::get(), // R - T::MaxAdditionalFields::get() // X + #[weight = weight_for::cancel_request::( + T::MaxRegistrars::get().into(), // R + T::MaxAdditionalFields::get().into(), // X )] fn cancel_request(origin, reg_index: RegistrarIndex) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; @@ -900,7 +918,7 @@ decl_module! { Self::deposit_event(RawEvent::JudgementUnrequested(sender, reg_index)); - Ok(Some(weight_for::request_judgement(T::DbWeight::get(), judgements, extra_fields)).into()) + Ok(Some(weight_for::request_judgement::(judgements, extra_fields)).into()) } /// Set the fee required for a judgement to be requested from a registrar. @@ -914,11 +932,11 @@ decl_module! { /// # /// - `O(R)`. /// - One storage mutation `O(R)`. - /// - Benchmark: 8.848 + R * 0.425 µs (min squares analysis) + /// - Benchmark: 7.315 + R * 0.329 µs (min squares analysis) /// # #[weight = T::DbWeight::get().reads_writes(1, 1) - + 9_000_000 // constant - + 430_000 * T::MaxRegistrars::get() as Weight // R + + 7_400_000 // constant + + 330_000 * T::MaxRegistrars::get() as Weight // R ] fn set_fee(origin, #[compact] index: RegistrarIndex, @@ -934,7 +952,7 @@ decl_module! { Ok(rs.len()) })?; Ok(Some(T::DbWeight::get().reads_writes(1, 1) - + 9_000_000 + 430_000 * registrars as Weight // R + + 7_400_000 + 330_000 * registrars as Weight // R ).into()) } @@ -949,11 +967,11 @@ decl_module! { /// # /// - `O(R)`. /// - One storage mutation `O(R)`. - /// - Benchmark: 10.05 + R * 0.438 µs (min squares analysis) + /// - Benchmark: 8.823 + R * 0.32 µs (min squares analysis) /// # #[weight = T::DbWeight::get().reads_writes(1, 1) - + 10_100_000 // constant - + 440_000 * T::MaxRegistrars::get() as Weight // R + + 8_900_000 // constant + + 320_000 * T::MaxRegistrars::get() as Weight // R ] fn set_account_id(origin, #[compact] index: RegistrarIndex, @@ -969,7 +987,7 @@ decl_module! { Ok(rs.len()) })?; Ok(Some(T::DbWeight::get().reads_writes(1, 1) - + 10_100_000 + 440_000 * registrars as Weight // R + + 8_900_000 + 320_000 * registrars as Weight // R ).into()) } @@ -984,11 +1002,11 @@ decl_module! { /// # /// - `O(R)`. /// - One storage mutation `O(R)`. - /// - Benchmark: 8.985 + R * 0.413 µs (min squares analysis) + /// - Benchmark: 7.464 + R * 0.325 µs (min squares analysis) /// # #[weight = T::DbWeight::get().reads_writes(1, 1) - + 9_000_000 // constant - + 420_000 * T::MaxRegistrars::get() as Weight // R + + 7_500_000 // constant + + 330_000 * T::MaxRegistrars::get() as Weight // R ] fn set_fields(origin, #[compact] index: RegistrarIndex, @@ -1004,7 +1022,7 @@ decl_module! { Ok(rs.len()) })?; Ok(Some(T::DbWeight::get().reads_writes(1, 1) - + 9_000_000 + 420_000 * registrars as Weight // R + + 7_500_000 + 330_000 * registrars as Weight // R ).into()) } @@ -1026,12 +1044,10 @@ decl_module! { /// - Up to one account-lookup operation. /// - Storage: 1 read `O(R)`, 1 mutate `O(R + X)`. /// - One event. - /// - Benchmark: 47.77 + R * 0.336 + X * 1.664 µs (min squares analysis) /// # - #[weight = weight_for::provide_judgement( - T::DbWeight::get(), - T::MaxRegistrars::get(), // R - T::MaxAdditionalFields::get() // X + #[weight = weight_for::provide_judgement::( + T::MaxRegistrars::get().into(), // R + T::MaxAdditionalFields::get().into(), // X )] fn provide_judgement(origin, #[compact] reg_index: RegistrarIndex, @@ -1064,7 +1080,7 @@ decl_module! { >::insert(&target, id); Self::deposit_event(RawEvent::JudgementGiven(target, reg_index)); - Ok(Some(weight_for::provide_judgement(T::DbWeight::get(), judgements, extra_fields)).into()) + Ok(Some(weight_for::provide_judgement::(judgements, extra_fields)).into()) } /// Remove an account's identity and sub-account information and slash the deposits. @@ -1085,13 +1101,11 @@ decl_module! { /// - One balance-reserve operation. /// - `S + 2` storage mutations. /// - One event. - /// - Benchmark: 101.9 + R * 0.091 + S * 2.589 + X * 0.871 µs (min squares analysis) /// # - #[weight = weight_for::kill_identity( - T::DbWeight::get(), - T::MaxRegistrars::get(), // R - T::MaxSubAccounts::get(), // S - T::MaxAdditionalFields::get() // X + #[weight = weight_for::kill_identity::( + T::MaxRegistrars::get().into(), // R + T::MaxSubAccounts::get().into(), // S + T::MaxAdditionalFields::get().into(), // X )] fn kill_identity(origin, target: ::Source) -> DispatchResultWithPostInfo { T::ForceOrigin::try_origin(origin) @@ -1112,8 +1126,7 @@ decl_module! { Self::deposit_event(RawEvent::IdentityKilled(target, deposit)); - Ok(Some(weight_for::kill_identity( - T::DbWeight::get(), + Ok(Some(weight_for::kill_identity::( id.judgements.len() as Weight, // R sub_ids.len() as Weight, // S id.info.additional.len() as Weight // X @@ -1180,6 +1193,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml index 55e5a49d586e5ff1554eec5dbacae7d6668f18f5..34b942c889f351d3a8ec73a524f7868f32d3b3c7 100644 --- a/frame/im-online/Cargo.toml +++ b/frame/im-online/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-im-online" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME's I'm online pallet" @@ -12,20 +12,20 @@ description = "FRAME's I'm online pallet" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } -pallet-authorship = { version = "2.0.0-dev", default-features = false, path = "../authorship" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/application-crypto" } +pallet-authorship = { version = "2.0.0-rc2", default-features = false, path = "../authorship" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.101", optional = true } -pallet-session = { version = "2.0.0-dev", default-features = false, path = "../session" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0-rc2", default-features = false, path = "../session" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } [features] default = ["std", "pallet-session/historical"] diff --git a/frame/im-online/src/benchmarking.rs b/frame/im-online/src/benchmarking.rs index dae2f719b614cc2317d65f7f231fb53c6663d170..63457168b3638fda25b0dc1a1d6b2145f99c1c22 100644 --- a/frame/im-online/src/benchmarking.rs +++ b/frame/im-online/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! I'm Online pallet benchmarking. diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index e280a890545c8d115726585abfa311608a392da0..c1c93910ece22181360db201a57e54e785a78beb 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # I'm online Module //! @@ -264,7 +265,7 @@ decl_event!( HeartbeatReceived(AuthorityId), /// At the end of the session, no offence was committed. AllGood, - /// At the end of the session, at least once validator was found to be offline. + /// At the end of the session, at least one validator was found to be offline. SomeOffline(Vec), } ); diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 7ba9dd19f91d325e9f25266f703504a4d12640be..01e84102b1a5c3bddfa3fd956502d355e5349c20 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -118,6 +119,7 @@ impl frame_system::Trait for Runtime { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/im-online/src/tests.rs b/frame/im-online/src/tests.rs index 2578b5114e21a866cddfa4f7eea04b29c4124602..7619781b68df0a46303434a0c8bf596853b5ad14 100644 --- a/frame/im-online/src/tests.rs +++ b/frame/im-online/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the im-online module. diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml index 515c0b478ddb426ca754c383a686a0e9a77a715a..d4217ca49c31e0042c4357b32fb78b2fb11176a8 100644 --- a/frame/indices/Cargo.toml +++ b/frame/indices/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-indices" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME indices management pallet" @@ -14,16 +14,16 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-keyring = { version = "2.0.0-dev", optional = true, path = "../../primitives/keyring" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-keyring = { version = "2.0.0-rc2", optional = true, path = "../../primitives/keyring" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -pallet-balances = { version = "2.0.0-dev", path = "../balances" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } [features] default = ["std"] diff --git a/frame/indices/src/address.rs b/frame/indices/src/address.rs index f4487eeb693dec14bfcc3bae7229c3ce41177329..0fd89333813289d448f85e50cdf1002b8386e2db 100644 --- a/frame/indices/src/address.rs +++ b/frame/indices/src/address.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Address type that is union of index and id for an account. diff --git a/frame/indices/src/lib.rs b/frame/indices/src/lib.rs index 8c17fed5921301c0f2ac5ad1bba6d30bde0e89fb..77a73a21aca481ba60618259a7d62e9e09984a68 100644 --- a/frame/indices/src/lib.rs +++ b/frame/indices/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! An index is a short form of an address. This module handles allocation //! of indices for a newly created accounts. diff --git a/frame/indices/src/mock.rs b/frame/indices/src/mock.rs index aa7057e61a1dce71904cc89c46410a7069059574..90ac1ae81b595264e9c9025f8e4451ee8f04c587 100644 --- a/frame/indices/src/mock.rs +++ b/frame/indices/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -64,6 +65,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/indices/src/tests.rs b/frame/indices/src/tests.rs index 9e434cfbe2a1c299ff2f16988c3b350af494d2fc..7f416afbd3392b87bcf93ec09025d09a6508ae1b 100644 --- a/frame/indices/src/tests.rs +++ b/frame/indices/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml index 742cc124a295a9cb2a8d664aa88eb3883f5834f6..21f55b900bc29754c28ed7665290ea5960500a53 100644 --- a/frame/membership/Cargo.toml +++ b/frame/membership/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-membership" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME membership management pallet" @@ -14,14 +14,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index faf2be8e11e5eb77f77bd2406f4cc6aec7379407..669964c70c1777ac6f5a6f7e6d0e88349d38e27e 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Membership Module //! @@ -118,7 +119,7 @@ decl_module! { /// /// May only be called from `AddOrigin` or root. #[weight = 50_000_000] - fn add_member(origin, who: T::AccountId) { + pub fn add_member(origin, who: T::AccountId) { T::AddOrigin::try_origin(origin) .map(|_| ()) .or_else(ensure_root)?; @@ -137,7 +138,7 @@ decl_module! { /// /// May only be called from `RemoveOrigin` or root. #[weight = 50_000_000] - fn remove_member(origin, who: T::AccountId) { + pub fn remove_member(origin, who: T::AccountId) { T::RemoveOrigin::try_origin(origin) .map(|_| ()) .or_else(ensure_root)?; @@ -159,7 +160,7 @@ decl_module! { /// /// Prime membership is *not* passed from `remove` to `add`, if extant. #[weight = 50_000_000] - fn swap_member(origin, remove: T::AccountId, add: T::AccountId) { + pub fn swap_member(origin, remove: T::AccountId, add: T::AccountId) { T::SwapOrigin::try_origin(origin) .map(|_| ()) .or_else(ensure_root)?; @@ -188,7 +189,7 @@ decl_module! { /// /// May only be called from `ResetOrigin` or root. #[weight = 50_000_000] - fn reset_members(origin, members: Vec) { + pub fn reset_members(origin, members: Vec) { T::ResetOrigin::try_origin(origin) .map(|_| ()) .or_else(ensure_root)?; @@ -211,7 +212,7 @@ decl_module! { /// /// Prime membership is passed from the origin account to `new`, if extant. #[weight = 50_000_000] - fn change_key(origin, new: T::AccountId) { + pub fn change_key(origin, new: T::AccountId) { let remove = ensure_signed(origin)?; if remove != new { @@ -239,7 +240,7 @@ decl_module! { /// Set the prime member. Must be a current member. #[weight = 50_000_000] - fn set_prime(origin, who: T::AccountId) { + pub fn set_prime(origin, who: T::AccountId) { T::PrimeOrigin::try_origin(origin) .map(|_| ()) .or_else(ensure_root)?; @@ -250,7 +251,7 @@ decl_module! { /// Remove the prime member if it exists. #[weight = 50_000_000] - fn clear_prime(origin) { + pub fn clear_prime(origin) { T::PrimeOrigin::try_origin(origin) .map(|_| ()) .or_else(ensure_root)?; @@ -317,6 +318,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/metadata/Cargo.toml b/frame/metadata/Cargo.toml index 73418be9b2b69295cd8cfd088be1161b0cf8e6b8..4eac66ca5caa02321576f486f8cb8c6a5e2c3809 100644 --- a/frame/metadata/Cargo.toml +++ b/frame/metadata/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-metadata" -version = "11.0.0-dev" +version = "11.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Decodable variant of the RuntimeMetadata." @@ -14,8 +14,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/metadata/src/lib.rs b/frame/metadata/src/lib.rs index bec69999b2187338ea48c5f57941105c70fbc691..c0eeb76b6f97625179caa47bb08b7232ea1835ca 100644 --- a/frame/metadata/src/lib.rs +++ b/frame/metadata/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Decodable variant of the RuntimeMetadata. //! diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml index fcb64731051e0e8d85894571232942e5f6c5f08c..38952e6e94d58bac6d3d7029e676d7885c72004c 100644 --- a/frame/nicks/Cargo.toml +++ b/frame/nicks/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-nicks" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for nick management" @@ -14,15 +14,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } [features] default = ["std"] diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 3088e7b68da4d37d63378c637eed08e15cccf8a0..11b23443d68b9b06f186bd4fdba933abd1e45299 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Nicks Module //! @@ -284,6 +285,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml index e0759325feba7db1591f38e34823248dc6990e98..260419741f0ac8b63db3af53aa695ac47f8be04e 100644 --- a/frame/offences/Cargo.toml +++ b/frame/offences/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-offences" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME offences pallet" @@ -12,18 +12,18 @@ description = "FRAME offences pallet" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -pallet-balances = { version = "2.0.0-dev", default-features = false, path = "../balances" } +pallet-balances = { version = "2.0.0-rc2", default-features = false, path = "../balances" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } serde = { version = "1.0.101", optional = true } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/offences/benchmarking/Cargo.toml b/frame/offences/benchmarking/Cargo.toml index 7b998176eb0de810841b5b242e430d9c7686801b..f72036361bb324788f28dfa946dcd549feee9dfb 100644 --- a/frame/offences/benchmarking/Cargo.toml +++ b/frame/offences/benchmarking/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-offences-benchmarking" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME offences pallet benchmarking" @@ -13,28 +13,27 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../../benchmarking" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../../system" } -pallet-babe = { version = "2.0.0-dev", default-features = false, path = "../../babe" } -pallet-balances = { version = "2.0.0-dev", default-features = false, path = "../../balances" } -pallet-grandpa = { version = "2.0.0-dev", default-features = false, path = "../../grandpa" } -pallet-im-online = { version = "2.0.0-dev", default-features = false, path = "../../im-online" } -pallet-offences = { version = "2.0.0-dev", default-features = false, features = ["runtime-benchmarks"], path = "../../offences" } -pallet-session = { version = "2.0.0-dev", default-features = false, path = "../../session" } -pallet-staking = { version = "2.0.0-dev", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" } -sp-io = { path = "../../../primitives/io", default-features = false, version = "2.0.0-dev"} -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/staking" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/std" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../../benchmarking" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../../system" } +pallet-babe = { version = "2.0.0-rc2", default-features = false, path = "../../babe" } +pallet-balances = { version = "2.0.0-rc2", default-features = false, path = "../../balances" } +pallet-grandpa = { version = "2.0.0-rc2", default-features = false, path = "../../grandpa" } +pallet-im-online = { version = "2.0.0-rc2", default-features = false, path = "../../im-online" } +pallet-offences = { version = "2.0.0-rc2", default-features = false, features = ["runtime-benchmarks"], path = "../../offences" } +pallet-session = { version = "2.0.0-rc2", default-features = false, path = "../../session" } +pallet-staking = { version = "2.0.0-rc2", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/staking" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/std" } [dev-dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -pallet-staking-reward-curve = { version = "2.0.0-dev", path = "../../staking/reward-curve" } -pallet-timestamp = { version = "2.0.0-dev", path = "../../timestamp" } +pallet-staking-reward-curve = { version = "2.0.0-rc2", path = "../../staking/reward-curve" } +pallet-timestamp = { version = "2.0.0-rc2", path = "../../timestamp" } serde = { version = "1.0.101" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-io ={ path = "../../../primitives/io", version = "2.0.0-dev"} +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-io = { version = "2.0.0-rc2", path = "../../../primitives/io" } [features] default = ["std"] @@ -52,5 +51,4 @@ std = [ "sp-runtime/std", "sp-staking/std", "sp-std/std", - "sp-io/std", ] diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index a0e05a74d58db8dee8fc34c1688d0fce5635d9de..1d726aedbb7f682e1f380bcb798cce9deffe31a3 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Offences pallet benchmarking. diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 20cf337d442b935682471f8fdaf7667ca4b49816..28263a5292cb53417f80cb590cca76019f46fe4a 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -1,25 +1,29 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock file for offences benchmarking. #![cfg(test)] use super::*; -use frame_support::parameter_types; +use frame_support::{ + parameter_types, + weights::{Weight, constants::WEIGHT_PER_SECOND}, +}; use frame_system as system; use sp_runtime::{ SaturatedConversion, @@ -33,6 +37,10 @@ type AccountIndex = u32; type BlockNumber = u64; type Balance = u64; +parameter_types! { + pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; +} + impl frame_system::Trait for Test { type Origin = Origin; type Index = AccountIndex; @@ -45,7 +53,7 @@ impl frame_system::Trait for Test { type Header = sp_runtime::testing::Header; type Event = Event; type BlockHashCount = (); - type MaximumBlockWeight = (); + type MaximumBlockWeight = MaximumBlockWeight; type DbWeight = (); type AvailableBlockRatio = (); type MaximumBlockLength = (); @@ -56,6 +64,7 @@ impl frame_system::Trait for Test { type OnKilledAccount = (Balances,); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); } parameter_types! { pub const ExistentialDeposit: Balance = 10; @@ -177,10 +186,15 @@ impl pallet_im_online::Trait for Test { type UnsignedPriority = (); } +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); +} + impl pallet_offences::Trait for Test { type Event = Event; type IdentificationTuple = pallet_session::historical::IdentificationTuple; type OnOffenceHandler = Staking; + type WeightSoftLimit = OffencesWeightSoftLimit; } impl frame_system::offchain::SendTransactionTypes for Test where Call: From { diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index b877d1e2b20dd1972c2dd6db776e984b76c9de56..a42f09697e3b46c3ef6e75f488411a55ee6c9f39 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Offences Module //! @@ -27,9 +28,10 @@ mod tests; use sp_std::vec::Vec; use frame_support::{ decl_module, decl_event, decl_storage, Parameter, debug, + traits::Get, weights::Weight, }; -use sp_runtime::{traits::Hash, Perbill}; +use sp_runtime::{traits::{Hash, Zero}, Perbill}; use sp_staking::{ SessionIndex, offence::{Offence, ReportOffence, Kind, OnOffenceHandler, OffenceDetails, OffenceError}, @@ -57,7 +59,11 @@ pub trait Trait: frame_system::Trait { /// Full identification of the validator. type IdentificationTuple: Parameter + Ord; /// A handler called for every offence report. - type OnOffenceHandler: OnOffenceHandler; + type OnOffenceHandler: OnOffenceHandler; + /// The a soft limit on maximum weight that may be consumed while dispatching deferred offences in + /// `on_initialize`. + /// Note it's going to be exceeded before we stop adding to it, so it has to be set conservatively. + type WeightSoftLimit: Get; } decl_storage! { @@ -101,23 +107,39 @@ decl_module! { fn on_initialize(now: T::BlockNumber) -> Weight { // only decode storage if we can actually submit anything again. - if T::OnOffenceHandler::can_report() { - >::mutate(|deferred| { - // keep those that fail to be reported again. An error log is emitted here; this - // should not happen if staking's `can_report` is implemented properly. - deferred.retain(|(o, p, s)| { - T::OnOffenceHandler::on_offence(&o, &p, *s).map_err(|_| { - debug::native::error!( - target: "pallet-offences", - "re-submitting a deferred slash returned Err at {}. This should not happen with pallet-staking", - now, - ); - }).is_err() - }) - }) + if !T::OnOffenceHandler::can_report() { + return 0; } - 0 + let limit = T::WeightSoftLimit::get(); + let mut consumed = Weight::zero(); + + >::mutate(|deferred| { + deferred.retain(|(offences, perbill, session)| { + if consumed >= limit { + true + } else { + // keep those that fail to be reported again. An error log is emitted here; this + // should not happen if staking's `can_report` is implemented properly. + match T::OnOffenceHandler::on_offence(&offences, &perbill, *session) { + Ok(weight) => { + consumed += weight; + false + }, + Err(_) => { + debug::native::error!( + target: "pallet-offences", + "re-submitting a deferred slash returned Err at {}. This should not happen with pallet-staking", + now, + ); + true + }, + } + } + }) + }); + + consumed } } } diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs index 595d091ea445556261e320803e06ad2d4e792938..30d2409a0019470d9897742138ddc8cc8e05f4e0 100644 --- a/frame/offences/src/mock.rs +++ b/frame/offences/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -31,7 +32,7 @@ use sp_runtime::traits::{IdentityLookup, BlakeTwo256}; use sp_core::H256; use frame_support::{ impl_outer_origin, impl_outer_event, parameter_types, StorageMap, StorageDoubleMap, - weights::Weight, + weights::{Weight, constants::{WEIGHT_PER_SECOND, RocksDbWeight}}, }; use frame_system as system; @@ -44,20 +45,23 @@ pub struct OnOffenceHandler; thread_local! { pub static ON_OFFENCE_PERBILL: RefCell> = RefCell::new(Default::default()); pub static CAN_REPORT: RefCell = RefCell::new(true); + pub static OFFENCE_WEIGHT: RefCell = RefCell::new(Default::default()); } -impl offence::OnOffenceHandler for OnOffenceHandler { +impl + offence::OnOffenceHandler for OnOffenceHandler +{ fn on_offence( _offenders: &[OffenceDetails], slash_fraction: &[Perbill], _offence_session: SessionIndex, - ) -> Result<(), ()> { - if >::can_report() { + ) -> Result { + if >::can_report() { ON_OFFENCE_PERBILL.with(|f| { *f.borrow_mut() = slash_fraction.to_vec(); }); - Ok(()) + Ok(OFFENCE_WEIGHT.with(|w| *w.borrow())) } else { Err(()) } @@ -78,12 +82,16 @@ pub fn with_on_offence_fractions) -> R>(f: F) -> }) } +pub fn set_offence_weight(new: Weight) { + OFFENCE_WEIGHT.with(|w| *w.borrow_mut() = new); +} + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Runtime; parameter_types! { pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } @@ -100,9 +108,10 @@ impl frame_system::Trait for Runtime { type Event = TestEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); + type DbWeight = RocksDbWeight; type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -112,10 +121,15 @@ impl frame_system::Trait for Runtime { type OnKilledAccount = (); } +parameter_types! { + pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); +} + impl Trait for Runtime { type Event = TestEvent; type IdentificationTuple = u64; type OnOffenceHandler = OnOffenceHandler; + type WeightSoftLimit = OffencesWeightSoftLimit; } mod offences { diff --git a/frame/offences/src/tests.rs b/frame/offences/src/tests.rs index 3179a0752318f1340ae924599734423b793fb012..0fb6620b7d81210e7fbe7f8781e376d7dfcee593 100644 --- a/frame/offences/src/tests.rs +++ b/frame/offences/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the offences module. @@ -21,7 +22,7 @@ use super::*; use crate::mock::{ Offences, System, Offence, TestEvent, KIND, new_test_ext, with_on_offence_fractions, - offence_reports, set_can_report, + offence_reports, set_can_report, set_offence_weight, }; use sp_runtime::Perbill; use frame_support::traits::OnInitialize; @@ -264,3 +265,48 @@ fn should_queue_and_resubmit_rejected_offence() { assert_eq!(Offences::deferred_offences().len(), 0); }) } + +#[test] +fn weight_soft_limit_is_used() { + new_test_ext().execute_with(|| { + set_can_report(false); + // Only 2 can fit in one block + set_offence_weight(::WeightSoftLimit::get() / 2); + + // Queue 3 offences + // #1 + let offence = Offence { + validator_set_count: 5, + time_slot: 42, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence).unwrap(); + // #2 + let offence = Offence { + validator_set_count: 5, + time_slot: 62, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence).unwrap(); + // #3 + let offence = Offence { + validator_set_count: 5, + time_slot: 72, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence).unwrap(); + // 3 are queued + assert_eq!(Offences::deferred_offences().len(), 3); + + // Allow reporting + set_can_report(true); + + Offences::on_initialize(3); + // Two are completed, one is left in the queue + assert_eq!(Offences::deferred_offences().len(), 1); + + Offences::on_initialize(4); + // All are done now + assert_eq!(Offences::deferred_offences().len(), 0); + }) +} diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml index 08d715899fb89189f83e3806ade882e0a01fb482..a539c295fe086f22bcedbf46af669fde3af87381 100644 --- a/frame/randomness-collective-flip/Cargo.toml +++ b/frame/randomness-collective-flip/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-randomness-collective-flip" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME randomness collective flip pallet" @@ -14,14 +14,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] safe-mix = { version = "1.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index 29068ea91ff81e17de7df6ea7dbea793772feabd..4a851c926fb7445407be7f32df8a879fb9c918a3 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Randomness Module //! @@ -172,6 +173,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/recovery/Cargo.toml b/frame/recovery/Cargo.toml index de422678c370d5e84b0525de89b83c8bc0fcc283..fe9e904fb38348cb5e6cb1883d366a293bb6cf3c 100644 --- a/frame/recovery/Cargo.toml +++ b/frame/recovery/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-recovery" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME account recovery pallet" @@ -15,15 +15,15 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } [features] default = ["std"] diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index 008461e50392b6ed144c6137fe0d37c5ed75f8fb..cd3ba76b37012cd819d8849de691766e4228246f 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Recovery Pallet //! diff --git a/frame/recovery/src/mock.rs b/frame/recovery/src/mock.rs index 648321a0ae77b541ec64643da6a5d38b83ce8892..aae9b2b75cf8c43f7c6176e5dce0e55f6d036c59 100644 --- a/frame/recovery/src/mock.rs +++ b/frame/recovery/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -78,6 +79,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/recovery/src/tests.rs b/frame/recovery/src/tests.rs index fb993043a5b005f4e94976f99a9701af6ab83b79..5192bdaca85e20c493613a71f0419eef688f6014 100644 --- a/frame/recovery/src/tests.rs +++ b/frame/recovery/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. diff --git a/frame/scheduler/Cargo.toml b/frame/scheduler/Cargo.toml index 6cc9161eea455212517aa3affa7d13027a1f54af..79a1a892690aaded0b4031eb3eb453d170a460b1 100644 --- a/frame/scheduler/Cargo.toml +++ b/frame/scheduler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-scheduler" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" @@ -11,16 +11,16 @@ description = "FRAME example pallet" [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.2.0", default-features = false } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core", default-features = false } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core", default-features = false } [features] default = ["std"] diff --git a/frame/scheduler/src/benchmarking.rs b/frame/scheduler/src/benchmarking.rs index ac9c19f7c3dc05b59f1480f80b74b85b2138c087..975c10e3b6c8f1a2ddc7e4c1e1b4b6a6e824a768 100644 --- a/frame/scheduler/src/benchmarking.rs +++ b/frame/scheduler/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Scheduler pallet benchmarking. diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index 029e1fd138db0d7cbad8f96934ff5b4991d7a31e..687fe46d16a676d08cbfc0e8bddf33cab8c1c4e5 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Scheduler //! @@ -501,6 +502,7 @@ mod tests { type DbWeight = RocksDbWeight; type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -513,7 +515,7 @@ mod tests { type Event = (); } parameter_types! { - pub const MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * MaximumBlockWeight::get(); } impl Trait for Test { type Event = (); diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml index ae8def3dd391b0e43ac4cd156eb70d6241cce4c0..4bee2eec30ce74c112db3fd8246191da9054816e 100644 --- a/frame/scored-pool/Cargo.toml +++ b/frame/scored-pool/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-scored-pool" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for scored pools" @@ -14,15 +14,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/scored-pool/src/lib.rs b/frame/scored-pool/src/lib.rs index 1ba999cc7c8380bd8a68eb9627e5853f0255304f..ba56298493a99b4148472e4db976393ff20bbf0a 100644 --- a/frame/scored-pool/src/lib.rs +++ b/frame/scored-pool/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Scored Pool Module //! diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index 6d914c60aae2c90cccada321d783d379ee590866..1b61bb18846f4a5d1d4f2b8dfb2334125cd59aff 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -69,6 +70,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/scored-pool/src/tests.rs b/frame/scored-pool/src/tests.rs index 8d87a20f757b223443b2b134fb1d66f0ab793b53..9c0074ff6e6899f6efe7967c1ddeb28661a3b5fd 100644 --- a/frame/scored-pool/src/tests.rs +++ b/frame/scored-pool/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml index 9237f0a16f64a435f9758971ea64dc248ab4ff7d..b79dc78f12c33585576842b53b4effb087be49d6 100644 --- a/frame/session/Cargo.toml +++ b/frame/session/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-session" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME sessions pallet" @@ -14,20 +14,20 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-session = { version = "2.0.0-dev", default-features = false, path = "../../primitives/session" } -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-timestamp = { version = "2.0.0-dev", default-features = false, path = "../timestamp" } -sp-trie = { optional = true, path = "../../primitives/trie", default-features = false, version = "2.0.0-dev"} -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-dev"} +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-session = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/session" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../timestamp" } +sp-trie = { version = "2.0.0-rc2", optional = true, default-features = false, path = "../../primitives/trie" } impl-trait-for-tuples = "0.1.3" [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-application-crypto = { version = "2.0.0-dev", path = "../../primitives/application-crypto" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../primitives/io" } +sp-application-crypto = { version = "2.0.0-rc2", path = "../../primitives/application-crypto" } lazy_static = "1.4.0" [features] @@ -43,5 +43,4 @@ std = [ "sp-staking/std", "pallet-timestamp/std", "sp-trie/std", - "sp-io/std", ] diff --git a/frame/session/benchmarking/Cargo.toml b/frame/session/benchmarking/Cargo.toml index a3994ab3790aeea6a621382850991ed00228d171..1fe2438195a3bbf2d3bd0ff5196a1bc9887d8cb5 100644 --- a/frame/session/benchmarking/Cargo.toml +++ b/frame/session/benchmarking/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-session-benchmarking" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME sessions pallet benchmarking" @@ -12,22 +12,22 @@ description = "FRAME sessions pallet benchmarking" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../../system" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../../benchmarking" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../../support" } -pallet-staking = { version = "2.0.0-dev", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" } -pallet-session = { version = "2.0.0-dev", default-features = false, path = "../../session" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/runtime" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../../system" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../../benchmarking" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../../support" } +pallet-staking = { version = "2.0.0-rc2", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" } +pallet-session = { version = "2.0.0-rc2", default-features = false, path = "../../session" } [dev-dependencies] serde = { version = "1.0.101" } codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -pallet-staking-reward-curve = { version = "2.0.0-dev", path = "../../staking/reward-curve" } -sp-io ={ path = "../../../primitives/io", version = "2.0.0-dev"} -pallet-timestamp = { version = "2.0.0-dev", path = "../../timestamp" } -pallet-balances = { version = "2.0.0-dev", path = "../../balances" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +pallet-staking-reward-curve = { version = "2.0.0-rc2", path = "../../staking/reward-curve" } +sp-io ={ version = "2.0.0-rc2", path = "../../../primitives/io" } +pallet-timestamp = { version = "2.0.0-rc2", path = "../../timestamp" } +pallet-balances = { version = "2.0.0-rc2", path = "../../balances" } [features] default = ["std"] diff --git a/frame/session/benchmarking/src/lib.rs b/frame/session/benchmarking/src/lib.rs index 3b91c2fdc5194f56086b139eb33a71efc468e050..04b7d556026da81efb0573ad37fc482a736964e5 100644 --- a/frame/session/benchmarking/src/lib.rs +++ b/frame/session/benchmarking/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Benchmarks for the Session Pallet. // This is separated into its own crate due to cyclic dependency issues. diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 5a7082dabbad65fcc48d179476421e50e63a17ea..5c0e40096eaf85b7bf31bacb2c8e6a4b49b6592b 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock file for session benchmarking. @@ -72,6 +73,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); type AvailableBlockRatio = (); type MaximumBlockLength = (); type Version = (); diff --git a/frame/session/src/historical.rs b/frame/session/src/historical.rs index d9711ecf9d3bd0242555749889604ea75810b1d5..a1c286eb39245548fa4c460dc7d2113f0412b262 100644 --- a/frame/session/src/historical.rs +++ b/frame/session/src/historical.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! An opt-in utility for tracking historical sessions in FRAME-session. //! diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 8e252211319fbf8652148399ea75eea0a450eae1..6f5630adf9ecf5836d610d763cbe2892290cab1e 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Session Module //! @@ -170,6 +171,14 @@ impl< offset }) } + + fn weight(_now: BlockNumber) -> Weight { + // Weight note: `estimate_next_session_rotation` has no storage reads and trivial computational overhead. + // There should be no risk to the chain having this weight value be zero for now. + // However, this value of zero was not properly calculated, and so it would be reasonable + // to come back here and properly calculate the weight of this function. + 0 + } } /// A trait for managing creation of new validator set. @@ -210,7 +219,7 @@ pub trait SessionHandler { /// All the key type ids this session handler can process. /// /// The order must be the same as it expects them in - /// [`on_new_session`](Self::on_new_session) and [`on_genesis_session`](Self::on_genesis_session). + /// [`on_new_session`](Self::on_new_session) and [`on_genesis_session`](Self::on_genesis_session). const KEY_TYPE_IDS: &'static [KeyTypeId]; /// The given validator set will be used for the genesis session. @@ -785,4 +794,8 @@ impl EstimateNextNewSession for Module { fn estimate_next_new_session(now: T::BlockNumber) -> Option { T::NextSessionRotation::estimate_next_session_rotation(now) } + + fn weight(now: T::BlockNumber) -> Weight { + T::NextSessionRotation::weight(now) + } } diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index 9e9b8776589d29b88fc58738bfe77b45f997ec2e..e7a98960648444d355e628f3cf0dbc6c2674c8f4 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock helpers for Session. @@ -187,6 +188,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/session/src/tests.rs b/frame/session/src/tests.rs index abfd9f738b614e2d9078ddfe02c07a1f3d862a32..75def78046bebf97111feca0320a256d17bb3207 100644 --- a/frame/session/src/tests.rs +++ b/frame/session/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Tests for the Session Pallet diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml index d79eb78b7d664dbd88da1c931730678aab6d7c4f..25f596e9fd1ad1952ca1af6cb57c6cd9367572e8 100644 --- a/frame/society/Cargo.toml +++ b/frame/society/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-society" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME society pallet" @@ -14,23 +14,22 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-io ={ path = "../../primitives/io", default-features = false , version = "2.0.0-dev"} -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } rand_chacha = { version = "0.2", default-features = false } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../primitives/io" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } [features] default = ["std"] std = [ "codec/std", "serde", - "sp-io/std", "sp-runtime/std", "rand_chacha/std", "sp-std/std", diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs index fcc0c66ebdbb463db4b320c388cc9eb32e1165d5..122ed06b2911917d2347ce03717052ca3857d290 100644 --- a/frame/society/src/lib.rs +++ b/frame/society/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Society Module //! diff --git a/frame/society/src/mock.rs b/frame/society/src/mock.rs index 121ec59555f0e73497600ef5ff653db443163202..7ddd25ee6a09b0c2e83d4fd258beb991dc3b1ed1 100644 --- a/frame/society/src/mock.rs +++ b/frame/society/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -79,6 +80,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/society/src/tests.rs b/frame/society/src/tests.rs index 8b10dc32e7ba0de12199d35ce580e77319090d26..8f18ecba469b61ab3831f6fbd22714de953b7933 100644 --- a/frame/society/src/tests.rs +++ b/frame/society/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml index 3ee07b5dec80d7b271e87aadbf933bd6f8d6bc5f..916e5676dad1904815e8d1ec605470c5ab471fbd 100644 --- a/frame/staking/Cargo.toml +++ b/frame/staking/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-staking" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet staking" @@ -12,49 +12,38 @@ description = "FRAME pallet staking" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +static_assertions = "1.1.0" serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-phragmen = { version = "2.0.0-dev", default-features = false, path = "../../primitives/phragmen" } -sp-io ={ version = "2.0.0-dev", path = "../../primitives/io", default-features = false } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-staking = { version = "2.0.0-dev", default-features = false, path = "../../primitives/staking" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-session = { version = "2.0.0-dev", features = ["historical"], path = "../session", default-features = false } -pallet-authorship = { version = "2.0.0-dev", default-features = false, path = "../authorship" } -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../primitives/application-crypto" } -static_assertions = "1.1.0" - -# Optional imports for tesing-utils feature -pallet-indices = { version = "2.0.0-dev", optional = true, path = "../indices", default-features = false } -sp-core = { version = "2.0.0-dev", optional = true, path = "../../primitives/core", default-features = false } -rand = { version = "0.7.3", optional = true, default-features = false } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-phragmen = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/phragmen" } +sp-io ={ version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0-rc2", default-features = false, features = ["historical"], path = "../session" } +pallet-authorship = { version = "2.0.0-rc2", default-features = false, path = "../authorship" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/application-crypto" } # Optional imports for benchmarking -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } rand_chacha = { version = "0.2", default-features = false, optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -sp-storage = { version = "2.0.0-dev", path = "../../primitives/storage" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -pallet-timestamp = { version = "2.0.0-dev", path = "../timestamp" } -pallet-staking-reward-curve = { version = "2.0.0-dev", path = "../staking/reward-curve" } -substrate-test-utils = { version = "2.0.0-dev", path = "../../test-utils" } -frame-benchmarking = { version = "2.0.0-dev", path = "../benchmarking" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +sp-storage = { version = "2.0.0-rc2", path = "../../primitives/storage" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +pallet-timestamp = { version = "2.0.0-rc2", path = "../timestamp" } +pallet-staking-reward-curve = { version = "2.0.0-rc2", path = "../staking/reward-curve" } +substrate-test-utils = { version = "2.0.0-rc2", path = "../../test-utils" } +frame-benchmarking = { version = "2.0.0-rc2", path = "../benchmarking" } rand_chacha = { version = "0.2" } parking_lot = "0.10.2" env_logger = "0.7.1" hex = "0.4" [features] -testing-utils = [ - "std", - "pallet-indices/std", - "sp-core/std", - "rand/std", -] default = ["std"] std = [ "serde", @@ -69,9 +58,8 @@ std = [ "frame-system/std", "pallet-authorship/std", "sp-application-crypto/std", - "sp-core/std", ] runtime-benchmarks = [ - "rand_chacha", "frame-benchmarking", + "rand_chacha", ] diff --git a/frame/staking/fuzzer/Cargo.lock b/frame/staking/fuzzer/Cargo.lock index a45f33fdce2492109446030c1a082e7cc32f2f19..f6cb65aa5cd19d4b7392394716b03bcb1656cc3a 100644 --- a/frame/staking/fuzzer/Cargo.lock +++ b/frame/staking/fuzzer/Cargo.lock @@ -1763,7 +1763,7 @@ dependencies = [ [[package]] name = "sp-phragmen-compact" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/frame/staking/fuzzer/Cargo.toml b/frame/staking/fuzzer/Cargo.toml index 812e5b2fc1de9ac82f9e71448fe0d2b09f41b8a8..f4a31ff11a891ab814f1f697a77b69268ce8613c 100644 --- a/frame/staking/fuzzer/Cargo.toml +++ b/frame/staking/fuzzer/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" authors = ["Automatically generated"] publish = false edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet staking fuzzing" @@ -15,19 +15,19 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] honggfuzz = "0.5" codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -pallet-staking = { version = "2.0.0-dev", path = "..", features = ["testing-utils"] } -pallet-staking-reward-curve = { version = "2.0.0-dev", path = "../reward-curve" } -pallet-session = { version = "2.0.0-dev", path = "../../session" } -pallet-indices = { version = "2.0.0-dev", path = "../../indices" } -pallet-balances = { version = "2.0.0-dev", path = "../../balances" } -pallet-timestamp = { version = "2.0.0-dev", path = "../../timestamp" } -frame-system = { version = "2.0.0-dev", path = "../../system" } -frame-support = { version = "2.0.0-dev", path = "../../support" } -sp-std = { version = "2.0.0-dev", path = "../../../primitives/std" } -sp-io ={ version = "2.0.0-dev", path = "../../../primitives/io" } -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-phragmen = { version = "2.0.0-dev", path = "../../../primitives/phragmen" } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } +pallet-staking = { version = "2.0.0-rc2", path = "..", features = ["runtime-benchmarks"] } +pallet-staking-reward-curve = { version = "2.0.0-rc2", path = "../reward-curve" } +pallet-session = { version = "2.0.0-rc2", path = "../../session" } +pallet-indices = { version = "2.0.0-rc2", path = "../../indices" } +pallet-balances = { version = "2.0.0-rc2", path = "../../balances" } +pallet-timestamp = { version = "2.0.0-rc2", path = "../../timestamp" } +frame-system = { version = "2.0.0-rc2", path = "../../system" } +frame-support = { version = "2.0.0-rc2", path = "../../support" } +sp-std = { version = "2.0.0-rc2", path = "../../../primitives/std" } +sp-io ={ version = "2.0.0-rc2", path = "../../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-phragmen = { version = "2.0.0-rc2", path = "../../../primitives/phragmen" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } [[bin]] name = "submit_solution" diff --git a/frame/staking/fuzzer/src/mock.rs b/frame/staking/fuzzer/src/mock.rs index 1819970e6061e62ef54537887bcbc50efca1d260..0e3b6cb13fbb7648dea855acbad6af499dfd2bee 100644 --- a/frame/staking/fuzzer/src/mock.rs +++ b/frame/staking/fuzzer/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock file for staking fuzzing. @@ -60,6 +61,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); type Index = AccountIndex; type BlockNumber = BlockNumber; type Call = Call; diff --git a/frame/staking/fuzzer/src/submit_solution.rs b/frame/staking/fuzzer/src/submit_solution.rs index cc897abac2d78edfa3cac8f354ddc2775daf6c1c..fafd686c9d802d14a6127ced72edaa522703c613 100644 --- a/frame/staking/fuzzer/src/submit_solution.rs +++ b/frame/staking/fuzzer/src/submit_solution.rs @@ -1,31 +1,33 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Fuzzing for staking pallet. +//! +//! HFUZZ_RUN_ARGS="-n 8" cargo hfuzz run submit_solution use honggfuzz::fuzz; use mock::Test; -use pallet_staking::testing_utils::{ - USER, get_seq_phragmen_solution, get_weak_solution, setup_chain_stakers, - set_validator_count, signed_account, -}; +use pallet_staking::testing_utils::*; use frame_support::{assert_ok, storage::StorageValue}; +use frame_system::RawOrigin; use sp_runtime::{traits::Dispatchable, DispatchError}; use sp_core::offchain::{testing::TestOffchainExt, OffchainExt}; +use pallet_staking::{EraElectionStatus, ElectionStatus, Module as Staking, Call as StakingCall}; mod mock; @@ -87,47 +89,52 @@ fn main() { ext.execute_with(|| { // initial setup - set_validator_count::(to_elect); - pallet_staking::testing_utils::init_active_era(); - setup_chain_stakers::( + init_active_era(); + assert_ok!(create_validators_with_nominators_for_era::( num_validators, num_nominators, - edge_per_voter, - ); - >::put(pallet_staking::ElectionStatus::Open(1)); + edge_per_voter as usize, + true, + None, + )); + >::put(ElectionStatus::Open(1)); + assert!(>::create_stakers_snapshot().0); + let origin = RawOrigin::Signed(create_funded_user::("fuzzer", 0, 100)); println!("++ Chain setup done."); // stuff to submit - let (winners, compact, score) = match mode { + let (winners, compact, score, size) = match mode { Mode::InitialSubmission => { /* No need to setup anything */ get_seq_phragmen_solution::(do_reduce) }, Mode::StrongerSubmission => { - let (winners, compact, score) = get_weak_solution::(false); + let (winners, compact, score, size) = get_weak_solution::(false); println!("Weak on chain score = {:?}", score); assert_ok!( - >::submit_election_solution( - signed_account::(USER), + >::submit_election_solution( + origin.clone().into(), winners, compact, score, - pallet_staking::testing_utils::active_era::(), + current_era::(), + size, ) ); get_seq_phragmen_solution::(do_reduce) }, Mode::WeakerSubmission => { - let (winners, compact, score) = get_seq_phragmen_solution::(do_reduce); + let (winners, compact, score, size) = get_seq_phragmen_solution::(do_reduce); println!("Strong on chain score = {:?}", score); assert_ok!( - >::submit_election_solution( - signed_account::(USER), + >::submit_election_solution( + origin.clone().into(), winners, compact, score, - pallet_staking::testing_utils::active_era::(), + current_era::(), + size, ) ); get_weak_solution::(false) @@ -137,27 +144,34 @@ fn main() { println!("++ Submission ready. Score = {:?}", score); // must have chosen correct number of winners. - assert_eq!(winners.len() as u32, >::validator_count()); + assert_eq!(winners.len() as u32, >::validator_count()); // final call and origin - let call = pallet_staking::Call::::submit_election_solution( + let call = StakingCall::::submit_election_solution( winners, compact, score, - pallet_staking::testing_utils::active_era::(), + current_era::(), + size, ); - let caller = signed_account::(USER); // actually submit match mode { Mode::WeakerSubmission => { assert_eq!( - call.dispatch(caller.into()).unwrap_err().error, - DispatchError::Module { index: 0, error: 16, message: Some("PhragmenWeakSubmission") }, + call.dispatch(origin.clone().into()).unwrap_err().error, + DispatchError::Module { + index: 0, + error: 16, + message: Some("PhragmenWeakSubmission"), + }, ); }, - // NOTE: so exhaustive pattern doesn't work here.. maybe some rust issue? or due to `#[repr(u32)]`? - Mode::InitialSubmission | Mode::StrongerSubmission => assert!(call.dispatch(caller.into()).is_ok()), + // NOTE: so exhaustive pattern doesn't work here.. maybe some rust issue? + // or due to `#[repr(u32)]`? + Mode::InitialSubmission | Mode::StrongerSubmission => { + assert_ok!(call.dispatch(origin.into())); + } }; }) }); diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml index b11d1cc0493389473a78e527b14d14ec68a1d765..582f8d79f35cb23c90bebb103a57fa07c9a5d732 100644 --- a/frame/staking/reward-curve/Cargo.toml +++ b/frame/staking/reward-curve/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-staking-reward-curve" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Reward Curve for FRAME staking pallet" @@ -21,4 +21,4 @@ proc-macro2 = "1.0.6" proc-macro-crate = "0.1.4" [dev-dependencies] -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } diff --git a/frame/staking/reward-curve/src/lib.rs b/frame/staking/reward-curve/src/lib.rs index 5a3d88bb537a876e3d89dbad715ba11523c5b983..9b55b346d5fd11bf59a9c8e4ccd76841384b46f0 100644 --- a/frame/staking/reward-curve/src/lib.rs +++ b/frame/staking/reward-curve/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Proc macro to generate the reward curve functions and tests. diff --git a/frame/staking/reward-curve/tests/test.rs b/frame/staking/reward-curve/tests/test.rs index 89f8653fe18d937881a2b6f916c2bca26918716c..45ad59e00ad279f9c4db932370183fdeb336ef1c 100644 --- a/frame/staking/reward-curve/tests/test.rs +++ b/frame/staking/reward-curve/tests/test.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test crate for pallet-staking-reward-curve. Allows to test for procedural macro. //! See tests directory. diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 2686623aa1eae85655beaf9a917679d1e483319f..d3723dce1cc11cc14e17365b7af0fa2bb1a95129 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -1,112 +1,59 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Staking pallet benchmarking. use super::*; - -use rand_chacha::{rand_core::{RngCore, SeedableRng}, ChaChaRng}; - -use sp_runtime::traits::{Dispatchable, One}; -use sp_io::hashing::blake2_256; - -use frame_system::RawOrigin; -use frame_benchmarking::{benchmarks, account}; - use crate::Module as Staking; -use frame_system::Module as System; +use testing_utils::*; +use sp_runtime::{traits::{Dispatchable, One}}; +use frame_system::RawOrigin; +pub use frame_benchmarking::{benchmarks, account}; const SEED: u32 = 0; - -fn create_funded_user(string: &'static str, n: u32) -> T::AccountId { - let user = account(string, n, SEED); - let balance = T::Currency::minimum_balance() * 100.into(); - T::Currency::make_free_balance_be(&user, balance); - user -} - -pub fn create_stash_controller(n: u32) -> Result<(T::AccountId, T::AccountId), &'static str> { - let stash = create_funded_user::("stash", n); - let controller = create_funded_user::("controller", n); - let controller_lookup: ::Source = T::Lookup::unlookup(controller.clone()); - let reward_destination = RewardDestination::Staked; - let amount = T::Currency::minimum_balance() * 10.into(); - Staking::::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, reward_destination)?; - return Ok((stash, controller)) -} - -fn create_validators(max: u32) -> Result::Source>, &'static str> { - let mut validators: Vec<::Source> = Vec::with_capacity(max as usize); - for i in 0 .. max { - let (stash, controller) = create_stash_controller::(i)?; - let validator_prefs = ValidatorPrefs { - commission: Perbill::from_percent(50), - }; - Staking::::validate(RawOrigin::Signed(controller).into(), validator_prefs)?; - let stash_lookup: ::Source = T::Lookup::unlookup(stash); - validators.push(stash_lookup); +const MAX_SPANS: u32 = 100; +const MAX_VALIDATORS: u32 = 1000; +const MAX_SLASHES: u32 = 1000; + +// Add slashing spans to a user account. Not relevant for actual use, only to benchmark +// read and write operations. +fn add_slashing_spans(who: &T::AccountId, spans: u32) { + if spans == 0 { return } + + // For the first slashing span, we initialize + let mut slashing_spans = crate::slashing::SlashingSpans::new(0); + SpanSlash::::insert((who, 0), crate::slashing::SpanRecord::default()); + + for i in 1 .. spans { + assert!(slashing_spans.end_span(i)); + SpanSlash::::insert((who, i), crate::slashing::SpanRecord::default()); } - Ok(validators) + SlashingSpans::::insert(who, slashing_spans); } -// This function generates v validators and n nominators who are randomly nominating up to MAX_NOMINATIONS. -pub fn create_validators_with_nominators_for_era(v: u32, n: u32) -> Result<(), &'static str> { - let mut validators: Vec<::Source> = Vec::with_capacity(v as usize); - let mut rng = ChaChaRng::from_seed(SEED.using_encoded(blake2_256)); - - // Create v validators - for i in 0 .. v { - let (v_stash, v_controller) = create_stash_controller::(i)?; - let validator_prefs = ValidatorPrefs { - commission: Perbill::from_percent(50), - }; - Staking::::validate(RawOrigin::Signed(v_controller.clone()).into(), validator_prefs)?; - let stash_lookup: ::Source = T::Lookup::unlookup(v_stash.clone()); - validators.push(stash_lookup.clone()); - } - - // Create n nominators - for j in 0 .. n { - let (_n_stash, n_controller) = create_stash_controller::(u32::max_value() - j)?; - - // Have them randomly validate - let mut available_validators = validators.clone(); - let mut selected_validators: Vec<::Source> = Vec::with_capacity(MAX_NOMINATIONS); - for _ in 0 .. v.min(MAX_NOMINATIONS as u32) { - let selected = rng.next_u32() as usize % available_validators.len(); - let validator = available_validators.remove(selected); - selected_validators.push(validator); - } - Staking::::nominate(RawOrigin::Signed(n_controller.clone()).into(), selected_validators)?; - } - - ValidatorCount::put(v); - - Ok(()) -} - -// This function generates one validator being nominated by n nominators, and returns -//the validator stash account. It also starts an era and creates pending payouts. +// This function generates one validator being nominated by n nominators, and returns the validator +// stash account. It also starts an era and creates pending payouts. pub fn create_validator_with_nominators(n: u32, upper_bound: u32) -> Result { let mut points_total = 0; let mut points_individual = Vec::new(); MinimumValidatorCount::put(0); - let (v_stash, v_controller) = create_stash_controller::(0)?; + let (v_stash, v_controller) = create_stash_controller::(0, 100)?; let validator_prefs = ValidatorPrefs { commission: Perbill::from_percent(50), }; @@ -118,7 +65,7 @@ pub fn create_validator_with_nominators(n: u32, upper_bound: u32) -> R // Give the validator n nominators, but keep total users in the system the same. for i in 0 .. upper_bound { - let (_n_stash, n_controller) = create_stash_controller::(u32::max_value() - i)?; + let (_n_stash, n_controller) = create_stash_controller::(u32::max_value() - i, 100)?; if i < n { Staking::::nominate(RawOrigin::Signed(n_controller.clone()).into(), vec![stash_lookup.clone()])?; } @@ -155,112 +102,189 @@ benchmarks! { bond { let u in ...; - let stash = create_funded_user::("stash",u); - let controller = create_funded_user::("controller", u); - let controller_lookup: ::Source = T::Lookup::unlookup(controller); + let stash = create_funded_user::("stash", u, 100); + let controller = create_funded_user::("controller", u, 100); + let controller_lookup: ::Source = T::Lookup::unlookup(controller.clone()); let reward_destination = RewardDestination::Staked; let amount = T::Currency::minimum_balance() * 10.into(); - }: _(RawOrigin::Signed(stash), controller_lookup, amount, reward_destination) + }: _(RawOrigin::Signed(stash.clone()), controller_lookup, amount, reward_destination) + verify { + assert!(Bonded::::contains_key(stash)); + assert!(Ledger::::contains_key(controller)); + } bond_extra { let u in ...; - let (stash, _) = create_stash_controller::(u)?; + let (stash, controller) = create_stash_controller::(u, 100)?; let max_additional = T::Currency::minimum_balance() * 10.into(); + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_bonded: BalanceOf = ledger.active; }: _(RawOrigin::Signed(stash), max_additional) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_bonded: BalanceOf = ledger.active; + assert!(original_bonded < new_bonded); + } unbond { let u in ...; - let (_, controller) = create_stash_controller::(u)?; + let (_, controller) = create_stash_controller::(u, 100)?; let amount = T::Currency::minimum_balance() * 10.into(); - }: _(RawOrigin::Signed(controller), amount) + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_bonded: BalanceOf = ledger.active; + }: _(RawOrigin::Signed(controller.clone()), amount) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_bonded: BalanceOf = ledger.active; + assert!(original_bonded > new_bonded); + } + + // Withdraw only updates the ledger + withdraw_unbonded_update { + // Slashing Spans + let s in 0 .. MAX_SPANS; + let (stash, controller) = create_stash_controller::(0, 100)?; + add_slashing_spans::(&stash, s); + let amount = T::Currency::minimum_balance() * 5.into(); // Half of total + Staking::::unbond(RawOrigin::Signed(controller.clone()).into(), amount)?; + CurrentEra::put(EraIndex::max_value()); + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_total: BalanceOf = ledger.total; + }: withdraw_unbonded(RawOrigin::Signed(controller.clone()), s) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_total: BalanceOf = ledger.total; + assert!(original_total > new_total); + } // Worst case scenario, everything is removed after the bonding duration - withdraw_unbonded { - let u in ...; - let (stash, controller) = create_stash_controller::(u)?; + withdraw_unbonded_kill { + // Slashing Spans + let s in 0 .. MAX_SPANS; + let (stash, controller) = create_stash_controller::(0, 100)?; + add_slashing_spans::(&stash, s); let amount = T::Currency::minimum_balance() * 10.into(); Staking::::unbond(RawOrigin::Signed(controller.clone()).into(), amount)?; - let current_block = System::::block_number(); - // let unbond_block = current_block + T::BondingDuration::get().into() + 10.into(); - // System::::set_block_number(unbond_block); - }: _(RawOrigin::Signed(controller)) + CurrentEra::put(EraIndex::max_value()); + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_total: BalanceOf = ledger.total; + }: withdraw_unbonded(RawOrigin::Signed(controller.clone()), s) + verify { + assert!(!Ledger::::contains_key(controller)); + } validate { let u in ...; - let (_, controller) = create_stash_controller::(u)?; + let (stash, controller) = create_stash_controller::(u, 100)?; let prefs = ValidatorPrefs::default(); }: _(RawOrigin::Signed(controller), prefs) + verify { + assert!(Validators::::contains_key(stash)); + } // Worst case scenario, MAX_NOMINATIONS nominate { let n in 1 .. MAX_NOMINATIONS as u32; - let (_, controller) = create_stash_controller::(n + 1)?; - let validators = create_validators::(n)?; + let (stash, controller) = create_stash_controller::(n + 1, 100)?; + let validators = create_validators::(n, 100)?; }: _(RawOrigin::Signed(controller), validators) + verify { + assert!(Nominators::::contains_key(stash)); + } chill { let u in ...; - let (_, controller) = create_stash_controller::(u)?; + let (_, controller) = create_stash_controller::(u, 100)?; }: _(RawOrigin::Signed(controller)) set_payee { let u in ...; - let (_, controller) = create_stash_controller::(u)?; + let (stash, controller) = create_stash_controller::(u, 100)?; + assert_eq!(Payee::::get(&stash), RewardDestination::Staked); }: _(RawOrigin::Signed(controller), RewardDestination::Controller) + verify { + assert_eq!(Payee::::get(&stash), RewardDestination::Controller); + } set_controller { let u in ...; - let (stash, _) = create_stash_controller::(u)?; - let new_controller = create_funded_user::("new_controller", u); - let new_controller_lookup = T::Lookup::unlookup(new_controller); + let (stash, _) = create_stash_controller::(u, 100)?; + let new_controller = create_funded_user::("new_controller", u, 100); + let new_controller_lookup = T::Lookup::unlookup(new_controller.clone()); }: _(RawOrigin::Signed(stash), new_controller_lookup) + verify { + assert!(Ledger::::contains_key(&new_controller)); + } set_validator_count { - let c in 0 .. 1000; + let c in 0 .. MAX_VALIDATORS; }: _(RawOrigin::Root, c) + verify { + assert_eq!(ValidatorCount::get(), c); + } force_no_eras { let i in 0 .. 1; }: _(RawOrigin::Root) + verify { assert_eq!(ForceEra::get(), Forcing::ForceNone); } force_new_era {let i in 0 .. 1; }: _(RawOrigin::Root) + verify { assert_eq!(ForceEra::get(), Forcing::ForceNew); } force_new_era_always { let i in 0 .. 1; }: _(RawOrigin::Root) + verify { assert_eq!(ForceEra::get(), Forcing::ForceAlways); } // Worst case scenario, the list of invulnerables is very long. set_invulnerables { - let v in 0 .. 1000; + let v in 0 .. MAX_VALIDATORS; let mut invulnerables = Vec::new(); for i in 0 .. v { invulnerables.push(account("invulnerable", i, SEED)); } }: _(RawOrigin::Root, invulnerables) + verify { + assert_eq!(Invulnerables::::get().len(), v as usize); + } force_unstake { - let u in ...; - let (stash, _) = create_stash_controller::(u)?; - }: _(RawOrigin::Root, stash) + // Slashing Spans + let s in 0 .. MAX_SPANS; + let (stash, controller) = create_stash_controller::(0, 100)?; + add_slashing_spans::(&stash, s); + }: _(RawOrigin::Root, stash, s) + verify { + assert!(!Ledger::::contains_key(&controller)); + } cancel_deferred_slash { - let s in 1 .. 1000; + let s in 1 .. MAX_SLASHES; let mut unapplied_slashes = Vec::new(); let era = EraIndex::one(); - for _ in 0 .. 1000 { + for _ in 0 .. MAX_SLASHES { unapplied_slashes.push(UnappliedSlash::>::default()); } UnappliedSlashes::::insert(era, &unapplied_slashes); let slash_indices: Vec = (0 .. s).collect(); }: _(RawOrigin::Root, era, slash_indices) + verify { + assert_eq!(UnappliedSlashes::::get(&era).len(), (MAX_SLASHES - s) as usize); + } payout_stakers { - let n in 1 .. MAX_NOMINATIONS as u32; - let validator = create_validator_with_nominators::(n, MAX_NOMINATIONS as u32)?; + let n in 1 .. T::MaxNominatorRewardedPerValidator::get() as u32; + let validator = create_validator_with_nominators::(n, T::MaxNominatorRewardedPerValidator::get() as u32)?; let current_era = CurrentEra::get().unwrap(); - let caller = account("caller", n, SEED); - }: _(RawOrigin::Signed(caller), validator, current_era) + let caller = account("caller", 0, SEED); + let balance_before = T::Currency::free_balance(&validator); + }: _(RawOrigin::Signed(caller), validator.clone(), current_era) + verify { + // Validator has been paid! + let balance_after = T::Currency::free_balance(&validator); + assert!(balance_before < balance_after); + } rebond { - let l in 1 .. 1000; - let (_, controller) = create_stash_controller::(u)?; + let l in 1 .. MAX_UNLOCKING_CHUNKS as u32; + let (_, controller) = create_stash_controller::(u, 100)?; let mut staking_ledger = Ledger::::get(controller.clone()).unwrap(); let unlock_chunk = UnlockChunk::> { value: 1.into(), @@ -269,8 +293,14 @@ benchmarks! { for _ in 0 .. l { staking_ledger.unlocking.push(unlock_chunk.clone()) } - Ledger::::insert(controller.clone(), staking_ledger); - }: _(RawOrigin::Signed(controller), (l + 100).into()) + Ledger::::insert(controller.clone(), staking_ledger.clone()); + let original_bonded: BalanceOf = staking_ledger.active; + }: _(RawOrigin::Signed(controller.clone()), (l + 100).into()) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_bonded: BalanceOf = ledger.active; + assert!(original_bonded < new_bonded); + } set_history_depth { let e in 1 .. 100; @@ -285,19 +315,26 @@ benchmarks! { >::insert(i, BalanceOf::::one()); ErasStartSessionIndex::insert(i, i); } - }: _(RawOrigin::Root, EraIndex::zero()) + }: _(RawOrigin::Root, EraIndex::zero(), u32::max_value()) + verify { + assert_eq!(HistoryDepth::get(), 0); + } reap_stash { - let u in 1 .. 1000; - let (stash, controller) = create_stash_controller::(u)?; + let s in 1 .. MAX_SPANS; + let (stash, controller) = create_stash_controller::(0, 100)?; + add_slashing_spans::(&stash, s); T::Currency::make_free_balance_be(&stash, 0.into()); - }: _(RawOrigin::Signed(controller), stash) + }: _(RawOrigin::Signed(controller), stash.clone(), s) + verify { + assert!(!Bonded::::contains_key(&stash)); + } new_era { let v in 1 .. 10; let n in 1 .. 100; MinimumValidatorCount::put(0); - create_validators_with_nominators_for_era::(v, n)?; + create_validators_with_nominators_for_era::(v, n, MAX_NOMINATIONS, false, None)?; let session_index = SessionIndex::one(); }: { let validators = Staking::::new_era(session_index).ok_or("`new_era` failed")?; @@ -305,8 +342,8 @@ benchmarks! { } do_slash { - let l in 1 .. 1000; - let (stash, controller) = create_stash_controller::(0)?; + let l in 1 .. MAX_UNLOCKING_CHUNKS as u32; + let (stash, controller) = create_stash_controller::(0, 100)?; let mut staking_ledger = Ledger::::get(controller.clone()).unwrap(); let unlock_chunk = UnlockChunk::> { value: 1.into(), @@ -317,6 +354,7 @@ benchmarks! { } Ledger::::insert(controller.clone(), staking_ledger.clone()); let slash_amount = T::Currency::minimum_balance() * 10.into(); + let balance_before = T::Currency::free_balance(&stash); }: { crate::slashing::do_slash::( &stash, @@ -324,13 +362,16 @@ benchmarks! { &mut BalanceOf::::zero(), &mut NegativeImbalanceOf::::zero() ); + } verify { + let balance_after = T::Currency::free_balance(&stash); + assert!(balance_before > balance_after); } payout_all { let v in 1 .. 10; let n in 1 .. 100; MinimumValidatorCount::put(0); - create_validators_with_nominators_for_era::(v, n)?; + create_validators_with_nominators_for_era::(v, n, MAX_NOMINATIONS, false, None)?; // Start a new Era let new_validators = Staking::::new_era(SessionIndex::one()).unwrap(); assert!(new_validators.len() == v as usize); @@ -364,6 +405,198 @@ benchmarks! { call.dispatch(RawOrigin::Signed(caller.clone()).into())?; } } + + // This benchmark create `v` validators intent, `n` nominators intent, each nominator nominate + // MAX_NOMINATIONS in the set of the first `w` validators. + // It builds a solution with `w` winners composed of nominated validators randomly nominated, + // `a` assignment with MAX_NOMINATIONS. + submit_solution_initial { + // number of validator intent + let v in 1000 .. 2000; + // number of nominator intent + let n in 1000 .. 2000; + // number of assignments. Basically, number of active nominators. + let a in 200 .. 500; + // number of winners, also ValidatorCount + let w in 16 .. 100; + + ensure!(w as usize >= MAX_NOMINATIONS, "doesn't support lower value"); + + let winners = create_validators_with_nominators_for_era::( + v, + n, + MAX_NOMINATIONS, + false, + Some(w), + )?; + + // needed for the solution to be generates. + assert!(>::create_stakers_snapshot().0); + + // set number of winners + ValidatorCount::put(w); + + // create a assignments in total for the w winners. + let (winners, assignments) = create_assignments_for_offchain::(a, winners)?; + + let ( + winners, + compact, + score, + size + ) = offchain_election::prepare_submission::(assignments, winners, false).unwrap(); + + // needed for the solution to be accepted + >::put(ElectionStatus::Open(T::BlockNumber::from(1u32))); + + let era = >::current_era().unwrap_or(0); + let caller: T::AccountId = account("caller", n, SEED); + }: { + let result = >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ); + assert!(result.is_ok()); + } + verify { + // new solution has been accepted. + assert_eq!(>::queued_score().unwrap(), score); + } + + // same as submit_solution_initial but we place a very weak solution on chian first. + submit_solution_better { + // number of validator intent + let v in 1000 .. 2000; + // number of nominator intent + let n in 1000 .. 2000; + // number of assignments. Basically, number of active nominators. + let a in 200 .. 500; + // number of winners, also ValidatorCount + let w in 16 .. 100; + + ensure!(w as usize >= MAX_NOMINATIONS, "doesn't support lower value"); + + let winners = create_validators_with_nominators_for_era::( + v, + n, + MAX_NOMINATIONS, + false, + Some(w), + )?; + + // needed for the solution to be generates. + assert!(>::create_stakers_snapshot().0); + + // set number of winners + ValidatorCount::put(w); + + // create a assignments in total for the w winners. + let (winners, assignments) = create_assignments_for_offchain::(a, winners)?; + + let single_winner = winners[0].0.clone(); + + let ( + winners, + compact, + score, + size + ) = offchain_election::prepare_submission::(assignments, winners, false).unwrap(); + + // needed for the solution to be accepted + >::put(ElectionStatus::Open(T::BlockNumber::from(1u32))); + + let era = >::current_era().unwrap_or(0); + let caller: T::AccountId = account("caller", n, SEED); + + // submit a very bad solution on-chain + { + // this is needed to fool the chain to accept this solution. + ValidatorCount::put(1); + let (winners, compact, score, size) = get_single_winner_solution::(single_winner)?; + assert!( + >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ).is_ok()); + + // new solution has been accepted. + assert_eq!(>::queued_score().unwrap(), score); + ValidatorCount::put(w); + } + }: { + let result = >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ); + assert!(result.is_ok()); + } + verify { + // new solution has been accepted. + assert_eq!(>::queued_score().unwrap(), score); + } + + // This will be early rejected based on the score. + submit_solution_weaker { + // number of validator intent + let v in 1000 .. 2000; + // number of nominator intent + let n in 1000 .. 2000; + + MinimumValidatorCount::put(0); + create_validators_with_nominators_for_era::(v, n, MAX_NOMINATIONS, false, None)?; + + // needed for the solution to be generates. + assert!(>::create_stakers_snapshot().0); + + // needed for the solution to be accepted + >::put(ElectionStatus::Open(T::BlockNumber::from(1u32))); + let caller: T::AccountId = account("caller", n, SEED); + let era = >::current_era().unwrap_or(0); + + // submit a seq-phragmen with all the good stuff on chain + { + let (winners, compact, score, size) = get_seq_phragmen_solution::(true); + assert!( + >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ).is_ok() + ); + + // new solution has been accepted. + assert_eq!(>::queued_score().unwrap(), score); + } + + // prepare a bad solution. This will be very early rejected. + let (winners, compact, score, size) = get_weak_solution::(true); + }: { + assert!( + >::submit_election_solution( + RawOrigin::Signed(caller.clone()).into(), + winners, + compact, + score.clone(), + era, + size, + ).is_err() + ); + } } #[cfg(test)] @@ -378,7 +611,8 @@ mod tests { let v = 10; let n = 100; - create_validators_with_nominators_for_era::(v,n).unwrap(); + create_validators_with_nominators_for_era::(v, n, MAX_NOMINATIONS, false, None) + .unwrap(); let count_validators = Validators::::iter().count(); let count_nominators = Nominators::::iter().count(); @@ -395,7 +629,7 @@ mod tests { let validator_stash = create_validator_with_nominators::( n, - MAX_NOMINATIONS as u32, + ::MaxNominatorRewardedPerValidator::get() as u32, ).unwrap(); let current_era = CurrentEra::get().unwrap(); @@ -408,6 +642,35 @@ mod tests { }); } + #[test] + fn add_slashing_spans_works() { + ExtBuilder::default().has_stakers(false).build().execute_with(|| { + let n = 10; + + let validator_stash = create_validator_with_nominators::( + n, + ::MaxNominatorRewardedPerValidator::get() as u32, + ).unwrap(); + + // Add 20 slashing spans + let num_of_slashing_spans = 20; + add_slashing_spans::(&validator_stash, num_of_slashing_spans); + + let slashing_spans = SlashingSpans::::get(&validator_stash).unwrap(); + assert_eq!(slashing_spans.iter().count(), num_of_slashing_spans as usize); + for i in 0 .. num_of_slashing_spans { + assert!(SpanSlash::::contains_key((&validator_stash, i))); + } + + // Test everything is cleaned up + assert_ok!(Staking::kill_stash(&validator_stash, num_of_slashing_spans)); + assert!(SlashingSpans::::get(&validator_stash).is_none()); + for i in 0 .. num_of_slashing_spans { + assert!(!SpanSlash::::contains_key((&validator_stash, i))); + } + }); + } + #[test] fn test_payout_all() { ExtBuilder::default().has_stakers(false).build().execute_with(|| { @@ -432,7 +695,8 @@ mod tests { assert_ok!(test_benchmark_bond::()); assert_ok!(test_benchmark_bond_extra::()); assert_ok!(test_benchmark_unbond::()); - assert_ok!(test_benchmark_withdraw_unbonded::()); + assert_ok!(test_benchmark_withdraw_unbonded_update::()); + assert_ok!(test_benchmark_withdraw_unbonded_kill::()); assert_ok!(test_benchmark_validate::()); assert_ok!(test_benchmark_nominate::()); assert_ok!(test_benchmark_chill::()); @@ -452,6 +716,18 @@ mod tests { assert_ok!(test_benchmark_new_era::()); assert_ok!(test_benchmark_do_slash::()); assert_ok!(test_benchmark_payout_all::()); + // only run one of them to same time on the CI. ignore the other two. + assert_ok!(test_benchmark_submit_solution_initial::()); + }); + } + + #[test] + #[ignore] + fn test_benchmarks_offchain() { + ExtBuilder::default().has_stakers(false).build().execute_with(|| { + assert_ok!(test_benchmark_submit_solution_better::()); + assert_ok!(test_benchmark_submit_solution_weaker::()); }); } + } diff --git a/frame/staking/src/inflation.rs b/frame/staking/src/inflation.rs index 63d008a197c6465b3e937dccf36319842be375d6..04bfc98357a7f4958a8a77da6538a77af9cbee6f 100644 --- a/frame/staking/src/inflation.rs +++ b/frame/staking/src/inflation.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! This module expose one function `P_NPoS` (Payout NPoS) or `compute_total_payout` which returns //! the total payout for the era given the era duration and the staking rate in NPoS. diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 534222ebdfd16ce1b718526cee8472fb7e308f01..535eb4446b70f2080e75c9ab8546294f122f894e 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Staking Module //! @@ -107,7 +108,7 @@ //! Rewards must be claimed for each era before it gets too old by `$HISTORY_DEPTH` using the //! `payout_stakers` call. Any account can call `payout_stakers`, which pays the reward to //! the validator as well as its nominators. -//! Only the [`T::MaxNominatorRewardedPerValidator`] biggest stakers can claim their reward. This +//! Only the [`Trait::MaxNominatorRewardedPerValidator`] biggest stakers can claim their reward. This //! is to limit the i/o cost to mutate storage for each nominator's account. //! //! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is @@ -271,7 +272,7 @@ mod mock; #[cfg(test)] mod tests; -#[cfg(feature = "testing-utils")] +#[cfg(any(feature = "runtime-benchmarks", test))] pub mod testing_utils; #[cfg(any(feature = "runtime-benchmarks", test))] pub mod benchmarking; @@ -289,10 +290,10 @@ use sp_std::{ }; use codec::{HasCompact, Encode, Decode}; use frame_support::{ - decl_module, decl_event, decl_storage, ensure, decl_error, debug, - weights::{Weight, DispatchClass}, + decl_module, decl_event, decl_storage, ensure, decl_error, + weights::{Weight, constants::{WEIGHT_PER_MICROS, WEIGHT_PER_NANOS}}, storage::IterableStorageMap, - dispatch::{IsSubType, DispatchResult}, + dispatch::{IsSubType, DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, traits::{ Currency, LockIdentifier, LockableCurrency, WithdrawReasons, OnUnbalanced, Imbalance, Get, UnixTime, EstimateNextNewSession, EnsureOrigin, @@ -331,13 +332,14 @@ const STAKING_ID: LockIdentifier = *b"staking "; pub const MAX_UNLOCKING_CHUNKS: usize = 32; pub const MAX_NOMINATIONS: usize = ::LIMIT; -// syntactic sugar for logging -#[cfg(feature = "std")] -const LOG_TARGET: &'static str = "staking"; +pub(crate) const LOG_TARGET: &'static str = "staking"; + +// syntactic sugar for logging. +#[macro_export] macro_rules! log { ($level:tt, $patter:expr $(, $values:expr)* $(,)?) => { - debug::native::$level!( - target: LOG_TARGET, + frame_support::debug::$level!( + target: crate::LOG_TARGET, $patter $(, $values)* ) }; @@ -371,7 +373,7 @@ generate_compact_solution_type!(pub GenericCompactAssignments, 16); pub struct ActiveEraInfo { /// Index of era. pub index: EraIndex, - /// Moment of start expresed as millisecond from `$UNIX_EPOCH`. + /// Moment of start expressed as millisecond from `$UNIX_EPOCH`. /// /// Start can be none if start hasn't been set for the era yet, /// Start is set on the first on_finalize of the era to guarantee usage of `Time`. @@ -679,6 +681,22 @@ pub enum ElectionStatus { Open(BlockNumber), } +/// Some indications about the size of the election. This must be submitted with the solution. +/// +/// Note that these values must reflect the __total__ number, not only those that are present in the +/// solution. In short, these should be the same size as the size of the values dumped in +/// `SnapshotValidators` and `SnapshotNominators`. +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, Default)] +pub struct ElectionSize { + /// Number of validators in the snapshot of the current election round. + #[codec(compact)] + pub validators: ValidatorIndex, + /// Number of nominators in the snapshot of the current election round. + #[codec(compact)] + pub nominators: NominatorIndex, +} + + impl ElectionStatus { fn is_open_at(&self, n: BlockNumber) -> bool { *self == Self::Open(n) @@ -742,6 +760,72 @@ impl SessionInterface<::AccountId> for T whe } } +pub mod weight { + use super::*; + + /// All weight notes are pertaining to the case of a better solution, in which we execute + /// the longest code path. + /// Weight: 0 + (0.63 μs * v) + (0.36 μs * n) + (96.53 μs * a ) + (8 μs * w ) with: + /// * v validators in snapshot validators, + /// * n nominators in snapshot nominators, + /// * a assignment in the submitted solution + /// * w winners in the submitted solution + /// + /// State reads: + /// - Initial checks: + /// - ElectionState, CurrentEra, QueuedScore + /// - SnapshotValidators.len() + SnapShotNominators.len() + /// - ValidatorCount + /// - SnapshotValidators + /// - SnapshotNominators + /// - Iterate over nominators: + /// - compact.len() * Nominators(who) + /// - (non_self_vote_edges) * SlashingSpans + /// - For `assignment_ratio_to_staked`: Basically read the staked value of each stash. + /// - (winners.len() + compact.len()) * (Ledger + Bonded) + /// - TotalIssuance (read a gzillion times potentially, but well it is cached.) + /// - State writes: + /// - QueuedElected, QueuedScore + pub fn weight_for_submit_solution( + winners: &Vec, + compact: &CompactAssignments, + size: &ElectionSize, + ) -> Weight { + (630 * WEIGHT_PER_NANOS).saturating_mul(size.validators as Weight) + .saturating_add((360 * WEIGHT_PER_NANOS).saturating_mul(size.nominators as Weight)) + .saturating_add((96 * WEIGHT_PER_MICROS).saturating_mul(compact.len() as Weight)) + .saturating_add((8 * WEIGHT_PER_MICROS).saturating_mul(winners.len() as Weight)) + // Initial checks + .saturating_add(T::DbWeight::get().reads(8)) + // Nominators + .saturating_add(T::DbWeight::get().reads(compact.len() as Weight)) + // SlashingSpans (upper bound for invalid solution) + .saturating_add(T::DbWeight::get().reads(compact.edge_count() as Weight)) + // `assignment_ratio_to_staked` + .saturating_add(T::DbWeight::get().reads(2 * ((winners.len() + compact.len()) as Weight))) + .saturating_add(T::DbWeight::get().reads(1)) + // write queued score and elected + .saturating_add(T::DbWeight::get().writes(2)) + } + + /// Weight of `submit_solution` in case of a correct submission. + /// + /// refund: we charged compact.len() * read(1) for SlashingSpans. A valid solution only reads + /// winners.len(). + pub fn weight_for_correct_submit_solution( + winners: &Vec, + compact: &CompactAssignments, + size: &ElectionSize, + ) -> Weight { + // NOTE: for consistency, we re-compute the original weight to maintain their relation and + // prevent any foot-guns. + let original_weight = weight_for_submit_solution::(winners, compact, size); + original_weight + .saturating_sub(T::DbWeight::get().reads(compact.edge_count() as Weight)) + .saturating_add(T::DbWeight::get().reads(winners.len() as Weight)) + } +} + pub trait Trait: frame_system::Trait + SendTransactionTypes> { /// The staking balance. type Currency: LockableCurrency; @@ -1089,6 +1173,8 @@ decl_event!( OldSlashingReportDiscarded(SessionIndex), /// A new set of stakers was elected with the given computation method. StakingElection(ElectionCompute), + /// A new solution for the upcoming election has been stored. + SolutionStored(ElectionCompute), /// An account has bonded this amount. /// /// NOTE: This event is only emitted when funds are bonded via a dispatchable. Notably, @@ -1162,8 +1248,14 @@ decl_error! { PhragmenBogusEdge, /// The claimed score does not match with the one computed from the data. PhragmenBogusScore, + /// The election size is invalid. + PhragmenBogusElectionSize, /// The call is not allowed at the given time due to restrictions of election period. CallNotAllowed, + /// Incorrect previous history depth input provided. + IncorrectHistoryDepth, + /// Incorrect number of slashing spans provided. + IncorrectSlashingSpans, } } @@ -1185,22 +1277,30 @@ decl_module! { /// worker, if applicable, will execute at the end of the current block, and solutions may /// be submitted. fn on_initialize(now: T::BlockNumber) -> Weight { + let mut consumed_weight = 0; + let mut add_weight = |reads, writes, weight| { + consumed_weight += T::DbWeight::get().reads_writes(reads, writes); + consumed_weight += weight; + }; if // if we don't have any ongoing offchain compute. Self::era_election_status().is_closed() && // either current session final based on the plan, or we're forcing. (Self::is_current_session_final() || Self::will_era_be_forced()) { - if let Some(next_session_change) = T::NextNewSession::estimate_next_new_session(now){ + if let Some(next_session_change) = T::NextNewSession::estimate_next_new_session(now) { if let Some(remaining) = next_session_change.checked_sub(&now) { if remaining <= T::ElectionLookahead::get() && !remaining.is_zero() { // create snapshot. - if Self::create_stakers_snapshot() { + let (did_snapshot, snapshot_weight) = Self::create_stakers_snapshot(); + add_weight(0, 0, snapshot_weight); + if did_snapshot { // Set the flag to make sure we don't waste any compute here in the same era // after we have triggered the offline compute. >::put( ElectionStatus::::Open(now) ); + add_weight(0, 1, 0); log!(info, "💸 Election window is Open({:?}). Snapshot created", now); } else { log!(warn, "💸 Failed to create snapshot at {:?}.", now); @@ -1210,10 +1310,13 @@ decl_module! { } else { log!(warn, "💸 Estimating next session change failed."); } + add_weight(0, 0, T::NextNewSession::weight(now)) } - - // weight - 50_000 + // For `era_election_status`, `is_current_session_final`, `will_era_be_forced` + add_weight(3, 0, 0); + // Additional read from `on_finalize` + add_weight(1, 0, 0); + consumed_weight } /// Check if the current block number is the one at which the election window has been set @@ -1227,7 +1330,7 @@ decl_module! { log!(debug, "skipping offchain worker in open election window due to [{}]", why); } else { if let Err(e) = compute_offchain_election::() { - log!(warn, "💸 Error in phragmen offchain worker: {:?}", e); + log!(error, "💸 Error in phragmen offchain worker: {:?}", e); } else { log!(debug, "Executed offchain worker thread without errors."); } @@ -1241,9 +1344,11 @@ decl_module! { if active_era.start.is_none() { let now_as_millis_u64 = T::UnixTime::now().as_millis().saturated_into::(); active_era.start = Some(now_as_millis_u64); + // This write only ever happens once, we don't include it in the weight in general ActiveEra::put(active_era); } } + // `on_finalize` weight is tracked in `on_initialize` } /// Take the origin account as a stash and lock up `value` of its balance. `controller` will @@ -1262,8 +1367,13 @@ decl_module! { /// /// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned /// unless the `origin` falls below _existential deposit_ and gets removed as dust. + /// ------------------ + /// Base Weight: 67.87 µs + /// DB Weight: + /// - Read: Bonded, Ledger, [Origin Account], Current Era, History Depth, Locks + /// - Write: Bonded, Payee, [Origin Account], Locks, Ledger /// # - #[weight = 500_000_000] + #[weight = 67 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(5, 4)] pub fn bond(origin, controller: ::Source, #[compact] value: BalanceOf, @@ -1326,8 +1436,13 @@ decl_module! { /// - Independent of the arguments. Insignificant complexity. /// - O(1). /// - One DB entry. + /// ------------ + /// Base Weight: 54.88 µs + /// DB Weight: + /// - Read: Era Election Status, Bonded, Ledger, [Origin Account], Locks + /// - Write: [Origin Account], Locks, Ledger /// # - #[weight = 500_000_000] + #[weight = 55 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)] fn bond_extra(origin, #[compact] max_additional: BalanceOf) { ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let stash = ensure_signed(origin)?; @@ -1372,8 +1487,13 @@ decl_module! { /// The only way to clean the aforementioned storage item is also user-controlled via /// `withdraw_unbonded`. /// - One DB entry. + /// ---------- + /// Base Weight: 50.34 µs + /// DB Weight: + /// - Read: Era Election Status, Ledger, Current Era, Locks, [Origin Account] + /// - Write: [Origin Account], Locks, Ledger /// - #[weight = 400_000_000] + #[weight = 50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)] fn unbond(origin, #[compact] value: BalanceOf) { ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; @@ -1420,9 +1540,28 @@ decl_module! { /// indirectly user-controlled. See [`unbond`] for more detail. /// - Contains a limited number of reads, yet the size of which could be large based on `ledger`. /// - Writes are limited to the `origin` account key. + /// --------------- + /// Complexity O(S) where S is the number of slashing spans to remove + /// Base Weight: + /// Update: 50.52 + .028 * S µs + /// - Reads: EraElectionStatus, Ledger, Current Era, Locks, [Origin Account] + /// - Writes: [Origin Account], Locks, Ledger + /// Kill: 79.41 + 2.366 * S µs + /// - Reads: EraElectionStatus, Ledger, Current Era, Bonded, Slashing Spans, [Origin Account], Locks + /// - Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, [Origin Account], Locks + /// - Writes Each: SpanSlash * S + /// NOTE: Weight annotation is the kill scenario, we refund otherwise. /// # - #[weight = 400_000_000] - fn withdraw_unbonded(origin) { + #[weight = T::DbWeight::get().reads_writes(6, 6) + .saturating_add(80 * WEIGHT_PER_MICROS) + .saturating_add( + (2 * WEIGHT_PER_MICROS).saturating_mul(Weight::from(*num_slashing_spans)) + ) + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans))) + // if slashing spans is non-zero, add 1 more write + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans).min(1))) + ] + fn withdraw_unbonded(origin, num_slashing_spans: u32) -> DispatchResultWithPostInfo { ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; let mut ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; @@ -1431,17 +1570,21 @@ decl_module! { ledger = ledger.consolidate_unlocked(current_era) } - if ledger.unlocking.is_empty() && ledger.active.is_zero() { + let post_info_weight = if ledger.unlocking.is_empty() && ledger.active.is_zero() { // This account must have called `unbond()` with some value that caused the active // portion to fall below existential deposit + will have no more unlocking chunks // left. We can now safely remove all staking-related information. - Self::kill_stash(&stash)?; + Self::kill_stash(&stash, num_slashing_spans)?; // remove the lock. T::Currency::remove_lock(STAKING_ID, &stash); + // This is worst case scenario, so we use the full weight and return None + None } else { // This was the consequence of a partial unbond. just update the ledger and move on. Self::update_ledger(&controller, &ledger); - } + // This is only an update, so we use less overall weight + Some(50 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(4, 2)) + }; // `old_total` should never be less than the new total because // `consolidate_unlocked` strictly subtracts balance. @@ -1450,6 +1593,8 @@ decl_module! { let value = old_total - ledger.total; Self::deposit_event(RawEvent::Withdrawn(stash, value)); } + + Ok(post_info_weight.into()) } /// Declare the desire to validate for the origin controller. @@ -1463,8 +1608,13 @@ decl_module! { /// - Independent of the arguments. Insignificant complexity. /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. + /// ----------- + /// Base Weight: 17.13 µs + /// DB Weight: + /// - Read: Era Election Status, Ledger + /// - Write: Nominators, Validators /// # - #[weight = 750_000_000] + #[weight = 17 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(2, 2)] pub fn validate(origin, prefs: ValidatorPrefs) { ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; @@ -1483,11 +1633,20 @@ decl_module! { /// And, it can be only called when [`EraElectionStatus`] is `Closed`. /// /// # - /// - The transaction's complexity is proportional to the size of `targets`, - /// which is capped at CompactAssignments::LIMIT. + /// - The transaction's complexity is proportional to the size of `targets` (N) + /// which is capped at CompactAssignments::LIMIT (MAX_NOMINATIONS). /// - Both the reads and writes follow a similar pattern. + /// --------- + /// Base Weight: 22.34 + .36 * N µs + /// where N is the number of targets + /// DB Weight: + /// - Reads: Era Election Status, Ledger, Current Era + /// - Writes: Validators, Nominators /// # - #[weight = 750_000_000] + #[weight = T::DbWeight::get().reads_writes(3, 2) + .saturating_add(22 * WEIGHT_PER_MICROS) + .saturating_add((360 * WEIGHT_PER_NANOS).saturating_mul(targets.len() as Weight)) + ] pub fn nominate(origin, targets: Vec<::Source>) { ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; @@ -1495,7 +1654,7 @@ decl_module! { let stash = &ledger.stash; ensure!(!targets.is_empty(), Error::::EmptyTargets); let targets = targets.into_iter() - .take(::LIMIT) + .take(MAX_NOMINATIONS) .map(|t| T::Lookup::lookup(t)) .collect::, _>>()?; @@ -1521,8 +1680,13 @@ decl_module! { /// - Independent of the arguments. Insignificant complexity. /// - Contains one read. /// - Writes are limited to the `origin` account key. + /// -------- + /// Base Weight: 16.53 µs + /// DB Weight: + /// - Read: EraElectionStatus, Ledger + /// - Write: Validators, Nominators /// # - #[weight = 500_000_000] + #[weight = 16 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(2, 2)] fn chill(origin) { ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; @@ -1540,8 +1704,13 @@ decl_module! { /// - Independent of the arguments. Insignificant complexity. /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. + /// --------- + /// - Base Weight: 11.33 µs + /// - DB Weight: + /// - Read: Ledger + /// - Write: Payee /// # - #[weight = 500_000_000] + #[weight = 11 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(1, 1)] fn set_payee(origin, payee: RewardDestination) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; @@ -1559,8 +1728,13 @@ decl_module! { /// - Independent of the arguments. Insignificant complexity. /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. + /// ---------- + /// Base Weight: 25.22 µs + /// DB Weight: + /// - Read: Bonded, Ledger New Controller, Ledger Old Controller + /// - Write: Bonded, Ledger New Controller, Ledger Old Controller /// # - #[weight = 750_000_000] + #[weight = 25 * WEIGHT_PER_MICROS + T::DbWeight::get().reads_writes(3, 3)] fn set_controller(origin, controller: ::Source) { let stash = ensure_signed(origin)?; let old_controller = Self::bonded(&stash).ok_or(Error::::NotStash)?; @@ -1576,8 +1750,15 @@ decl_module! { } } - /// The ideal number of validators. - #[weight = 5_000_000] + /// Sets the ideal number of validators. + /// + /// The dispatch origin must be Root. + /// + /// # + /// Base Weight: 1.717 µs + /// Write: Validator Count + /// # + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)] fn set_validator_count(origin, #[compact] new: u32) { ensure_root(origin)?; ValidatorCount::put(new); @@ -1585,10 +1766,14 @@ decl_module! { /// Force there to be no new eras indefinitely. /// + /// The dispatch origin must be Root. + /// /// # /// - No arguments. + /// - Base Weight: 1.857 µs + /// - Write: ForceEra /// # - #[weight = 5_000_000] + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)] fn force_no_eras(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceNone); @@ -1597,29 +1782,62 @@ decl_module! { /// Force there to be a new era at the end of the next session. After this, it will be /// reset to normal (non-forced) behaviour. /// + /// The dispatch origin must be Root. + /// /// # /// - No arguments. + /// - Base Weight: 1.959 µs + /// - Write ForceEra /// # - #[weight = 5_000_000] + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)] fn force_new_era(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceNew); } /// Set the validators who cannot be slashed (if any). - #[weight = 5_000_000] + /// + /// The dispatch origin must be Root. + /// + /// # + /// - O(V) + /// - Base Weight: 2.208 + .006 * V µs + /// - Write: Invulnerables + /// # + #[weight = T::DbWeight::get().writes(1) + .saturating_add(2 * WEIGHT_PER_MICROS) + .saturating_add((6 * WEIGHT_PER_NANOS).saturating_mul(validators.len() as Weight)) + ] fn set_invulnerables(origin, validators: Vec) { ensure_root(origin)?; >::put(validators); } /// Force a current staker to become completely unstaked, immediately. - #[weight = 0] - fn force_unstake(origin, stash: T::AccountId) { + /// + /// The dispatch origin must be Root. + /// + /// # + /// O(S) where S is the number of slashing spans to be removed + /// Base Weight: 53.07 + 2.365 * S µs + /// Reads: Bonded, Slashing Spans, Account, Locks + /// Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, Account, Locks + /// Writes Each: SpanSlash * S + /// # + #[weight = T::DbWeight::get().reads_writes(4, 7) + .saturating_add(53 * WEIGHT_PER_MICROS) + .saturating_add( + WEIGHT_PER_MICROS.saturating_mul(2).saturating_mul(Weight::from(*num_slashing_spans)) + ) + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans))) + // if slashing spans is non-zero, add 1 more write + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans > 0))) + ] + fn force_unstake(origin, stash: T::AccountId, num_slashing_spans: u32) { ensure_root(origin)?; // remove all staking-related information. - Self::kill_stash(&stash)?; + Self::kill_stash(&stash, num_slashing_spans)?; // remove the lock. T::Currency::remove_lock(STAKING_ID, &stash); @@ -1627,23 +1845,36 @@ decl_module! { /// Force there to be a new era at the end of sessions indefinitely. /// + /// The dispatch origin must be Root. + /// /// # - /// - One storage write + /// - Base Weight: 2.05 µs + /// - Write: ForceEra /// # - #[weight = 5_000_000] + #[weight = 2 * WEIGHT_PER_MICROS + T::DbWeight::get().writes(1)] fn force_new_era_always(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceAlways); } - /// Cancel enactment of a deferred slash. Can be called by either the root origin or - /// the `T::SlashCancelOrigin`. - /// passing the era and indices of the slashes for that era to kill. + /// Cancel enactment of a deferred slash. + /// + /// Can be called by either the root origin or the `T::SlashCancelOrigin`. + /// + /// Parameters: era and indices of the slashes for that era to kill. /// /// # - /// - One storage write. + /// Complexity: O(U + S) + /// with U unapplied slashes weighted with U=1000 + /// and S is the number of slash indices to be canceled. + /// - Base: 5870 + 34.61 * S µs + /// - Read: Unapplied Slashes + /// - Write: Unapplied Slashes /// # - #[weight = 1_000_000_000] + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(5_870 * WEIGHT_PER_MICROS) + .saturating_add((35 * WEIGHT_PER_MICROS).saturating_mul(slash_indices.len() as Weight)) + ] fn cancel_deferred_slash(origin, era: EraIndex, slash_indices: Vec) { T::SlashCancelOrigin::try_origin(origin) .map(|_| ()) @@ -1741,8 +1972,23 @@ decl_module! { /// # /// - Time complexity: at most O(MaxNominatorRewardedPerValidator). /// - Contains a limited number of reads and writes. + /// ----------- + /// N is the Number of payouts for the validator (including the validator) + /// Base Weight: 110 + 54.2 * N µs (Median Slopes) + /// DB Weight: + /// - Read: EraElectionStatus, CurrentEra, HistoryDepth, MigrateEra, ErasValidatorReward, + /// ErasStakersClipped, ErasRewardPoints, ErasValidatorPrefs (8 items) + /// - Read Each: Bonded, Ledger, Payee, Locks, System Account (5 items) + /// - Write Each: System Account, Locks, Ledger (3 items) + // TODO: Remove read on Migrate Era /// # - #[weight = 500_000_000] + #[weight = + 110 * WEIGHT_PER_MICROS + + 54 * WEIGHT_PER_MICROS * Weight::from(T::MaxNominatorRewardedPerValidator::get()) + + T::DbWeight::get().reads(8) + + T::DbWeight::get().reads(5) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1) + + T::DbWeight::get().writes(3) * Weight::from(T::MaxNominatorRewardedPerValidator::get() + 1) + ] fn payout_stakers(origin, validator_stash: T::AccountId, era: EraIndex) -> DispatchResult { ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); ensure_signed(origin)?; @@ -1755,11 +2001,21 @@ decl_module! { /// [`EraElectionStatus`] is `Closed`. /// /// # - /// - Time complexity: O(1). Bounded by `MAX_UNLOCKING_CHUNKS`. + /// - Time complexity: O(L), where L is unlocking chunks + /// - Bounded by `MAX_UNLOCKING_CHUNKS`. /// - Storage changes: Can't increase storage, only decrease it. + /// --------------- + /// - Base Weight: 34.51 µs * .048 L µs + /// - DB Weight: + /// - Reads: EraElectionStatus, Ledger, Locks, [Origin Account] + /// - Writes: [Origin Account], Locks, Ledger /// # - #[weight = 500_000_000] - fn rebond(origin, #[compact] value: BalanceOf) { + #[weight = + 35 * WEIGHT_PER_MICROS + + 50 * WEIGHT_PER_NANOS * (MAX_UNLOCKING_CHUNKS as Weight) + + T::DbWeight::get().reads_writes(3, 2) + ] + fn rebond(origin, #[compact] value: BalanceOf) -> DispatchResultWithPostInfo { ensure!(Self::era_election_status().is_closed(), Error::::CallNotAllowed); let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; @@ -1767,13 +2023,44 @@ decl_module! { let ledger = ledger.rebond(value); Self::update_ledger(&controller, &ledger); + Ok(Some( + 35 * WEIGHT_PER_MICROS + + 50 * WEIGHT_PER_NANOS * (ledger.unlocking.len() as Weight) + + T::DbWeight::get().reads_writes(3, 2) + ).into()) } - /// Set history_depth value. + /// Set `HistoryDepth` value. This function will delete any history information + /// when `HistoryDepth` is reduced. + /// + /// Parameters: + /// - `new_history_depth`: The new history depth you would like to set. + /// - `era_items_deleted`: The number of items that will be deleted by this dispatch. + /// This should report all the storage items that will be deleted by clearing old + /// era history. Needed to report an accurate weight for the dispatch. Trusted by + /// `Root` to report an accurate number. /// /// Origin must be root. - #[weight = (500_000_000, DispatchClass::Operational)] - fn set_history_depth(origin, #[compact] new_history_depth: EraIndex) { + /// + /// # + /// - E: Number of history depths removed, i.e. 10 -> 7 = 3 + /// - Base Weight: 29.13 * E µs + /// - DB Weight: + /// - Reads: Current Era, History Depth + /// - Writes: History Depth + /// - Clear Prefix Each: Era Stakers, EraStakersClipped, ErasValidatorPrefs + /// - Writes Each: ErasValidatorReward, ErasRewardPoints, ErasTotalStake, ErasStartSessionIndex + /// # + #[weight = { + let items = Weight::from(*_era_items_deleted); + T::DbWeight::get().reads_writes(2, 1) + .saturating_add(T::DbWeight::get().reads_writes(items, items)) + + }] + fn set_history_depth(origin, + #[compact] new_history_depth: EraIndex, + #[compact] _era_items_deleted: u32, + ) { ensure_root(origin)?; if let Some(current_era) = Self::current_era() { HistoryDepth::mutate(|history_depth| { @@ -1794,10 +2081,27 @@ decl_module! { /// This can be called from any origin. /// /// - `stash`: The stash account to reap. Its balance must be zero. - #[weight = 0] - fn reap_stash(_origin, stash: T::AccountId) { + /// + /// # + /// Complexity: O(S) where S is the number of slashing spans on the account. + /// Base Weight: 75.94 + 2.396 * S µs + /// DB Weight: + /// - Reads: Stash Account, Bonded, Slashing Spans, Locks + /// - Writes: Bonded, Slashing Spans (if S > 0), Ledger, Payee, Validators, Nominators, Stash Account, Locks + /// - Writes Each: SpanSlash * S + /// # + #[weight = T::DbWeight::get().reads_writes(4, 7) + .saturating_add(76 * WEIGHT_PER_MICROS) + .saturating_add( + WEIGHT_PER_MICROS.saturating_mul(2).saturating_mul(Weight::from(*num_slashing_spans)) + ) + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans))) + // if slashing spans is non-zero, add 1 more write + .saturating_add(T::DbWeight::get().writes(Weight::from(*num_slashing_spans).min(1))) + ] + fn reap_stash(_origin, stash: T::AccountId, num_slashing_spans: u32) { ensure!(T::Currency::total_balance(&stash).is_zero(), Error::::FundedTarget); - Self::kill_stash(&stash)?; + Self::kill_stash(&stash, num_slashing_spans)?; T::Currency::remove_lock(STAKING_ID, &stash); } @@ -1846,51 +2150,26 @@ decl_module! { /// minimized (to ensure less variance) /// /// # - /// E: number of edges. m: size of winner committee. n: number of nominators. d: edge degree - /// (16 for now) v: number of on-chain validator candidates. - /// - /// NOTE: given a solution which is reduced, we can enable a new check the ensure `|E| < n + - /// m`. We don't do this _yet_, but our offchain worker code executes it nonetheless. - /// - /// major steps (all done in `check_and_replace_solution`): - /// - /// - Storage: O(1) read `ElectionStatus`. - /// - Storage: O(1) read `PhragmenScore`. - /// - Storage: O(1) read `ValidatorCount`. - /// - Storage: O(1) length read from `SnapshotValidators`. - /// - /// - Storage: O(v) reads of `AccountId` to fetch `snapshot_validators`. - /// - Memory: O(m) iterations to map winner index to validator id. - /// - Storage: O(n) reads `AccountId` to fetch `snapshot_nominators`. - /// - Memory: O(n + m) reads to map index to `AccountId` for un-compact. - /// - /// - Storage: O(e) accountid reads from `Nomination` to read correct nominations. - /// - Storage: O(e) calls into `slashable_balance_of_vote_weight` to convert ratio to staked. - /// - /// - Memory: build_support_map. O(e). - /// - Memory: evaluate_support: O(E). - /// - /// - Storage: O(e) writes to `QueuedElected`. - /// - Storage: O(1) write to `QueuedScore` - /// - /// The weight of this call is 1/10th of the blocks total weight. + /// See `crate::weight` module. /// # - #[weight = 100_000_000_000] + #[weight = weight::weight_for_submit_solution::(winners, compact, size)] pub fn submit_election_solution( origin, winners: Vec, - compact_assignments: CompactAssignments, + compact: CompactAssignments, score: PhragmenScore, era: EraIndex, - ) { + size: ElectionSize, + ) -> DispatchResultWithPostInfo { let _who = ensure_signed(origin)?; Self::check_and_replace_solution( winners, - compact_assignments, + compact, ElectionCompute::Signed, score, era, - )? + size, + ) } /// Unsigned version of `submit_election_solution`. @@ -1898,22 +2177,28 @@ decl_module! { /// Note that this must pass the [`ValidateUnsigned`] check which only allows transactions /// from the local node to be included. In other words, only the block author can include a /// transaction in the block. - #[weight = 100_000_000_000] + /// + /// # + /// See `crate::weight` module. + /// # + #[weight = weight::weight_for_submit_solution::(winners, compact, size)] pub fn submit_election_solution_unsigned( origin, winners: Vec, - compact_assignments: CompactAssignments, + compact: CompactAssignments, score: PhragmenScore, era: EraIndex, - ) { + size: ElectionSize, + ) -> DispatchResultWithPostInfo { ensure_none(origin)?; Self::check_and_replace_solution( winners, - compact_assignments, + compact, ElectionCompute::Unsigned, score, era, - )? + size, + ) // TODO: instead of returning an error, panic. This makes the entire produced block // invalid. // This ensures that block authors will not ever try and submit a solution which is not @@ -1925,6 +2210,7 @@ decl_module! { impl Module { /// The total balance that can be slashed from a stash account as of right now. pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { + // Weight note: consider making the stake accessible through stash. Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default() } @@ -1939,12 +2225,18 @@ impl Module { /// /// This data is used to efficiently evaluate election results. returns `true` if the operation /// is successful. - fn create_stakers_snapshot() -> bool { + pub fn create_stakers_snapshot() -> (bool, Weight) { + let mut consumed_weight = 0; + let mut add_db_reads_writes = |reads, writes| { + consumed_weight += T::DbWeight::get().reads_writes(reads, writes); + }; let validators = >::iter().map(|(v, _)| v).collect::>(); let mut nominators = >::iter().map(|(n, _)| n).collect::>(); let num_validators = validators.len(); let num_nominators = nominators.len(); + add_db_reads_writes((num_validators + num_nominators) as Weight, 0); + if num_validators > MAX_VALIDATORS || num_nominators.saturating_add(num_validators) > MAX_NOMINATORS @@ -1957,14 +2249,15 @@ impl Module { num_nominators, MAX_NOMINATORS, ); - false + (false, consumed_weight) } else { // all validators nominate themselves; nominators.extend(validators.clone()); >::put(validators); >::put(nominators); - true + add_db_reads_writes(0, 2); + (true, consumed_weight) } } @@ -2276,16 +2569,19 @@ impl Module { Forcing::ForceAlways => (), Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (), _ => { - // not forcing, not a new era either. If final, set the flag. - if era_length + 1 >= T::SessionsPerEra::get() { + // Either `ForceNone`, or `NotForcing && era_length < T::SessionsPerEra::get()`. + if era_length + 1 == T::SessionsPerEra::get() { IsCurrentSessionFinal::put(true); + } else if era_length >= T::SessionsPerEra::get() { + // Should only happen when we are ready to trigger an era but we have ForceNone, + // otherwise previous arm would short circuit. + Self::close_election_window(); } return None }, } // new era. - IsCurrentSessionFinal::put(false); Self::new_era(session_index) } else { // Set initial era @@ -2294,19 +2590,24 @@ impl Module { } /// Basic and cheap checks that we perform in validate unsigned, and in the execution. - pub fn pre_dispatch_checks(score: PhragmenScore, era: EraIndex) -> Result<(), Error> { + /// + /// State reads: ElectionState, CurrentEr, QueuedScore. + /// + /// This function does weight refund in case of errors, which is based upon the fact that it is + /// called at the very beginning of the call site's function. + pub fn pre_dispatch_checks(score: PhragmenScore, era: EraIndex) -> DispatchResultWithPostInfo { // discard solutions that are not in-time // check window open ensure!( Self::era_election_status().is_open(), - Error::::PhragmenEarlySubmission, + Error::::PhragmenEarlySubmission.with_weight(T::DbWeight::get().reads(1)), ); // check current era. if let Some(current_era) = Self::current_era() { ensure!( current_era == era, - Error::::PhragmenEarlySubmission, + Error::::PhragmenEarlySubmission.with_weight(T::DbWeight::get().reads(2)), ) } @@ -2314,11 +2615,11 @@ impl Module { if let Some(queued_score) = Self::queued_score() { ensure!( is_score_better(queued_score, score), - Error::::PhragmenWeakSubmission, + Error::::PhragmenWeakSubmission.with_weight(T::DbWeight::get().reads(3)), ) } - Ok(()) + Ok(None.into()) } /// Checks a given solution and if correct and improved, writes it on chain as the queued result @@ -2329,21 +2630,46 @@ impl Module { compute: ElectionCompute, claimed_score: PhragmenScore, era: EraIndex, - ) -> Result<(), Error> { + election_size: ElectionSize, + ) -> DispatchResultWithPostInfo { // Do the basic checks. era, claimed score and window open. Self::pre_dispatch_checks(claimed_score, era)?; + // the weight that we will refund in case of a correct submission. We compute this now + // because the data needed for it will be consumed further down. + let adjusted_weight = weight::weight_for_correct_submit_solution::( + &winners, + &compact_assignments, + &election_size, + ); // Check that the number of presented winners is sane. Most often we have more candidates - // that we need. Then it should be Self::validator_count(). Else it should be all the + // than we need. Then it should be `Self::validator_count()`. Else it should be all the // candidates. - let snapshot_length = >::decode_len() - .map_err(|_| Error::::SnapshotUnavailable)?; + let snapshot_validators_length = >::decode_len() + .map(|l| l as u32) + .ok_or_else(|| Error::::SnapshotUnavailable)?; + + // size of the solution must be correct. + ensure!( + snapshot_validators_length == u32::from(election_size.validators), + Error::::PhragmenBogusElectionSize, + ); // check the winner length only here and when we know the length of the snapshot validators // length. - let desired_winners = Self::validator_count().min(snapshot_length as u32); + let desired_winners = Self::validator_count().min(snapshot_validators_length); ensure!(winners.len() as u32 == desired_winners, Error::::PhragmenBogusWinnerCount); + let snapshot_nominators_len = >::decode_len() + .map(|l| l as u32) + .ok_or_else(|| Error::::SnapshotUnavailable)?; + + // rest of the size of the solution must be correct. + ensure!( + snapshot_nominators_len == election_size.nominators, + Error::::PhragmenBogusElectionSize, + ); + // decode snapshot validators. let snapshot_validators = Self::snapshot_validators() .ok_or(Error::::SnapshotUnavailable)?; @@ -2357,7 +2683,7 @@ impl Module { }).collect::, Error>>()?; // decode the rest of the snapshot. - let snapshot_nominators = >::snapshot_nominators() + let snapshot_nominators = Self::snapshot_nominators() .ok_or(Error::::SnapshotUnavailable)?; // helpers @@ -2391,7 +2717,7 @@ impl Module { // have bigger problems. log!(error, "💸 detected an error in the staking locking and snapshot."); // abort. - return Err(Error::::PhragmenBogusNominator); + return Err(Error::::PhragmenBogusNominator.into()); } if !is_validator { @@ -2408,14 +2734,14 @@ impl Module { // each target in the provided distribution must be actually nominated by the // nominator after the last non-zero slash. if nomination.targets.iter().find(|&tt| tt == t).is_none() { - return Err(Error::::PhragmenBogusNomination); + return Err(Error::::PhragmenBogusNomination.into()); } if ::SlashingSpans::get(&t).map_or( false, |spans| nomination.submitted_in < spans.last_nonzero_slash(), ) { - return Err(Error::::PhragmenSlashedNomination); + return Err(Error::::PhragmenSlashedNomination.into()); } } } else { @@ -2455,8 +2781,9 @@ impl Module { let exposures = Self::collect_exposure(supports); log!( info, - "💸 A better solution (with compute {:?}) has been validated and stored on chain.", + "💸 A better solution (with compute {:?} and score {:?}) has been validated and stored on chain.", compute, + submitted_score, ); // write new results. @@ -2467,8 +2794,10 @@ impl Module { }); QueuedScore::put(submitted_score); - Ok(()) + // emit event. + Self::deposit_event(RawEvent::SolutionStored(compute)); + Ok(Some(adjusted_weight).into()) } /// Start a session potentially starting an era. @@ -2586,6 +2915,17 @@ impl Module { maybe_new_validators } + + /// Remove all the storage items associated with the election. + fn close_election_window() { + // Close window. + >::put(ElectionStatus::Closed); + // Kill snapshots. + Self::kill_stakers_snapshot(); + // Don't track final session. + IsCurrentSessionFinal::put(false); + } + /// Select the new validator set at the end of the era. /// /// Runs [`try_do_phragmen`] and updates the following storage items: @@ -2607,11 +2947,8 @@ impl Module { exposures, compute, }) = Self::try_do_phragmen() { - // We have chosen the new validator set. Submission is no longer allowed. - >::put(ElectionStatus::Closed); - - // kill the snapshots. - Self::kill_stakers_snapshot(); + // Totally close the election round and data. + Self::close_election_window(); // Populate Stakers and write slot stake. let mut total_stake: BalanceOf = Zero::zero(); @@ -2772,7 +3109,7 @@ impl Module { supports.into_iter().map(|(validator, support)| { // build `struct exposure` from `support` - let mut others = Vec::new(); + let mut others = Vec::with_capacity(support.voters.len()); let mut own: BalanceOf = Zero::zero(); let mut total: BalanceOf = Zero::zero(); support.voters @@ -2804,16 +3141,18 @@ impl Module { /// This is called: /// - after a `withdraw_unbond()` call that frees all of a stash's bonded balance. /// - through `reap_stash()` if the balance has fallen to zero (through slashing). - fn kill_stash(stash: &T::AccountId) -> DispatchResult { - let controller = Bonded::::take(stash).ok_or(Error::::NotStash)?; + fn kill_stash(stash: &T::AccountId, num_slashing_spans: u32) -> DispatchResult { + let controller = Bonded::::get(stash).ok_or(Error::::NotStash)?; + + slashing::clear_stash_metadata::(stash, num_slashing_spans)?; + + Bonded::::remove(stash); >::remove(&controller); >::remove(stash); >::remove(stash); >::remove(stash); - slashing::clear_stash_metadata::(stash); - system::Module::::dec_ref(stash); Ok(()) @@ -2992,7 +3331,9 @@ impl Convert> } /// This is intended to be used with `FilterHistoricalOffences`. -impl OnOffenceHandler> for Module where +impl + OnOffenceHandler, Weight> +for Module where T: pallet_session::Trait::AccountId>, T: pallet_session::historical::Trait< FullIdentification = Exposure<::AccountId, BalanceOf>, @@ -3000,24 +3341,32 @@ impl OnOffenceHandler, T::SessionHandler: pallet_session::SessionHandler<::AccountId>, T::SessionManager: pallet_session::SessionManager<::AccountId>, - T::ValidatorIdOf: Convert<::AccountId, Option<::AccountId>> + T::ValidatorIdOf: Convert< + ::AccountId, + Option<::AccountId>, + >, { fn on_offence( offenders: &[OffenceDetails>], slash_fraction: &[Perbill], slash_session: SessionIndex, - ) -> Result<(), ()> { + ) -> Result { if !Self::can_report() { return Err(()) } let reward_proportion = SlashRewardFraction::get(); + let mut consumed_weight: Weight = 0; + let mut add_db_reads_writes = |reads, writes| { + consumed_weight += T::DbWeight::get().reads_writes(reads, writes); + }; let active_era = { let active_era = Self::active_era(); + add_db_reads_writes(1, 0); if active_era.is_none() { // this offence need not be re-submitted. - return Ok(()) + return Ok(consumed_weight) } active_era.expect("value checked not to be `None`; qed").index }; @@ -3026,6 +3375,7 @@ impl OnOffenceHandler OnOffenceHandler return Ok(()), // before bonding period. defensive - should be filtered out. Some(&(ref slash_era, _)) => *slash_era, + // before bonding period. defensive - should be filtered out. + None => return Ok(consumed_weight), } }; @@ -3048,14 +3400,18 @@ impl OnOffenceHandler OnOffenceHandler(unapplied); + { + let slash_cost = (6, 5); + let reward_cost = (2, 2); + add_db_reads_writes( + (1 + nominators_len) * slash_cost.0 + reward_cost.0 * reporters_len, + (1 + nominators_len) * slash_cost.1 + reward_cost.1 * reporters_len + ); + } } else { // defer to end of some `slash_defer_duration` from now. ::UnappliedSlashes::mutate( active_era, move |for_later| for_later.push(unapplied), ); + add_db_reads_writes(1, 1); } + } else { + add_db_reads_writes(4 /* fetch_spans */, 5 /* kick_out_if_recent */) } } - Ok(()) + Ok(consumed_weight) } fn can_report() -> bool { @@ -3119,12 +3494,6 @@ impl ReportOffence } } -impl From> for InvalidTransaction { - fn from(e: Error) -> Self { - InvalidTransaction::Custom(e.as_u8()) - } -} - #[allow(deprecated)] impl frame_support::unsigned::ValidateUnsigned for Module { type Call = Call; @@ -3134,8 +3503,10 @@ impl frame_support::unsigned::ValidateUnsigned for Module { _, score, era, + _, ) = call { use offchain_election::DEFAULT_LONGEVITY; + use sp_runtime::DispatchError; // discard solution not coming from the local OCW. match source { @@ -3146,9 +3517,18 @@ impl frame_support::unsigned::ValidateUnsigned for Module { } } - if let Err(e) = Self::pre_dispatch_checks(*score, *era) { - log!(debug, "validate unsigned pre dispatch checks failed due to {:?}.", e); - return InvalidTransaction::from(e).into(); + if let Err(error_with_post_info) = Self::pre_dispatch_checks(*score, *era) { + let error = error_with_post_info.error; + let error_number = match error { + DispatchError::Module { error, ..} => error, + _ => 0, + }; + log!( + debug, + "validate unsigned pre dispatch checks failed due to module error #{:?}.", + error, + ); + return InvalidTransaction::Custom(error_number).into(); } log!(debug, "validateUnsigned succeeded for a solution at era {}.", era); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 21400b0b8d4c2fe5c1bb30810f6b6fe58518e0f9..094ab6375ca0e48d5326a8d23e0180f9a46c7c2f 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test utilities @@ -27,7 +28,7 @@ use frame_support::{ assert_ok, impl_outer_origin, parameter_types, impl_outer_dispatch, impl_outer_event, StorageValue, StorageMap, StorageDoubleMap, IterableStorageMap, traits::{Currency, Get, FindAuthor, OnFinalize, OnInitialize}, - weights::Weight, + weights::{Weight, constants::RocksDbWeight}, }; use sp_io; use sp_phragmen::{ @@ -36,7 +37,7 @@ use sp_phragmen::{ }; use crate::*; -const INIT_TIMESTAMP: u64 = 30_000; +pub const INIT_TIMESTAMP: u64 = 30_000; /// The AccountId alias in this test module. pub(crate) type AccountId = u64; @@ -211,9 +212,10 @@ impl frame_system::Trait for Test { type Event = MetaEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); + type DbWeight = RocksDbWeight; type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -473,7 +475,7 @@ impl ExtBuilder { (41, balance_factor * 2000), (100, 2000 * balance_factor), (101, 2000 * balance_factor), - // This allow us to have a total_payout different from 0. + // This allows us to have a total_payout different from 0. (999, 1_000_000_000_000), ], }.assimilate_storage(&mut storage); @@ -763,6 +765,18 @@ pub(crate) fn on_offence_now( on_offence_in_era(offenders, slash_fraction, now) } +pub(crate) fn add_slash(who: &AccountId) { + on_offence_now( + &[ + OffenceDetails { + offender: (who.clone(), Staking::eras_stakers(Staking::active_era().unwrap().index, who.clone())), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); +} + // winners will be chosen by simply their unweighted total backing stake. Nominator stake is // distributed evenly. pub(crate) fn horrible_phragmen_with_post_processing( @@ -1035,3 +1049,7 @@ pub(crate) fn staking_events() -> Vec> { } }).collect() } + +pub(crate) fn balances(who: &AccountId) -> (Balance, Balance) { + (Balances::free_balance(who), Balances::reserved_balance(who)) +} diff --git a/frame/staking/src/offchain_election.rs b/frame/staking/src/offchain_election.rs index 2568638319394e45f72bdc844c790bd86bf3fad8..ce9b77aef7c62fb0c0771bf6482ddc1edeec470f 100644 --- a/frame/staking/src/offchain_election.rs +++ b/frame/staking/src/offchain_election.rs @@ -1,24 +1,26 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Helpers for offchain worker election. use codec::Decode; use crate::{ Call, CompactAssignments, Module, NominatorIndex, OffchainAccuracy, Trait, ValidatorIndex, + ElectionSize, }; use frame_system::offchain::SubmitTransaction; use sp_phragmen::{ @@ -27,7 +29,7 @@ use sp_phragmen::{ }; use sp_runtime::offchain::storage::StorageValueRef; use sp_runtime::{PerThing, RuntimeDebug, traits::{TrailingZeroInput, Zero}}; -use frame_support::{debug, traits::Get}; +use frame_support::traits::Get; use sp_std::{convert::TryInto, prelude::*}; /// Error types related to the offchain election machinery. @@ -112,7 +114,7 @@ pub(crate) fn compute_offchain_election() -> Result<(), OffchainElecti .ok_or(OffchainElectionError::ElectionFailed)?; // process and prepare it for submission. - let (winners, compact, score) = prepare_submission::(assignments, winners, true)?; + let (winners, compact, score, size) = prepare_submission::(assignments, winners, true)?; // defensive-only: current era can never be none except genesis. let current_era = >::current_era().unwrap_or_default(); @@ -123,12 +125,14 @@ pub(crate) fn compute_offchain_election() -> Result<(), OffchainElecti compact, score, current_era, + size, ).into(); SubmitTransaction::>::submit_unsigned_transaction(call) .map_err(|_| OffchainElectionError::PoolSubmissionFailed) } + /// Takes a phragmen result and spits out some data that can be submitted to the chain. /// /// This does a lot of stuff; read the inline comments. @@ -136,7 +140,12 @@ pub fn prepare_submission( assignments: Vec>, winners: Vec<(T::AccountId, ExtendedBalance)>, do_reduce: bool, -) -> Result<(Vec, CompactAssignments, PhragmenScore), OffchainElectionError> where +) -> Result<( + Vec, + CompactAssignments, + PhragmenScore, + ElectionSize, +), OffchainElectionError> where ExtendedBalance: From<::Inner>, { // make sure that the snapshot is available. @@ -234,12 +243,18 @@ pub fn prepare_submission( } } - debug::native::debug!( - target: "staking", + // both conversions are safe; snapshots are not created if they exceed. + let size = ElectionSize { + validators: snapshot_validators.len() as ValidatorIndex, + nominators: snapshot_nominators.len() as NominatorIndex, + }; + + crate::log!( + info, "prepared solution after {} equalization iterations with score {:?}", iterations_executed, score, ); - Ok((winners_indexed, compact, score)) + Ok((winners_indexed, compact, score, size)) } diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs index 26f0828989d733bfc720de288f33f0efcafd462d..4e43b754b8e377659e3ba30a468a279bdb2fb8db 100644 --- a/frame/staking/src/slashing.rs +++ b/frame/staking/src/slashing.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A slashing implementation for NPoS systems. //! @@ -50,11 +51,11 @@ use super::{ EraIndex, Trait, Module, Store, BalanceOf, Exposure, Perbill, SessionInterface, - NegativeImbalanceOf, UnappliedSlash, + NegativeImbalanceOf, UnappliedSlash, Error, }; -use sp_runtime::{traits::{Zero, Saturating}, RuntimeDebug}; +use sp_runtime::{traits::{Zero, Saturating}, RuntimeDebug, DispatchResult}; use frame_support::{ - StorageMap, StorageDoubleMap, + StorageMap, StorageDoubleMap, ensure, traits::{Currency, OnUnbalanced, Imbalance}, }; use sp_std::vec::Vec; @@ -100,7 +101,7 @@ pub struct SlashingSpans { impl SlashingSpans { // creates a new record of slashing spans for a stash, starting at the beginning // of the bonding period, relative to now. - fn new(window_start: EraIndex) -> Self { + pub(crate) fn new(window_start: EraIndex) -> Self { SlashingSpans { span_index: 0, last_start: window_start, @@ -115,7 +116,7 @@ impl SlashingSpans { // update the slashing spans to reflect the start of a new span at the era after `now` // returns `true` if a new span was started, `false` otherwise. `false` indicates // that internal state is unchanged. - fn end_span(&mut self, now: EraIndex) -> bool { + pub(crate) fn end_span(&mut self, now: EraIndex) -> bool { let next_start = now + 1; if next_start <= self.last_start { return false } @@ -547,12 +548,19 @@ pub(crate) fn clear_era_metadata(obsolete_era: EraIndex) { } /// Clear slashing metadata for a dead account. -pub(crate) fn clear_stash_metadata(stash: &T::AccountId) { - let spans = match as Store>::SlashingSpans::take(stash) { - None => return, +pub(crate) fn clear_stash_metadata( + stash: &T::AccountId, + num_slashing_spans: u32, +) -> DispatchResult { + let spans = match as Store>::SlashingSpans::get(stash) { + None => return Ok(()), Some(s) => s, }; + ensure!(num_slashing_spans as usize >= spans.iter().count(), Error::::IncorrectSlashingSpans); + + as Store>::SlashingSpans::remove(stash); + // kill slashing-span metadata for account. // // this can only happen while the account is staked _if_ they are completely slashed. @@ -561,6 +569,8 @@ pub(crate) fn clear_stash_metadata(stash: &T::AccountId) { for span in spans.iter() { as Store>::SpanSlash::remove(&(stash.clone(), span.index)); } + + Ok(()) } // apply the slash to a stash account, deducting any missing funds from the reward diff --git a/frame/staking/src/testing_utils.rs b/frame/staking/src/testing_utils.rs index ede14c8cf733a944999511b2e923f8dd023f3642..2a38f47f4e8da7e659a280274fe2fe63f64818e1 100644 --- a/frame/staking/src/testing_utils.rs +++ b/frame/staking/src/testing_utils.rs @@ -1,155 +1,144 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Testing utils for staking. Needs the `testing-utils` feature to be enabled. -//! -//! Note that these helpers should NOT be used with the actual crate tests, but are rather designed -//! for when the module is being externally tested (i.e. fuzzing, benchmarking, e2e tests). Enabling -//! this feature in the current crate's Cargo.toml will leak all of this into a normal release -//! build. Just don't do it. +//! Testing utils for staking. Provides some common functions to setup staking state, such as +//! bonding validators, nominators, and generating different types of solutions. use crate::*; -use codec::{Decode, Encode}; -use frame_support::assert_ok; +use crate::Module as Staking; +use frame_benchmarking::{account}; use frame_system::RawOrigin; -use pallet_indices::address::Address; -use rand::Rng; -use sp_core::hashing::blake2_256; -use sp_phragmen::{ - build_support_map, evaluate_support, reduce, Assignment, PhragmenScore, StakedAssignment, -}; - -const CTRL_PREFIX: u32 = 1000; -const NOMINATOR_PREFIX: u32 = 1_000_000; - -/// A dummy suer. -pub const USER: u32 = 999_999_999; - -/// Address type of the `T` -pub type AddressOf = Address<::AccountId, u32>; - -/// Random number in the range `[a, b]`. -pub fn random(a: u32, b: u32) -> u32 { - rand::thread_rng().gen_range(a, b) -} - -/// Set the desired validator count, with related storage items. -pub fn set_validator_count(to_elect: u32) { - ValidatorCount::put(to_elect); - MinimumValidatorCount::put(to_elect / 2); - >::put(ElectionStatus::Closed); +use sp_io::hashing::blake2_256; +use rand_chacha::{rand_core::{RngCore, SeedableRng}, ChaChaRng}; +use sp_phragmen::*; + +const SEED: u32 = 0; + +/// Grab a funded user. +pub fn create_funded_user(string: &'static str, n: u32, balance_factor: u32) -> T::AccountId { + let user = account(string, n, SEED); + let balance = T::Currency::minimum_balance() * balance_factor.into(); + T::Currency::make_free_balance_be(&user, balance); + // ensure T::CurrencyToVote will work correctly. + T::Currency::issue(balance); + user } -/// Build an account with the given index. -pub fn account(index: u32) -> T::AccountId { - let entropy = (b"benchmark/staking", index).using_encoded(blake2_256); - T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() +/// Create a stash and controller pair. +pub fn create_stash_controller(n: u32, balance_factor: u32) + -> Result<(T::AccountId, T::AccountId), &'static str> +{ + let stash = create_funded_user::("stash", n, balance_factor); + let controller = create_funded_user::("controller", n, balance_factor); + let controller_lookup: ::Source = T::Lookup::unlookup(controller.clone()); + let reward_destination = RewardDestination::Staked; + let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into(); + Staking::::bond(RawOrigin::Signed(stash.clone()).into(), controller_lookup, amount, reward_destination)?; + return Ok((stash, controller)) } -/// Build an address given Index -pub fn address(index: u32) -> AddressOf { - pallet_indices::address::Address::Id(account::(index)) +/// create `max` validators. +pub fn create_validators( + max: u32, + balance_factor: u32, +) -> Result::Source>, &'static str> { + let mut validators: Vec<::Source> = Vec::with_capacity(max as usize); + for i in 0 .. max { + let (stash, controller) = create_stash_controller::(i, balance_factor)?; + let validator_prefs = ValidatorPrefs { + commission: Perbill::from_percent(50), + }; + Staking::::validate(RawOrigin::Signed(controller).into(), validator_prefs)?; + let stash_lookup: ::Source = T::Lookup::unlookup(stash); + validators.push(stash_lookup); + } + Ok(validators) } -/// Generate signed origin from `who`. -pub fn signed(who: T::AccountId) -> T::Origin { - RawOrigin::Signed(who).into() -} +/// This function generates validators and nominators who are randomly nominating +/// `edge_per_nominator` random validators (until `to_nominate` if provided). +/// +/// Parameters: +/// - `validators`: number of bonded validators +/// - `nominators`: number of bonded nominators. +/// - `edge_per_nominator`: number of edge (vote) per nominator. +/// - `randomize_stake`: whether to randomize the stakes. +/// - `to_nominate`: if `Some(n)`, only the first `n` bonded validator are voted upon. +/// Else, all of them are considered and `edge_per_nominator` random validators are voted for. +/// +/// Return the validators choosen to be nominated. +pub fn create_validators_with_nominators_for_era( + validators: u32, + nominators: u32, + edge_per_nominator: usize, + randomize_stake: bool, + to_nominate: Option, +) -> Result::Source>, &'static str> { + let mut validators_stash: Vec<::Source> + = Vec::with_capacity(validators as usize); + let mut rng = ChaChaRng::from_seed(SEED.using_encoded(blake2_256)); + + // Create validators + for i in 0 .. validators { + let balance_factor = if randomize_stake { rng.next_u32() % 255 + 10 } else { 100u32 }; + let (v_stash, v_controller) = create_stash_controller::(i, balance_factor)?; + let validator_prefs = ValidatorPrefs { + commission: Perbill::from_percent(50), + }; + Staking::::validate(RawOrigin::Signed(v_controller.clone()).into(), validator_prefs)?; + let stash_lookup: ::Source = T::Lookup::unlookup(v_stash.clone()); + validators_stash.push(stash_lookup.clone()); + } -/// Generate signed origin from `index`. -pub fn signed_account(index: u32) -> T::Origin { - signed::(account::(index)) -} + let to_nominate = to_nominate.unwrap_or(validators_stash.len() as u32) as usize; + let validator_choosen = validators_stash[0..to_nominate].to_vec(); + + // Create nominators + for j in 0 .. nominators { + let balance_factor = if randomize_stake { rng.next_u32() % 255 + 10 } else { 100u32 }; + let (_n_stash, n_controller) = create_stash_controller::( + u32::max_value() - j, + balance_factor, + )?; + + // Have them randomly validate + let mut available_validators = validator_choosen.clone(); + let mut selected_validators: Vec<::Source> = + Vec::with_capacity(edge_per_nominator); + + for _ in 0 .. validators.min(edge_per_nominator as u32) { + let selected = rng.next_u32() as usize % available_validators.len(); + let validator = available_validators.remove(selected); + selected_validators.push(validator); + } + Staking::::nominate(RawOrigin::Signed(n_controller.clone()).into(), selected_validators)?; + } -/// Bond a validator. -pub fn bond_validator(stash: T::AccountId, ctrl: u32, val: BalanceOf) -where - T::Lookup: StaticLookup>, -{ - let _ = T::Currency::make_free_balance_be(&stash, val); - assert_ok!(>::bond( - signed::(stash), - address::(ctrl), - val, - RewardDestination::Controller - )); - assert_ok!(>::validate( - signed_account::(ctrl), - ValidatorPrefs::default() - )); -} + ValidatorCount::put(validators); -pub fn bond_nominator( - stash: T::AccountId, - ctrl: u32, - val: BalanceOf, - target: Vec>, -) where - T::Lookup: StaticLookup>, -{ - let _ = T::Currency::make_free_balance_be(&stash, val); - assert_ok!(>::bond( - signed::(stash), - address::(ctrl), - val, - RewardDestination::Controller - )); - assert_ok!(>::nominate(signed_account::(ctrl), target)); + Ok(validator_choosen) } -/// Bond `nun_validators` validators and `num_nominator` nominators with `edge_per_voter` random -/// votes per nominator. -pub fn setup_chain_stakers(num_validators: u32, num_voters: u32, edge_per_voter: u32) -where - T::Lookup: StaticLookup>, -{ - (0..num_validators).for_each(|i| { - bond_validator::( - account::(i), - i + CTRL_PREFIX, - >::from(random(1, 1000)) * T::Currency::minimum_balance(), - ); - }); - - (0..num_voters).for_each(|i| { - let mut targets: Vec> = Vec::with_capacity(edge_per_voter as usize); - let mut all_targets = (0..num_validators) - .map(|t| address::(t)) - .collect::>(); - assert!(num_validators >= edge_per_voter); - (0..edge_per_voter).for_each(|_| { - let target = all_targets.remove(random(0, all_targets.len() as u32 - 1) as usize); - targets.push(target); - }); - bond_nominator::( - account::(i + NOMINATOR_PREFIX), - i + NOMINATOR_PREFIX + CTRL_PREFIX, - >::from(random(1, 1000)) * T::Currency::minimum_balance(), - targets, - ); - }); - - >::create_stakers_snapshot(); -} /// Build a _really bad_ but acceptable solution for election. This should always yield a solution /// which has a less score than the seq-phragmen. pub fn get_weak_solution( do_reduce: bool, -) -> (Vec, CompactAssignments, PhragmenScore) { +) -> (Vec, CompactAssignments, PhragmenScore, ElectionSize) { let mut backing_stake_of: BTreeMap> = BTreeMap::new(); // self stake @@ -158,68 +147,19 @@ pub fn get_weak_solution( >::slashable_balance_of(&who) }); - // add nominator stuff - >::iter().for_each(|(who, nomination)| { - nomination.targets.into_iter().for_each(|v| { - *backing_stake_of.entry(v).or_insert(Zero::zero()) += - >::slashable_balance_of(&who) - }) - }); - - // elect winners + // elect winners. We chose the.. least backed ones. let mut sorted: Vec = backing_stake_of.keys().cloned().collect(); sorted.sort_by_key(|x| backing_stake_of.get(x).unwrap()); let winners: Vec = sorted .iter() + .rev() .cloned() .take(>::validator_count() as usize) .collect(); let mut staked_assignments: Vec> = Vec::new(); - >::iter().for_each(|(who, nomination)| { - let mut dist: Vec<(T::AccountId, ExtendedBalance)> = Vec::new(); - nomination.targets.into_iter().for_each(|v| { - if winners.iter().find(|&w| *w == v).is_some() { - dist.push((v, ExtendedBalance::zero())); - } - }); - - if dist.len() == 0 { - return; - } - - // assign real stakes. just split the stake. - let stake = , u64>>::convert( - >::slashable_balance_of(&who), - ) as ExtendedBalance; - - let mut sum: ExtendedBalance = Zero::zero(); - let dist_len = dist.len() as ExtendedBalance; - - // assign main portion - // only take the first half into account. This should highly imbalance stuff, which is good. - dist.iter_mut() - .take(if dist_len > 1 { - (dist_len as usize) / 2 - } else { - 1 - }) - .for_each(|(_, w)| { - let partial = stake / dist_len; - *w = partial; - sum += partial; - }); - - // assign the leftover to last. - let leftover = stake - sum; - let last = dist.last_mut().unwrap(); - last.1 += leftover; - - staked_assignments.push(StakedAssignment { - who, - distribution: dist, - }); - }); + // you could at this point start adding some of the nominator's stake, but for now we don't. + // This solution must be bad. // add self support to winners. winners.iter().for_each(|w| { @@ -254,10 +194,10 @@ pub fn get_weak_solution( .position(|x| x == a) .and_then(|i| >::try_into(i).ok()) }; - let stake_of = |who: &T::AccountId| -> ExtendedBalance { + let stake_of = |who: &T::AccountId| -> VoteWeight { , u64>>::convert( >::slashable_balance_of(who), - ) as ExtendedBalance + ) }; // convert back to ratio assignment. This takes less space. @@ -269,13 +209,10 @@ pub fn get_weak_solution( // re-calculate score based on what the chain will decode. let score = { - let staked: Vec> = low_accuracy_assignment - .iter() - .map(|a| { - let stake = stake_of(&a.who); - a.clone().into_staked(stake, true) - }) - .collect(); + let staked = assignment_ratio_to_staked::<_, OffchainAccuracy, _>( + low_accuracy_assignment.clone(), + stake_of + ); let (support_map, _) = build_support_map::(winners.as_slice(), staked.as_slice()); @@ -303,14 +240,19 @@ pub fn get_weak_solution( }) .collect::>(); - (winners, compact, score) + let size = ElectionSize { + validators: snapshot_validators.len() as ValidatorIndex, + nominators: snapshot_nominators.len() as NominatorIndex, + }; + + (winners, compact, score, size) } /// Create a solution for seq-phragmen. This uses the same internal function as used by the offchain /// worker code. pub fn get_seq_phragmen_solution( do_reduce: bool, -) -> (Vec, CompactAssignments, PhragmenScore) { +) -> (Vec, CompactAssignments, PhragmenScore, ElectionSize) { let sp_phragmen::PhragmenResult { winners, assignments, @@ -319,29 +261,40 @@ pub fn get_seq_phragmen_solution( offchain_election::prepare_submission::(assignments, winners, do_reduce).unwrap() } -/// Remove all validator, nominators, votes and exposures. -pub fn clean(era: EraIndex) - where - ::AccountId: codec::EncodeLike, - u32: codec::EncodeLike, -{ - >::iter().for_each(|(k, _)| { - let ctrl = >::bonded(&k).unwrap(); - >::remove(&k); - >::remove(&k); - >::remove(&ctrl); - >::remove(k, era); - }); - >::iter().for_each(|(k, _)| >::remove(k)); - >::remove_all(); - >::remove_all(); - >::kill(); - QueuedScore::kill(); +/// Returns a solution in which only one winner is elected with just a self vote. +pub fn get_single_winner_solution( + winner: T::AccountId +) -> Result<(Vec, CompactAssignments, PhragmenScore, ElectionSize), &'static str> { + let snapshot_validators = >::snapshot_validators().unwrap(); + let snapshot_nominators = >::snapshot_nominators().unwrap(); + + let val_index = snapshot_validators.iter().position(|x| *x == winner).ok_or("not a validator")?; + let nom_index = snapshot_nominators.iter().position(|x| *x == winner).ok_or("not a nominator")?; + + let stake = >::slashable_balance_of(&winner); + let stake = , VoteWeight>>::convert(stake) + as ExtendedBalance; + + let val_index = val_index as ValidatorIndex; + let nom_index = nom_index as NominatorIndex; + + let winners = vec![val_index]; + let compact = CompactAssignments { + votes1: vec![(nom_index, val_index)], + ..Default::default() + }; + let score = [stake, stake, stake * stake]; + let size = ElectionSize { + validators: snapshot_validators.len() as ValidatorIndex, + nominators: snapshot_nominators.len() as NominatorIndex, + }; + + Ok((winners, compact, score, size)) } /// get the active era. -pub fn active_era() -> EraIndex { - >::active_era().unwrap().index +pub fn current_era() -> EraIndex { + >::current_era().unwrap_or(0) } /// initialize the first era. @@ -351,3 +304,33 @@ pub fn init_active_era() { start: None, }) } + +/// Create random assignments for the given list of winners. Each assignment will have +/// MAX_NOMINATIONS edges. +pub fn create_assignments_for_offchain( + num_assignments: u32, + winners: Vec<::Source>, +) -> Result< + ( + Vec<(T::AccountId, ExtendedBalance)>, + Vec>, + ), + &'static str +> { + let ratio = OffchainAccuracy::from_rational_approximation(1, MAX_NOMINATIONS); + let assignments: Vec> = >::iter() + .take(num_assignments as usize) + .map(|(n, t)| Assignment { + who: n, + distribution: t.targets.iter().map(|v| (v.clone(), ratio)).collect(), + }) + .collect(); + + ensure!(assignments.len() == num_assignments as usize, "must bench for `a` assignments"); + + let winners = winners.into_iter().map(|v| { + (::lookup(v).unwrap(), 0) + }).collect(); + + Ok((winners, assignments)) +} diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 73fcb6c2afeb9fe182dafebe450715938c045b24..a241161e11101f45348eef3aa3e60cced204f31b 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the module. @@ -24,27 +25,29 @@ use sp_runtime::{ use sp_staking::offence::OffenceDetails; use frame_support::{ assert_ok, assert_noop, StorageMap, - traits::{Currency, ReservableCurrency, OnInitialize}, + traits::{Currency, ReservableCurrency, OnInitialize, OnFinalize}, }; use pallet_balances::Error as BalancesError; use substrate_test_utils::assert_eq_uvec; -use crate::Store; #[test] fn force_unstake_works() { - // Verifies initial conditions of mock ExtBuilder::default().build_and_execute(|| { // Account 11 is stashed and locked, and account 10 is the controller assert_eq!(Staking::bonded(&11), Some(10)); + // Adds 2 slashing spans + add_slash(&11); // Cant transfer assert_noop!( Balances::transfer(Origin::signed(11), 1, 10), BalancesError::::LiquidityRestrictions ); // Force unstake requires root. - assert_noop!(Staking::force_unstake(Origin::signed(11), 11), BadOrigin); + assert_noop!(Staking::force_unstake(Origin::signed(11), 11, 2), BadOrigin); + // Force unstake needs correct number of slashing spans (for weight calculation) + assert_noop!(Staking::force_unstake(Origin::signed(11), 11, 0), BadOrigin); // We now force them to unstake - assert_ok!(Staking::force_unstake(Origin::ROOT, 11)); + assert_ok!(Staking::force_unstake(Origin::ROOT, 11, 2)); // No longer bonded. assert_eq!(Staking::bonded(&11), None); // Transfer works. @@ -52,6 +55,24 @@ fn force_unstake_works() { }); } +#[test] +fn kill_stash_works() { + ExtBuilder::default().build_and_execute(|| { + // Account 11 is stashed and locked, and account 10 is the controller + assert_eq!(Staking::bonded(&11), Some(10)); + // Adds 2 slashing spans + add_slash(&11); + // Only can kill a stash account + assert_noop!(Staking::kill_stash(&12, 0), Error::::NotStash); + // Respects slashing span count + assert_noop!(Staking::kill_stash(&11, 0), Error::::IncorrectSlashingSpans); + // Correct inputs, everything works + assert_ok!(Staking::kill_stash(&11, 2)); + // No longer bonded. + assert_eq!(Staking::bonded(&11), None); + }); +} + #[test] fn basic_setup_works() { // Verifies initial conditions of mock @@ -128,17 +149,18 @@ fn basic_setup_works() { #[test] fn change_controller_works() { ExtBuilder::default().build_and_execute(|| { + // 10 and 11 are bonded as stash controller. assert_eq!(Staking::bonded(&11), Some(10)); - assert!(Session::validators().contains(&11)); // 10 can control 11 who is initially a validator. assert_ok!(Staking::chill(Origin::signed(10))); - assert!(Session::validators().contains(&11)); + // change controller assert_ok!(Staking::set_controller(Origin::signed(11), 5)); - + assert_eq!(Staking::bonded(&11), Some(5)); mock::start_era(1); + // 10 is no longer in control. assert_noop!( Staking::validate(Origin::signed(10), ValidatorPrefs::default()), Error::::NotController, @@ -533,60 +555,71 @@ fn nominating_and_rewards_should_work() { } #[test] -fn nominators_also_get_slashed() { - // A nominator should be slashed if the validator they nominated is slashed - // Here is the breakdown of roles: - // 10 - is the controller of 11 - // 11 - is the stash. - // 2 - is the nominator of 20, 10 - ExtBuilder::default().nominate(false).build_and_execute(|| { - assert_eq!(Staking::validator_count(), 2); - - // 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, 2, 3, 10].iter() { - let _ = Balances::make_free_balance_be(i, initial_balance); - } - - // 2 will nominate for 10, 20 - let nominator_stake = 500; - assert_ok!(Staking::bond(Origin::signed(1), 2, nominator_stake, RewardDestination::default())); - assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 10])); - - let total_payout = current_total_payout_for_duration(3000); - assert!(total_payout > 100); // Test is meaningful if reward something - >::reward_by_ids(vec![(11, 1)]); - - // new era, pay rewards, +fn nominators_also_get_slashed_pro_rata() { + ExtBuilder::default().build_and_execute(|| { mock::start_era(1); + let slash_percent = Perbill::from_percent(5); + let initial_exposure = Staking::eras_stakers(active_era(), 11); + // 101 is a nominator for 11 + assert_eq!( + initial_exposure.others.first().unwrap().who, + 101, + ); - // Nominator stash didn't collect any. - assert_eq!(Balances::total_balance(&2), initial_balance); + // staked values; + let nominator_stake = Staking::ledger(100).unwrap().active; + let nominator_balance = balances(&101).0; + let validator_stake = Staking::ledger(10).unwrap().active; + let validator_balance = balances(&11).0; + let exposed_stake = initial_exposure.total; + let exposed_validator = initial_exposure.own; + let exposed_nominator = initial_exposure.others.first().unwrap().value; - // 10 goes offline + // 11 goes offline on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap().index, 11), + initial_exposure.clone(), ), reporters: vec![], }], - &[Perbill::from_percent(5)], + &[slash_percent], ); - let expo = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); - let slash_value = 50; - 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(&11), initial_balance - validator_slash); - assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); + // both stakes must have been decreased. + assert!(Staking::ledger(100).unwrap().active < nominator_stake); + assert!(Staking::ledger(10).unwrap().active < validator_stake); + let slash_amount = slash_percent * exposed_stake; + let validator_share = + Perbill::from_rational_approximation(exposed_validator, exposed_stake) * slash_amount; + let nominator_share = Perbill::from_rational_approximation( + exposed_nominator, + exposed_stake, + ) * slash_amount; + + // both slash amounts need to be positive for the test to make sense. + assert!(validator_share > 0); + assert!(nominator_share > 0); + + // both stakes must have been decreased pro-rata. + assert_eq!( + Staking::ledger(100).unwrap().active, + nominator_stake - nominator_share, + ); + assert_eq!( + Staking::ledger(10).unwrap().active, + validator_stake - validator_share, + ); + assert_eq!( + balances(&101).0, // free balance + nominator_balance - nominator_share, + ); + assert_eq!( + balances(&11).0, // free balance + validator_balance - validator_share, + ); // Because slashing happened. assert!(is_disabled(10)); }); @@ -1013,7 +1046,10 @@ fn bond_extra_and_withdraw_unbonded_works() { unlocking: vec![], claimed_rewards: vec![], })); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000, own: 1000, others: vec![] }); + assert_eq!( + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), + Exposure { total: 1000, own: 1000, others: vec![] } + ); // deposit the extra 100 units Staking::bond_extra(Origin::signed(11), 100).unwrap(); @@ -1026,7 +1062,10 @@ fn bond_extra_and_withdraw_unbonded_works() { claimed_rewards: vec![], })); // Exposure is a snapshot! only updated after the next era update. - assert_ne!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_ne!( + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), + Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] } + ); // trigger next era. mock::start_era(2); @@ -1041,34 +1080,68 @@ fn bond_extra_and_withdraw_unbonded_works() { claimed_rewards: vec![], })); // Exposure is now updated. - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_eq!( + Staking::eras_stakers(Staking::active_era().unwrap().index, 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 + 3}], claimed_rewards: vec![] }) + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000 + 100, + active: 100, + unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], + claimed_rewards: vec![] + }), ); // 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 + 3}], claimed_rewards: vec![] })); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000 + 100, + active: 100, + unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], + claimed_rewards: vec![] + }), + ); // trigger next era. mock::start_era(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 + 3}], claimed_rewards: vec![] })); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000 + 100, + active: 100, + unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], + claimed_rewards: vec![] + }), + ); // trigger next era. mock::start_era(5); - Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); // 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![], claimed_rewards: vec![] })); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 100, + active: 100, + unlocking: vec![], + claimed_rewards: vec![] + }), + ); }) } @@ -1091,7 +1164,7 @@ fn too_many_unbond_calls_should_not_work() { assert_noop!(Staking::unbond(Origin::signed(10), 1), Error::::NoMoreChunks); // free up. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(10))); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10), 0)); // Can add again. assert_ok!(Staking::unbond(Origin::signed(10), 1)); @@ -1439,7 +1512,7 @@ fn on_free_balance_zero_stash_removes_validator() { assert_eq!(Balances::total_balance(&11), 0); // Reap the stash - assert_ok!(Staking::reap_stash(Origin::NONE, 11)); + assert_ok!(Staking::reap_stash(Origin::NONE, 11, 0)); // Check storage items do not exist assert!(!>::contains_key(&10)); @@ -1495,7 +1568,7 @@ fn on_free_balance_zero_stash_removes_nominator() { assert_eq!(Balances::total_balance(&11), 0); // Reap the stash - assert_ok!(Staking::reap_stash(Origin::NONE, 11)); + assert_ok!(Staking::reap_stash(Origin::NONE, 11, 0)); // Check storage items do not exist assert!(!>::contains_key(&10)); @@ -1609,14 +1682,14 @@ fn bond_with_no_staked_value() { mock::start_era(2); // not yet removed. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(2), 0)); assert!(Staking::ledger(2).is_some()); assert_eq!(Balances::locks(&1)[0].amount, 5); mock::start_era(3); // poof. Account 1 is removed from the staking system. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); + assert_ok!(Staking::withdraw_unbonded(Origin::signed(2), 0)); assert!(Staking::ledger(2).is_none()); assert_eq!(Balances::locks(&1).len(), 0); }); @@ -2260,7 +2333,12 @@ fn garbage_collection_after_slashing() { assert_eq!(Balances::free_balance(11), 0); assert_eq!(Balances::total_balance(&11), 0); - assert_ok!(Staking::reap_stash(Origin::NONE, 11)); + let slashing_spans = ::SlashingSpans::get(&11).unwrap(); + assert_eq!(slashing_spans.iter().count(), 2); + + // reap_stash respects num_slashing_spans so that weight is accurate + assert_noop!(Staking::reap_stash(Origin::NONE, 11, 0), Error::::IncorrectSlashingSpans); + assert_ok!(Staking::reap_stash(Origin::NONE, 11, 2)); assert!(::SlashingSpans::get(&11).is_none()); assert_eq!(::SpanSlash::get(&(11, 0)).amount_slashed(), &0); @@ -2675,7 +2753,10 @@ fn remove_multi_deferred() { mod offchain_phragmen { use crate::*; use codec::Encode; - use frame_support::{assert_noop, assert_ok}; + use frame_support::{ + assert_noop, assert_ok, assert_err_with_weight, + dispatch::DispatchResultWithPostInfo, + }; use sp_runtime::transaction_validity::TransactionSource; use mock::*; use parking_lot::RwLock; @@ -2695,7 +2776,7 @@ mod offchain_phragmen { /// setup a new set of validators and nominator storage items independent of the parent mock /// file. This produces a edge graph that can be reduced. - fn build_offchain_phragmen_test_ext() { + pub fn build_offchain_phragmen_test_ext() { for i in (10..=40).step_by(10) { // Note: we respect the convention of the mock (10, 11 pairs etc.) since these accounts // have corresponding keys in session which makes everything more ergonomic and @@ -2730,6 +2811,29 @@ mod offchain_phragmen { pool_state } + fn election_size() -> ElectionSize { + ElectionSize { + validators: Staking::snapshot_validators().unwrap().len() as ValidatorIndex, + nominators: Staking::snapshot_nominators().unwrap().len() as NominatorIndex, + } + } + + fn submit_solution( + origin: Origin, + winners: Vec, + compact: CompactAssignments, + score: PhragmenScore, + ) -> DispatchResultWithPostInfo { + Staking::submit_election_solution( + origin, + winners, + compact, + score, + current_era(), + election_size(), + ) + } + #[test] fn is_current_session_final_works() { ExtBuilder::default() @@ -2755,7 +2859,7 @@ mod offchain_phragmen { } #[test] - fn offchain_election_flag_is_triggered() { + fn offchain_window_is_triggered() { ExtBuilder::default() .session_per_era(5) .session_length(10) @@ -2815,16 +2919,13 @@ mod offchain_phragmen { } #[test] - fn offchain_election_flag_is_triggered_when_forcing() { + fn offchain_window_is_triggered_when_forcing() { ExtBuilder::default() .session_per_era(5) .session_length(10) .election_lookahead(3) .build() .execute_with(|| { - run_to_block(7); - assert_session_era!(0, 0); - run_to_block(12); ForceEra::put(Forcing::ForceNew); run_to_block(13); @@ -2832,11 +2933,90 @@ mod offchain_phragmen { run_to_block(17); // instead of 47 assert_eq!(Staking::era_election_status(), ElectionStatus::Open(17)); + + run_to_block(20); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + }) + } + + #[test] + fn offchain_window_is_triggered_when_force_always() { + ExtBuilder::default() + .session_per_era(5) + .session_length(10) + .election_lookahead(3) + .build() + .execute_with(|| { + + ForceEra::put(Forcing::ForceAlways); + run_to_block(16); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + run_to_block(17); // instead of 37 + assert_eq!(Staking::era_election_status(), ElectionStatus::Open(17)); + + run_to_block(20); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + run_to_block(26); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + run_to_block(27); // next one again + assert_eq!(Staking::era_election_status(), ElectionStatus::Open(27)); + }) + } + + #[test] + fn offchain_window_closes_when_forcenone() { + ExtBuilder::default() + .session_per_era(5) + .session_length(10) + .election_lookahead(3) + .build() + .execute_with(|| { + ForceEra::put(Forcing::ForceNone); + + run_to_block(36); + assert_session_era!(3, 0); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + // opens + run_to_block(37); + assert_eq!(Staking::era_election_status(), ElectionStatus::Open(37)); + assert!(Staking::is_current_session_final()); + assert!(Staking::snapshot_validators().is_some()); + + // closes normally + run_to_block(40); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert!(!Staking::is_current_session_final()); + assert!(Staking::snapshot_validators().is_none()); + assert_session_era!(4, 0); + + run_to_block(47); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert_session_era!(4, 0); + + run_to_block(57); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert_session_era!(5, 0); + + run_to_block(67); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + + // Will not open again as scheduled + run_to_block(87); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert_session_era!(8, 0); + + run_to_block(90); + assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); + assert_session_era!(9, 0); }) } #[test] - fn election_on_chain_fallback_works() { + fn offchain_window_on_chain_fallback_works() { ExtBuilder::default().build_and_execute(|| { start_session(1); start_session(2); @@ -2918,16 +3098,30 @@ mod offchain_phragmen { assert!(Staking::snapshot_validators().is_some()); let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - current_era(), )); let queued_result = Staking::queued_elected().unwrap(); assert_eq!(queued_result.compute, ElectionCompute::Signed); + assert_eq!( + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| { + if let MetaEvent::staking(inner) = e { + Some(inner) + } else { + None + } + }) + .last() + .unwrap(), + RawEvent::SolutionStored(ElectionCompute::Signed), + ); run_to_block(15); assert_eq!(Staking::era_election_status(), ElectionStatus::Closed); @@ -2961,13 +3155,7 @@ mod offchain_phragmen { assert_eq!(Staking::era_election_status(), ElectionStatus::Open(12)); let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); - assert_ok!(Staking::submit_election_solution( - Origin::signed(10), - winners, - compact, - score, - current_era(), - )); + assert_ok!(submit_solution(Origin::signed(10), winners, compact, score)); let queued_result = Staking::queued_elected().unwrap(); assert_eq!(queued_result.compute, ElectionCompute::Signed); @@ -3010,15 +3198,17 @@ mod offchain_phragmen { let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); Staking::kill_stakers_snapshot(); - assert_noop!( + assert_err_with_weight!( Staking::submit_election_solution( Origin::signed(10), - winners, - compact, + winners.clone(), + compact.clone(), score, current_era(), + ElectionSize::default(), ), Error::::PhragmenEarlySubmission, + Some(::DbWeight::get().reads(1)), ); }) } @@ -3037,25 +3227,24 @@ mod offchain_phragmen { // a good solution let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - current_era(), )); // a bad solution let (compact, winners, score) = horrible_phragmen_with_post_processing(false); - assert_noop!( - Staking::submit_election_solution( + assert_err_with_weight!( + submit_solution( Origin::signed(10), - winners, - compact, + winners.clone(), + compact.clone(), score, - current_era(), ), Error::::PhragmenWeakSubmission, + Some(::DbWeight::get().reads(3)) ); }) } @@ -3074,22 +3263,20 @@ mod offchain_phragmen { // a meeeeh solution let (compact, winners, score) = horrible_phragmen_with_post_processing(false); - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - current_era(), )); // a better solution let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - current_era(), )); }) } @@ -3190,12 +3377,11 @@ mod offchain_phragmen { run_to_block(12); // put a good solution on-chain let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ),); // now run the offchain worker in the same chain state. @@ -3240,6 +3426,28 @@ mod offchain_phragmen { assert_eq!(winners.len(), 3); + assert_noop!( + submit_solution( + Origin::signed(10), + winners, + compact, + score, + ), + Error::::PhragmenBogusWinnerCount, + ); + }) + } + + #[test] + fn invalid_phragmen_result_solution_size() { + ExtBuilder::default() + .offchain_phragmen_ext() + .build() + .execute_with(|| { + run_to_block(12); + + let (compact, winners, score) = prepare_submission_with(true, 2, |_| {}); + assert_noop!( Staking::submit_election_solution( Origin::signed(10), @@ -3247,8 +3455,9 @@ mod offchain_phragmen { compact, score, current_era(), + ElectionSize::default(), ), - Error::::PhragmenBogusWinnerCount, + Error::::PhragmenBogusElectionSize, ); }) } @@ -3272,12 +3481,11 @@ mod offchain_phragmen { assert_eq!(winners.len(), 3); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusWinnerCount, ); @@ -3301,12 +3509,11 @@ mod offchain_phragmen { assert_eq!(winners.len(), 4); // all good. We chose 4 and it works. - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ),); }) } @@ -3332,12 +3539,11 @@ mod offchain_phragmen { // The error type sadly cannot be more specific now. assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusCompact, ); @@ -3365,12 +3571,11 @@ mod offchain_phragmen { // The error type sadly cannot be more specific now. assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusCompact, ); @@ -3397,12 +3602,11 @@ mod offchain_phragmen { let winners = vec![0, 1, 2, 4]; assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusWinner, ); @@ -3433,12 +3637,11 @@ mod offchain_phragmen { }); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusEdge, ); @@ -3469,12 +3672,11 @@ mod offchain_phragmen { }); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusSelfVote, ); @@ -3505,12 +3707,11 @@ mod offchain_phragmen { // This raises score issue. assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusSelfVote, ); @@ -3540,12 +3741,11 @@ mod offchain_phragmen { } assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusCompact, ); @@ -3582,12 +3782,11 @@ mod offchain_phragmen { }); assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusNomination, ); @@ -3645,12 +3844,11 @@ mod offchain_phragmen { }); // can be submitted. - assert_ok!(Staking::submit_election_solution( + assert_ok!(submit_solution( Origin::signed(10), winners, compact, score, - current_era(), )); // a wrong solution. @@ -3664,12 +3862,11 @@ mod offchain_phragmen { // is rejected. assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenSlashedNomination, ); @@ -3692,12 +3889,11 @@ mod offchain_phragmen { score[0] += 1; assert_noop!( - Staking::submit_election_solution( + submit_solution( Origin::signed(10), winners, compact, score, - current_era(), ), Error::::PhragmenBogusScore, ); @@ -4082,16 +4278,16 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( fn set_history_depth_works() { ExtBuilder::default().build_and_execute(|| { mock::start_era(10); - Staking::set_history_depth(Origin::ROOT, 20).unwrap(); + Staking::set_history_depth(Origin::ROOT, 20, 0).unwrap(); assert!(::ErasTotalStake::contains_key(10 - 4)); assert!(::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 4).unwrap(); + Staking::set_history_depth(Origin::ROOT, 4, 0).unwrap(); assert!(::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 3).unwrap(); + Staking::set_history_depth(Origin::ROOT, 3, 0).unwrap(); assert!(!::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 8).unwrap(); + Staking::set_history_depth(Origin::ROOT, 8, 0).unwrap(); assert!(!::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); }); @@ -4588,3 +4784,79 @@ fn migrate_era_should_handle_errors_2() { assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); }); } + +#[test] +fn offences_weight_calculated_correctly() { + ExtBuilder::default().nominate(true).build_and_execute(|| { + // On offence with zero offenders: 4 Reads, 1 Write + let zero_offence_weight = ::DbWeight::get().reads_writes(4, 1); + assert_eq!(Staking::on_offence(&[], &[Perbill::from_percent(50)], 0), Ok(zero_offence_weight)); + + // On Offence with N offenders, Unapplied: 4 Reads, 1 Write + 4 Reads, 5 Writes + let n_offence_unapplied_weight = ::DbWeight::get().reads_writes(4, 1) + + ::DbWeight::get().reads_writes(4, 5); + + let offenders: Vec::AccountId, pallet_session::historical::IdentificationTuple>> + = (1..10).map(|i| + OffenceDetails { + offender: (i, Staking::eras_stakers(Staking::active_era().unwrap().index, i)), + reporters: vec![], + } + ).collect(); + assert_eq!(Staking::on_offence(&offenders, &[Perbill::from_percent(50)], 0), Ok(n_offence_unapplied_weight)); + + // On Offence with one offenders, Applied + let one_offender = [ + OffenceDetails { + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), + reporters: vec![1], + }, + ]; + + let n = 1; // Number of offenders + let rw = 3 + 3 * n; // rw reads and writes + let one_offence_unapplied_weight = ::DbWeight::get().reads_writes(4, 1) + + ::DbWeight::get().reads_writes(rw, rw) + // One `slash_cost` + + ::DbWeight::get().reads_writes(6, 5) + // `slash_cost` * nominators (1) + + ::DbWeight::get().reads_writes(6, 5) + // `reward_cost` * reporters (1) + + ::DbWeight::get().reads_writes(2, 2); + + assert_eq!(Staking::on_offence(&one_offender, &[Perbill::from_percent(50)], 0), Ok(one_offence_unapplied_weight)); + }); +} + +#[test] +fn on_initialize_weight_is_correct() { + ExtBuilder::default().has_stakers(false).build_and_execute(|| { + assert_eq!(Validators::::iter().count(), 0); + assert_eq!(Nominators::::iter().count(), 0); + // When this pallet has nothing, we do 4 reads each block + let base_weight = ::DbWeight::get().reads(4); + assert_eq!(base_weight, Staking::on_initialize(0)); + }); + + ExtBuilder::default() + .offchain_phragmen_ext() + .validator_count(4) + .has_stakers(false) + .build() + .execute_with(|| { + crate::tests::offchain_phragmen::build_offchain_phragmen_test_ext(); + run_to_block(11); + Staking::on_finalize(System::block_number()); + System::set_block_number((System::block_number() + 1).into()); + Timestamp::set_timestamp(System::block_number() * 1000 + INIT_TIMESTAMP); + Session::on_initialize(System::block_number()); + + assert_eq!(Validators::::iter().count(), 4); + assert_eq!(Nominators::::iter().count(), 5); + // With 4 validators and 5 nominator, we should increase weight by: + // - (4 + 5) reads + // - 3 Writes + let final_weight = ::DbWeight::get().reads_writes(4 + 9, 3); + assert_eq!(final_weight, Staking::on_initialize(System::block_number())); + }); +} diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml index 25988b1fe30c945ba8b53ef48944057108d2c16d..979eeb2b2864aee5e95d9bc2f390aec0a17111a3 100644 --- a/frame/sudo/Cargo.toml +++ b/frame/sudo/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-sudo" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for sudo" @@ -14,14 +14,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs index 21ae841c79242a9e0083d48802ac926bc36e07a1..3d5d1b25821271868fb7c005c07357433df69f43 100644 --- a/frame/sudo/src/lib.rs +++ b/frame/sudo/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Sudo Module //! @@ -95,6 +96,11 @@ use frame_support::{ use frame_support::weights::{Weight, GetDispatchInfo, FunctionOf, Pays}; use frame_system::{self as system, ensure_signed}; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + pub trait Trait: frame_system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..a270787da66ec5e70c3fff960692938b95da00df --- /dev/null +++ b/frame/sudo/src/mock.rs @@ -0,0 +1,176 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Test utilities + +use super::*; +use frame_support::{ + impl_outer_origin, impl_outer_dispatch, impl_outer_event, parameter_types, + weights::{Weight, DispatchClass} +}; +use sp_core::H256; +// The testing primitives are very useful for avoiding having to work with signatures +// or public keys. +use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; +use sp_io; +use crate as sudo; + +// Logger module to track execution. +pub mod logger { + use super::*; + use frame_system::ensure_root; + + pub trait Trait: system::Trait { + type Event: From> + Into<::Event>; + } + + decl_storage! { + trait Store for Module as Logger { + AccountLog get(fn account_log): Vec; + I32Log get(fn i32_log): Vec; + } + } + + decl_event! { + pub enum Event where AccountId = ::AccountId { + AppendI32(i32, Weight), + AppendI32AndAccount(AccountId, i32, Weight), + } + } + + decl_module! { + pub struct Module for enum Call where origin: ::Origin { + fn deposit_event() = default; + + #[weight = FunctionOf( + |args: (&i32, &Weight)| *args.1, + DispatchClass::Normal, + Pays::Yes, + )] + fn privileged_i32_log(origin, i: i32, weight: Weight){ + // Ensure that the `origin` is `Root`. + ensure_root(origin)?; + ::append(i); + Self::deposit_event(RawEvent::AppendI32(i, weight)); + } + + #[weight = FunctionOf( + |args: (&i32, &Weight)| *args.1, + DispatchClass::Normal, + Pays::Yes, + )] + fn non_privileged_log(origin, i: i32, weight: Weight){ + // Ensure that the `origin` is some signed account. + let sender = ensure_signed(origin)?; + ::append(i); + >::append(sender.clone()); + Self::deposit_event(RawEvent::AppendI32AndAccount(sender, i, weight)); + } + } + } +} + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +mod test_events { + pub use crate::Event; +} + +impl_outer_event! { + pub enum TestEvent for Test { + system, + sudo, + logger, + } +} + +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + sudo::Sudo, + logger::Logger, + } +} + +// For testing the pallet, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of pallets we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Trait for Test { + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); +} + +// Implement the logger module's `Trait` on the Test runtime. +impl logger::Trait for Test { + type Event = TestEvent; +} + +// Implement the sudo module's `Trait` on the Test runtime. +impl Trait for Test { + type Event = TestEvent; + type Call = Call; +} + +// Assign back to type variables in order to make dispatched calls of these modules later. +pub type Sudo = Module; +pub type Logger = logger::Module; +pub type System = system::Module; + +// New types for dispatchable functions. +pub type SudoCall = sudo::Call; +pub type LoggerCall = logger::Call; + +// Build test environment by setting the root `key` for the Genesis. +pub fn new_test_ext(root_key: u64) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig::{ + key: root_key, + }.assimilate_storage(&mut t).unwrap(); + t.into() +} diff --git a/frame/sudo/src/tests.rs b/frame/sudo/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..79424d2824f9026d43d3ec04332896f545ba7eb2 --- /dev/null +++ b/frame/sudo/src/tests.rs @@ -0,0 +1,169 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests for the module. + +use super::*; +use mock::{ + Sudo, SudoCall, Origin, Call, Test, new_test_ext, LoggerCall, Logger, System, TestEvent, +}; +use frame_support::{assert_ok, assert_noop}; + +#[test] +fn test_setup_works() { + // Environment setup, logger storage, and sudo `key` retrieval should work as expected. + new_test_ext(1).execute_with(|| { + assert_eq!(Sudo::key(), 1u64); + assert_eq!(Logger::i32_log(), vec![]); + assert_eq!(Logger::account_log(), vec![]); + }); +} + +#[test] +fn sudo_basics() { + // Configure a default test environment and set the root `key` to 1. + new_test_ext(1).execute_with(|| { + // A privileged function should work when `sudo` is passed the root `key` as `origin`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_ok!(Sudo::sudo(Origin::signed(1), call)); + assert_eq!(Logger::i32_log(), vec![42i32]); + + // A privileged function should not work when `sudo` is passed a non-root `key` as `origin`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_noop!(Sudo::sudo(Origin::signed(2), call), Error::::RequireSudo); + }); +} + +#[test] +fn sudo_emits_events_correctly() { + new_test_ext(1).execute_with(|| { + // Set block number to 1 because events are not emitted on block 0. + System::set_block_number(1); + + // Should emit event to indicate success when called with the root `key` and `call` is `Ok`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1))); + assert_ok!(Sudo::sudo(Origin::signed(1), call)); + let expected_event = TestEvent::sudo(RawEvent::Sudid(Ok(()))); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }) +} + +#[test] +fn sudo_unchecked_weight_basics() { + new_test_ext(1).execute_with(|| { + // A privileged function should work when `sudo` is passed the root `key` as origin. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_ok!(Sudo::sudo_unchecked_weight(Origin::signed(1), call, 1_000)); + assert_eq!(Logger::i32_log(), vec![42i32]); + + // A privileged function should not work when called with a non-root `key`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_noop!( + Sudo::sudo_unchecked_weight(Origin::signed(2), call, 1_000), + Error::::RequireSudo, + ); + // `I32Log` is unchanged after unsuccessful call. + assert_eq!(Logger::i32_log(), vec![42i32]); + + // Controls the dispatched weight. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1))); + let sudo_unchecked_weight_call = SudoCall::sudo_unchecked_weight(call, 1_000); + let info = sudo_unchecked_weight_call.get_dispatch_info(); + assert_eq!(info.weight, 1_000); + }); +} + +#[test] +fn sudo_unchecked_weight_emits_events_correctly() { + new_test_ext(1).execute_with(|| { + // Set block number to 1 because events are not emitted on block 0. + System::set_block_number(1); + + // Should emit event to indicate success when called with the root `key` and `call` is `Ok`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1))); + assert_ok!(Sudo::sudo_unchecked_weight(Origin::signed(1), call, 1_000)); + let expected_event = TestEvent::sudo(RawEvent::Sudid(Ok(()))); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }) +} + +#[test] +fn set_key_basics() { + new_test_ext(1).execute_with(|| { + // A root `key` can change the root `key` + assert_ok!(Sudo::set_key(Origin::signed(1), 2)); + assert_eq!(Sudo::key(), 2u64); + }); + + new_test_ext(1).execute_with(|| { + // A non-root `key` will trigger a `RequireSudo` error and a non-root `key` cannot change the root `key`. + assert_noop!(Sudo::set_key(Origin::signed(2), 3), Error::::RequireSudo); + }); +} + +#[test] +fn set_key_emits_events_correctly() { + new_test_ext(1).execute_with(|| { + // Set block number to 1 because events are not emitted on block 0. + System::set_block_number(1); + + // A root `key` can change the root `key`. + assert_ok!(Sudo::set_key(Origin::signed(1), 2)); + let expected_event = TestEvent::sudo(RawEvent::KeyChanged(1)); + assert!(System::events().iter().any(|a| a.event == expected_event)); + // Double check. + assert_ok!(Sudo::set_key(Origin::signed(2), 4)); + let expected_event = TestEvent::sudo(RawEvent::KeyChanged(2)); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }); +} + +#[test] +fn sudo_as_basics() { + new_test_ext(1).execute_with(|| { + // A privileged function will not work when passed to `sudo_as`. + let call = Box::new(Call::Logger(LoggerCall::privileged_i32_log(42, 1_000))); + assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call)); + assert_eq!(Logger::i32_log(), vec![]); + assert_eq!(Logger::account_log(), vec![]); + + // A non-privileged function should not work when called with a non-root `key`. + let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1))); + assert_noop!(Sudo::sudo_as(Origin::signed(3), 2, call), Error::::RequireSudo); + + // A non-privileged function will work when passed to `sudo_as` with the root `key`. + let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1))); + assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call)); + assert_eq!(Logger::i32_log(), vec![42i32]); + // The correct user makes the call within `sudo_as`. + assert_eq!(Logger::account_log(), vec![2]); + }); +} + +#[test] +fn sudo_as_emits_events_correctly() { + new_test_ext(1).execute_with(|| { + // Set block number to 1 because events are not emitted on block 0. + System::set_block_number(1); + + // A non-privileged function will work when passed to `sudo_as` with the root `key`. + let call = Box::new(Call::Logger(LoggerCall::non_privileged_log(42, 1))); + assert_ok!(Sudo::sudo_as(Origin::signed(1), 2, call)); + let expected_event = TestEvent::sudo(RawEvent::SudoAsDone(true)); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }); +} diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index 0168705da7e343f682dd38209a15bf93efbc126c..d9117cf5267519c7dd5829ecf43d521900b9ac52 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-support" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Support code for the runtime." @@ -15,24 +15,25 @@ targets = ["x86_64-unknown-linux-gnu"] log = "0.4" serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -frame-metadata = { version = "11.0.0-dev", default-features = false, path = "../metadata" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-tracing = { version = "2.0.0-dev", default-features = false, path = "../../primitives/tracing" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-arithmetic = { version = "2.0.0-dev", default-features = false, path = "../../primitives/arithmetic" } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" } -frame-support-procedural = { version = "2.0.0-dev", path = "./procedural" } +frame-metadata = { version = "11.0.0-rc2", default-features = false, path = "../metadata" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-tracing = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/tracing" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-arithmetic = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/arithmetic" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/inherents" } +frame-support-procedural = { version = "2.0.0-rc2", path = "./procedural" } paste = "0.1.6" once_cell = { version = "1", default-features = false, optional = true } -sp-state-machine = { version = "0.8.0-dev", optional = true, path = "../../primitives/state-machine" } +sp-state-machine = { version = "0.8.0-rc2", optional = true, path = "../../primitives/state-machine" } bitmask = { version = "0.5.0", default-features = false } impl-trait-for-tuples = "0.1.3" +smallvec = "1.4.0" [dev-dependencies] pretty_assertions = "0.6.1" -frame-system = { version = "2.0.0-dev", path = "../system" } +frame-system = { version = "2.0.0-rc2", path = "../system" } [features] default = ["std"] diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml index 55e551343214d0711945d6c3d3008d03086836dd..0c20ac93e194483824e13452ca309d55f9e13ceb 100644 --- a/frame/support/procedural/Cargo.toml +++ b/frame/support/procedural/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-support-procedural" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Proc macro of Support code for the runtime." @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] proc-macro = true [dependencies] -frame-support-procedural-tools = { version = "2.0.0-dev", path = "./tools" } +frame-support-procedural-tools = { version = "2.0.0-rc2", path = "./tools" } proc-macro2 = "1.0.6" quote = "1.0.3" syn = { version = "1.0.7", features = ["full"] } diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs index b74a27e7ba936c982512438fc47d5ab7dd5dc379..d7529cd272d0e042caf1b5a692f4595bf40e2888 100644 --- a/frame/support/procedural/src/construct_runtime/mod.rs +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod parse; diff --git a/frame/support/procedural/src/construct_runtime/parse.rs b/frame/support/procedural/src/construct_runtime/parse.rs index 4a81a7efd6b77ad09cad319a88eb16e8a4589e97..92a71687cc102b429726c20c177dc1f6017ce1ef 100644 --- a/frame/support/procedural/src/construct_runtime/parse.rs +++ b/frame/support/procedural/src/construct_runtime/parse.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use frame_support_procedural_tools::syn_ext as ext; use proc_macro2::Span; diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 17b1efdcd488cb8ef68ffb499b6d459820c6522f..df5665ec48a2f5f97dbb34b2b8247ac873123376 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Proc macro of Support code for the runtime. diff --git a/frame/support/procedural/src/storage/genesis_config/builder_def.rs b/frame/support/procedural/src/storage/genesis_config/builder_def.rs index 87255ee481b37b8debf9d2ff25b55775e8fe46c2..a045794529c958d908dfbb34ff6b847c9af52235 100644 --- a/frame/support/procedural/src/storage/genesis_config/builder_def.rs +++ b/frame/support/procedural/src/storage/genesis_config/builder_def.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Builder logic definition used to build genesis storage. @@ -54,10 +55,16 @@ impl BuilderDef { data = Some(match &line.storage_type { StorageLineTypeDef::Simple(_) if line.is_option => quote_spanned!(builder.span() => - let data = (#builder)(self); + // NOTE: the type of `data` is specified when used later in the code + let builder: fn(&Self) -> _ = #builder; + let data = builder(self); let data = Option::as_ref(&data); ), - _ => quote_spanned!(builder.span() => let data = &(#builder)(self); ), + _ => quote_spanned!(builder.span() => + // NOTE: the type of `data` is specified when used later in the code + let builder: fn(&Self) -> _ = #builder; + let data = &builder(self); + ), }); } else if let Some(config) = &line.config { is_generic |= line.is_generic; diff --git a/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs b/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs index 9b6ddc92178bd6f981fde39c47933412c565c31e..6339134ea0d22681ac413b60613b66080dec10bd 100644 --- a/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs +++ b/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Genesis config definition. diff --git a/frame/support/procedural/src/storage/genesis_config/mod.rs b/frame/support/procedural/src/storage/genesis_config/mod.rs index eeeca150d9b9b8419922f73f1ef51ed3ce46e095..7cc0f7c3befd4bc9ac331b5c690b3ffb69f30508 100644 --- a/frame/support/procedural/src/storage/genesis_config/mod.rs +++ b/frame/support/procedural/src/storage/genesis_config/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Declaration of genesis config structure and implementation of build storage trait and //! functions. diff --git a/frame/support/procedural/src/storage/getters.rs b/frame/support/procedural/src/storage/getters.rs index ae0e646fcd73aaf0d398d82755372dbfe9736da6..5507db4630596f32addac764289d3dd71efa643b 100644 --- a/frame/support/procedural/src/storage/getters.rs +++ b/frame/support/procedural/src/storage/getters.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of getters on module structure. diff --git a/frame/support/procedural/src/storage/instance_trait.rs b/frame/support/procedural/src/storage/instance_trait.rs index b2f0ad9c06c037d075a1781b0ceda194ce0d9133..1e5e198a8c527a95f6a876db4fe639aa33be839a 100644 --- a/frame/support/procedural/src/storage/instance_trait.rs +++ b/frame/support/procedural/src/storage/instance_trait.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of the trait instance and the instance structures implementing it. //! (For not instantiable traits there is still the inherent instance implemented). diff --git a/frame/support/procedural/src/storage/metadata.rs b/frame/support/procedural/src/storage/metadata.rs index bb23c99d9df5160bc3f09d780c7960bcf9c0dfa2..065320cd018aef1061c05e8140777eec50efdbb8 100644 --- a/frame/support/procedural/src/storage/metadata.rs +++ b/frame/support/procedural/src/storage/metadata.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of `storage_metadata` on module structure, used by construct_runtime. diff --git a/frame/support/procedural/src/storage/mod.rs b/frame/support/procedural/src/storage/mod.rs index e8599c52a907173f5c19f1359bc43205667a749e..766141f5aaf8f677a2177fdc3c0afaf154e10966 100644 --- a/frame/support/procedural/src/storage/mod.rs +++ b/frame/support/procedural/src/storage/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! `decl_storage` input definition and expansion. diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index beb9beff707b3c8254cb2ea1c5ff6418cc77e0b6..5a3bb3f40cd4be0b9c3c5811f918f128b771a88f 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Parsing of decl_storage input. diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs index cbd477354e820946a9f3f1692d70c3a7f2a52ca5..4cacb35c49d9abc0324a5009ee3ead917851e9a6 100644 --- a/frame/support/procedural/src/storage/storage_struct.rs +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implementation of storage structures and implementation of storage traits on them. @@ -85,7 +86,10 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre Ident::new(INHERENT_INSTANCE_NAME, Span::call_site()) }; - let storage_name_str = syn::LitStr::new(&line.name.to_string(), line.name.span()); + let storage_name_bstr = syn::LitByteStr::new( + line.name.to_string().as_ref(), + line.name.span() + ); let storage_generator_trait = &line.storage_generator_trait; let storage_struct = &line.storage_struct; @@ -106,7 +110,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { @@ -130,7 +134,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } } @@ -145,7 +149,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { @@ -170,7 +174,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } } @@ -188,7 +192,7 @@ pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStre } fn storage_prefix() -> &'static [u8] { - #storage_name_str.as_bytes() + #storage_name_bstr } fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { diff --git a/frame/support/procedural/src/storage/store_trait.rs b/frame/support/procedural/src/storage/store_trait.rs index 96281e408e958342777aa53c4f973d6cfa9178a7..7efe65b5f31783596841e0c45a6083229ade15c5 100644 --- a/frame/support/procedural/src/storage/store_trait.rs +++ b/frame/support/procedural/src/storage/store_trait.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Declaration of store trait and implementation on module structure. diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml index f64ad9b1e66edcd87640a73ce257ab0a74730713..052a0740248fa9ed380e57e435269b89a0a28d62 100644 --- a/frame/support/procedural/tools/Cargo.toml +++ b/frame/support/procedural/tools/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-support-procedural-tools" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Proc macro helpers for procedural macros" @@ -12,7 +12,7 @@ description = "Proc macro helpers for procedural macros" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -frame-support-procedural-tools-derive = { version = "2.0.0-dev", path = "./derive" } +frame-support-procedural-tools-derive = { version = "2.0.0-rc2", path = "./derive" } proc-macro2 = "1.0.6" quote = "1.0.3" syn = { version = "1.0.7", features = ["full", "visit"] } diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml index 75721508e8f0f138d7d4c64da1c1a4822530b00c..75cb6f3045e691ade907d805fd3309860e9502b7 100644 --- a/frame/support/procedural/tools/derive/Cargo.toml +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-support-procedural-tools-derive" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Use to derive parsing for parsing struct." diff --git a/frame/support/procedural/tools/derive/src/lib.rs b/frame/support/procedural/tools/derive/src/lib.rs index 0c5930892b1b5321857d05993170acebf7cd2515..ec5af13b6753f2862bbe8ff874866f4d88b14cb3 100644 --- a/frame/support/procedural/tools/derive/src/lib.rs +++ b/frame/support/procedural/tools/derive/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Use to derive parsing for parsing struct. diff --git a/frame/support/procedural/tools/src/lib.rs b/frame/support/procedural/tools/src/lib.rs index 102fee0e18ed0e2bd713967e99048f742273f21b..0033787a7c0450629c693037f73fd43e37d76504 100644 --- a/frame/support/procedural/tools/src/lib.rs +++ b/frame/support/procedural/tools/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Proc macro helpers for procedural macros diff --git a/frame/support/procedural/tools/src/syn_ext.rs b/frame/support/procedural/tools/src/syn_ext.rs index 45774372325aeebc6b6a89a4aef3efdb480a658d..2ba4cf3f28a11f1935ec50d76f025e543ae3cb06 100644 --- a/frame/support/procedural/tools/src/syn_ext.rs +++ b/frame/support/procedural/tools/src/syn_ext.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Extension to syn types, mainly for parsing diff --git a/frame/support/src/debug.rs b/frame/support/src/debug.rs index 4b7ff6cc393366791d1225a4dbd048379a63b4d5..e4a48068460c6cc038577d7d8eae9304617094fa 100644 --- a/frame/support/src/debug.rs +++ b/frame/support/src/debug.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime debugging and logging utilities. //! diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index df887fa2c42ca850adfed27451c0949bda299428..dd4b6d0b862f93e2254a1128d41de0dd0879e964 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Dispatch system. Contains a macro for defining runtime modules and //! generating values representing lazy module function calls. diff --git a/frame/support/src/error.rs b/frame/support/src/error.rs index 115920f39a933440d61825661830cbc391588a9f..456ef3c46197087181e8607ea5c37fbb71629918 100644 --- a/frame/support/src/error.rs +++ b/frame/support/src/error.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macro for declaring a module error. diff --git a/frame/support/src/hash.rs b/frame/support/src/hash.rs index 40cb1f612f7bf61e4a499e08feba56c1bfe6ea41..a5de205863d5ca8584e32b4b557e5b13eedbeeec 100644 --- a/frame/support/src/hash.rs +++ b/frame/support/src/hash.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Hash utilities. diff --git a/frame/support/src/inherent.rs b/frame/support/src/inherent.rs index 4e09bf9dd817398864bd8e71c86dd0e82befb4fd..8bc99db9e22c277e909117574029d3c73c216acf 100644 --- a/frame/support/src/inherent.rs +++ b/frame/support/src/inherent.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[doc(hidden)] pub use crate::sp_std::vec::Vec; diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 6bad5985abcb64626f8cc931b2ce0e4c3a39a2d2..471dd72a748dffe1103febb5d275e0515b0924b1 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Support code for the runtime. @@ -83,27 +84,62 @@ pub use sp_runtime::{self, ConsensusEngineId, print, traits::Printable}; #[derive(Debug)] pub enum Never {} -/// Macro for easily creating a new implementation of the `Get` trait. Use similarly to -/// how you would declare a `const`: +/// Macro for easily creating a new implementation of the `Get` trait. If `const` token is used, the +/// rhs of the expression must be `const`-only, and get is implemented as `const`: /// -/// ```no_compile +/// ``` +/// # use frame_support::traits::Get; +/// # use frame_support::parameter_types; +/// // This function cannot be used in a const context. +/// fn non_const_expression() -> u64 { 99 } +/// +/// const FIXED_VALUE: u64 = 10; /// parameter_types! { -/// pub const Argument: u64 = 42; +/// pub const Argument: u64 = 42 + FIXED_VALUE; +/// pub OtherArgument: u64 = non_const_expression(); /// } +/// /// trait Config { /// type Parameter: Get; +/// type OtherParameter: Get; /// } +/// /// struct Runtime; /// impl Config for Runtime { /// type Parameter = Argument; +/// type OtherParameter = OtherArgument; /// } /// ``` +/// +/// Invalid example: +/// +/// ```compile_fail +/// # use frame_support::traits::Get; +/// # use frame_support::parameter_types; +/// // This function cannot be used in a const context. +/// fn non_const_expression() -> u64 { 99 } +/// +/// parameter_types! { +/// pub const Argument: u64 = non_const_expression(); +/// } +/// ``` + #[macro_export] macro_rules! parameter_types { ( $( #[ $attr:meta ] )* $vis:vis const $name:ident: $type:ty = $value:expr; $( $rest:tt )* + ) => ( + $( #[ $attr ] )* + $vis struct $name; + $crate::parameter_types!{IMPL_CONST $name , $type , $value} + $crate::parameter_types!{ $( $rest )* } + ); + ( + $( #[ $attr:meta ] )* + $vis:vis $name:ident: $type:ty = $value:expr; + $( $rest:tt )* ) => ( $( #[ $attr ] )* $vis struct $name; @@ -111,6 +147,18 @@ macro_rules! parameter_types { $crate::parameter_types!{ $( $rest )* } ); () => (); + (IMPL_CONST $name:ident , $type:ty , $value:expr) => { + impl $name { + pub const fn get() -> $type { + $value + } + } + impl> $crate::traits::Get for $name { + fn get() -> I { + I::from($value) + } + } + }; (IMPL $name:ident , $type:ty , $value:expr) => { impl $name { pub fn get() -> $type { @@ -213,7 +261,21 @@ macro_rules! assert_err { #[cfg(feature = "std")] macro_rules! assert_err_ignore_postinfo { ( $x:expr , $y:expr $(,)? ) => { - assert_err!($x.map(|_| ()).map_err(|e| e.error), $y); + $crate::assert_err!($x.map(|_| ()).map_err(|e| e.error), $y); + } +} + +/// Assert an expression returns error with the given weight. +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_err_with_weight { + ($call:expr, $err:expr, $weight:expr $(,)? ) => { + if let Err(dispatch_err_with_post) = $call { + $crate::assert_err!($call.map(|_| ()).map_err(|e| e.error), $err); + assert_eq!(dispatch_err_with_post.post_info.actual_weight, $weight.into()); + } else { + panic!("expected Err(_), got Ok(_).") + } } } diff --git a/frame/support/src/metadata.rs b/frame/support/src/metadata.rs index 081f392b9ecf16d2bedbdcc90046a04ef4d7983b..7248d6bc4df5c088e3a7c7be2f7ff718fc013356 100644 --- a/frame/support/src/metadata.rs +++ b/frame/support/src/metadata.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub use frame_metadata::{ DecodeDifferent, FnEncode, RuntimeMetadata, ModuleMetadata, RuntimeMetadataLastVersion, diff --git a/frame/support/src/origin.rs b/frame/support/src/origin.rs index 43d2e70953af90b401c8b041d1cf76e35b9ba55c..f96ec07af0a9c648f34c5990b2caccfc3cac9e72 100644 --- a/frame/support/src/origin.rs +++ b/frame/support/src/origin.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macros that define an Origin type. Every function call to your runtime has an origin which //! specifies where the extrinsic was generated from. diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs index 658908d258a2ffee230b555a38aa18865e74c276..431b5e09303844db6bf212e325e251b22708c642 100644 --- a/frame/support/src/storage/child.rs +++ b/frame/support/src/storage/child.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Operation on runtime child storages. //! diff --git a/frame/support/src/storage/generator/double_map.rs b/frame/support/src/storage/generator/double_map.rs index 2c18089d38ba7fae12b436a43acd6b0122fec6e1..ff83aaf8ec8297f6dc77af8bfb1b4cc2870996c4 100644 --- a/frame/support/src/storage/generator/double_map.rs +++ b/frame/support/src/storage/generator/double_map.rs @@ -1,23 +1,24 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_std::prelude::*; use sp_std::borrow::Borrow; use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike}; -use crate::{storage::{self, unhashed, StorageAppend}, traits::Len, Never}; +use crate::{storage::{self, unhashed, StorageAppend}, Never}; use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher}; /// Generator for `StorageDoubleMap` used by `decl_storage`. @@ -260,23 +261,6 @@ impl storage::StorageDoubleMap for G where sp_io::storage::append(&final_key, item.encode()); } - fn decode_len(key1: KArg1, key2: KArg2) -> Result where - KArg1: EncodeLike, - KArg2: EncodeLike, - V: codec::DecodeLength + Len, - { - let final_key = Self::storage_double_map_final_key(key1, key2); - if let Some(v) = unhashed::get_raw(&final_key) { - ::len(&v).map_err(|e| e.what()) - } else { - let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) - .map(|v| v.len()) - .unwrap_or(0); - - Ok(len) - } - } - fn migrate_keys< OldHasher1: StorageHasher, OldHasher2: StorageHasher, diff --git a/frame/support/src/storage/generator/map.rs b/frame/support/src/storage/generator/map.rs index 307e3b1c781e67a79c56471b4385d31c95b28fe7..fe932b797940b8ac8e8d08b74d1f96d984a7e0a6 100644 --- a/frame/support/src/storage/generator/map.rs +++ b/frame/support/src/storage/generator/map.rs @@ -1,25 +1,28 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[cfg(not(feature = "std"))] use sp_std::prelude::*; use sp_std::borrow::Borrow; use codec::{FullCodec, FullEncode, Decode, Encode, EncodeLike}; -use crate::{storage::{self, unhashed, StorageAppend}, traits::Len, Never}; -use crate::hash::{StorageHasher, Twox128, ReversibleStorageHasher}; +use crate::{ + storage::{self, unhashed, StorageAppend}, + Never, hash::{StorageHasher, Twox128, ReversibleStorageHasher}, +}; /// Generator for `StorageMap` used by `decl_storage`. /// @@ -287,21 +290,6 @@ impl> storage::StorageMap sp_io::storage::append(&key, item.encode()); } - fn decode_len>(key: KeyArg) -> Result - where V: codec::DecodeLength + Len - { - let key = Self::storage_map_final_key(key); - if let Some(v) = unhashed::get_raw(key.as_ref()) { - ::len(&v).map_err(|e| e.what()) - } else { - let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) - .map(|v| v.len()) - .unwrap_or(0); - - Ok(len) - } - } - fn migrate_key>(key: KeyArg) -> Option { let old_key = { let module_prefix_hashed = Twox128::hash(Self::module_prefix()); diff --git a/frame/support/src/storage/generator/mod.rs b/frame/support/src/storage/generator/mod.rs index 07e75055f356a87435fc0ec700e5afdb0795c877..7df7dfd31739918562367edcfe97d8572414df7c 100644 --- a/frame/support/src/storage/generator/mod.rs +++ b/frame/support/src/storage/generator/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generators are a set of trait on which storage traits are implemented. //! diff --git a/frame/support/src/storage/generator/value.rs b/frame/support/src/storage/generator/value.rs index f4119ba4617112e6c25162f4620ec4ac96ecb713..2da3d91718438ffd6cfbf038f1f051992accf3ff 100644 --- a/frame/support/src/storage/generator/value.rs +++ b/frame/support/src/storage/generator/value.rs @@ -1,25 +1,25 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use codec::{FullCodec, Encode, EncodeLike, Decode}; use crate::{ Never, storage::{self, unhashed, StorageAppend}, hash::{Twox128, StorageHasher}, - traits::Len }; /// Generator for `StorageValue` used by `decl_storage`. @@ -141,19 +141,4 @@ impl> storage::StorageValue for G { let key = Self::storage_value_final_key(); sp_io::storage::append(&key, item.encode()); } - - fn decode_len() -> Result where T: codec::DecodeLength, T: Len { - let key = Self::storage_value_final_key(); - - // attempt to get the length directly. - if let Some(k) = unhashed::get_raw(&key) { - ::len(&k).map_err(|e| e.what()) - } else { - let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) - .map(|v| v.len()) - .unwrap_or(0); - - Ok(len) - } - } } diff --git a/frame/support/src/storage/hashed.rs b/frame/support/src/storage/hashed.rs index a3ffddcb841053e341cb19d90044b596341eb492..96a487111a2af171f108d1627bdc9821498fcbe0 100644 --- a/frame/support/src/storage/hashed.rs +++ b/frame/support/src/storage/hashed.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Operation on runtime storage using hashed keys. diff --git a/frame/support/src/storage/migration.rs b/frame/support/src/storage/migration.rs index 264c3c644e144ee6d042e6323ee915a53f61acb9..75f90ba7b06cc2d9a36e7f48e3a9453aeed9923c 100644 --- a/frame/support/src/storage/migration.rs +++ b/frame/support/src/storage/migration.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Some utilities for helping access storage with arbitrary key types. diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs index cdbdcbc6ffa5284c839b760d588e2f22e30a5f6f..6d0ef91ce1e17e4f81c69a624827c9a252d1fa7b 100644 --- a/frame/support/src/storage/mod.rs +++ b/frame/support/src/storage/mod.rs @@ -1,24 +1,25 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Stuff to do with the runtime's storage. use sp_std::{prelude::*, marker::PhantomData}; use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode}; -use crate::{traits::Len, hash::{Twox128, StorageHasher}}; +use crate::hash::{Twox128, StorageHasher}; use sp_runtime::generic::{Digest, DigestItem}; pub mod unhashed; @@ -105,11 +106,20 @@ pub trait StorageValue { EncodeLikeItem: EncodeLike, T: StorageAppend; - /// Read the length of the value in a fast way, without decoding the entire value. + /// Read the length of the storage value without decoding the entire value. + /// + /// `T` is required to implement [`StorageDecodeLength`]. + /// + /// If the value does not exists or it fails to decode the length, `None` is returned. + /// Otherwise `Some(len)` is returned. + /// + /// # Warning /// - /// `T` is required to implement `Codec::DecodeLength`. - fn decode_len() -> Result - where T: codec::DecodeLength + Len; + /// `None` does not mean that `get()` does not return a value. The default value is completly + /// ignored by this function. + fn decode_len() -> Option where T: StorageDecodeLength { + T::decode_len(&Self::hashed_key()) + } } /// A strongly-typed map in storage. @@ -175,15 +185,23 @@ pub trait StorageMap { EncodeLikeItem: EncodeLike, V: StorageAppend; - /// Read the length of the value in a fast way, without decoding the entire value. + /// Read the length of the storage value without decoding the entire value under the + /// given `key`. + /// + /// `V` is required to implement [`StorageDecodeLength`]. + /// + /// If the value does not exists or it fails to decode the length, `None` is returned. + /// Otherwise `Some(len)` is returned. /// - /// `T` is required to implement `Codec::DecodeLength`. + /// # Warning /// - /// Note that `0` is returned as the default value if no encoded value exists at the given key. - /// Therefore, this function cannot be used as a sign of _existence_. use the `::contains_key()` - /// function for this purpose. - fn decode_len>(key: KeyArg) -> Result - where V: codec::DecodeLength + Len; + /// `None` does not mean that `get()` does not return a value. The default value is completly + /// ignored by this function. + fn decode_len>(key: KeyArg) -> Option + where V: StorageDecodeLength, + { + V::decode_len(&Self::hashed_key_for(key)) + } /// Migrate an item with the given `key` from a defunct `OldHasher` to the current hasher. /// @@ -348,18 +366,26 @@ pub trait StorageDoubleMap { EncodeLikeItem: EncodeLike, V: StorageAppend; - /// Read the length of the value in a fast way, without decoding the entire value. + /// Read the length of the storage value without decoding the entire value under the + /// given `key1` and `key2`. /// - /// `V` is required to implement `Codec::DecodeLength`. + /// `V` is required to implement [`StorageDecodeLength`]. /// - /// Note that `0` is returned as the default value if no encoded value exists at the given key. - /// Therefore, this function cannot be used as a sign of _existence_. use the `::contains_key()` - /// function for this purpose. - fn decode_len(key1: KArg1, key2: KArg2) -> Result + /// If the value does not exists or it fails to decode the length, `None` is returned. + /// Otherwise `Some(len)` is returned. + /// + /// # Warning + /// + /// `None` does not mean that `get()` does not return a value. The default value is completly + /// ignored by this function. + fn decode_len(key1: KArg1, key2: KArg2) -> Option where KArg1: EncodeLike, KArg2: EncodeLike, - V: codec::DecodeLength + Len; + V: StorageDecodeLength, + { + V::decode_len(&Self::hashed_key_for(key1, key2)) + } /// Migrate an item with the given `key1` and `key2` from defunct `OldHasher1` and /// `OldHasher2` to the current hashers. @@ -493,7 +519,29 @@ pub trait StoragePrefixedMap { /// This trait is sealed. pub trait StorageAppend: private::Sealed {} -/// Provides `Sealed` trait to prevent implementing trait `StorageAppend` outside of this crate. +/// Marker trait that will be implemented for types that support to decode their length in an +/// effificent way. It is expected that the length is at the beginning of the encoded object +/// and that the length is a `Compact`. +/// +/// This trait is sealed. +pub trait StorageDecodeLength: private::Sealed + codec::DecodeLength { + /// Decode the length of the storage value at `key`. + /// + /// This function assumes that the length is at the beginning of the encoded object + /// and is a `Compact`. + /// + /// Returns `None` if the storage value does not exist or the decoding failed. + fn decode_len(key: &[u8]) -> Option { + // `Compact` is 5 bytes in maximum. + let mut data = [0u8; 5]; + let len = sp_io::storage::read(key, &mut data, 0)?; + let len = data.len().min(len as usize); + ::len(&data[..len]).ok() + } +} + +/// Provides `Sealed` trait to prevent implementing trait `StorageAppend` & `StorageDecodeLength` +/// outside of this crate. mod private { use super::*; @@ -504,6 +552,7 @@ mod private { } impl StorageAppend for Vec {} +impl StorageDecodeLength for Vec {} /// We abuse the fact that SCALE does not put any marker into the encoding, i.e. /// we only encode the internal vec and we can append to this vec. We have a test that ensures diff --git a/frame/support/src/storage/unhashed.rs b/frame/support/src/storage/unhashed.rs index 1ecf46ef1864708b53e7e19073768196314be5b4..34b146b86f6ba0ecdf75e0bf3467ac76400f085d 100644 --- a/frame/support/src/storage/unhashed.rs +++ b/frame/support/src/storage/unhashed.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Operation on unhashed runtime storage. diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 0230937fc49c7a10fa9dce16cb80b9c6fd43d725..0b48ac7f410e8d9a3ef825e5c0090f0ffce8db31 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Traits for FRAME. //! @@ -29,8 +30,19 @@ use sp_runtime::{ }; use crate::dispatch::Parameter; use crate::storage::StorageMap; +use crate::weights::Weight; use impl_trait_for_tuples::impl_for_tuples; +/// Simple trait for providing a filter over a reference to some type. +pub trait Filter { + /// Determine if a given value should be allowed through the filter (returns `true`) or not. + fn filter(_: &T) -> bool; +} + +impl Filter for () { + fn filter(_: &T) -> bool { true } +} + /// An abstraction of a value stored within storage, but possibly as part of a larger composite /// item. pub trait StoredMap { @@ -147,12 +159,19 @@ pub trait EstimateNextSessionRotation { /// /// None should be returned if the estimation fails to come to an answer fn estimate_next_session_rotation(now: BlockNumber) -> Option; + + /// Return the weight of calling `estimate_next_session_rotation` + fn weight(now: BlockNumber) -> Weight; } impl EstimateNextSessionRotation for () { fn estimate_next_session_rotation(_: BlockNumber) -> Option { Default::default() } + + fn weight(_: BlockNumber) -> Weight { + 0 + } } /// Something that can estimate at which block the next `new_session` will be triggered. This must @@ -160,12 +179,19 @@ impl EstimateNextSessionRotation for () { pub trait EstimateNextNewSession { /// Return the block number at which the next new session is estimated to happen. fn estimate_next_new_session(now: BlockNumber) -> Option; + + /// Return the weight of calling `estimate_next_new_session` + fn weight(now: BlockNumber) -> Weight; } impl EstimateNextNewSession for () { fn estimate_next_new_session(_: BlockNumber) -> Option { Default::default() } + + fn weight(_: BlockNumber) -> Weight { + 0 + } } /// Anything that can have a `::len()` method. diff --git a/frame/support/src/unsigned.rs b/frame/support/src/unsigned.rs index 3bc6f692affc20426f196792666fe1c0413c146f..16c434fe638bca64c9f1dd6a266af052852d9207 100644 --- a/frame/support/src/unsigned.rs +++ b/frame/support/src/unsigned.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[doc(hidden)] pub use crate::sp_runtime::traits::ValidateUnsigned; diff --git a/frame/support/src/weights.rs b/frame/support/src/weights.rs index 1d3862b60fb7c22b68509d1fe0d413faac387d7a..dd80f8d8a8e6c406fc450e623245550e028e1621 100644 --- a/frame/support/src/weights.rs +++ b/frame/support/src/weights.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Primitives for transaction weighting. //! @@ -133,7 +134,10 @@ use sp_runtime::{ traits::SignedExtension, generic::{CheckedExtrinsic, UncheckedExtrinsic}, }; -use crate::dispatch::{DispatchErrorWithPostInfo, DispatchError}; +use crate::dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, DispatchError}; +use sp_runtime::traits::SaturatedConversion; +use sp_arithmetic::{Perbill, traits::{BaseArithmetic, Saturating}}; +use smallvec::{smallvec, SmallVec}; /// Re-export priority as type pub use sp_runtime::transaction_validity::TransactionPriority; @@ -268,18 +272,27 @@ pub struct PostDispatchInfo { impl PostDispatchInfo { /// Calculate how much (if any) weight was not used by the `Dispatchable`. pub fn calc_unspent(&self, info: &DispatchInfo) -> Weight { + info.weight - self.calc_actual_weight(info) + } + + /// Calculate how much weight was actually spent by the `Dispatchable`. + pub fn calc_actual_weight(&self, info: &DispatchInfo) -> Weight { if let Some(actual_weight) = self.actual_weight { - if actual_weight >= info.weight { - 0 - } else { - info.weight - actual_weight - } + actual_weight.min(info.weight) } else { - 0 + info.weight } } } +/// Extract the actual weight from a dispatch result if any or fall back to the default weight. +pub fn extract_actual_weight(result: &DispatchResultWithPostInfo, info: &DispatchInfo) -> Weight { + match result { + Ok(post_info) => &post_info, + Err(err) => &err.post_info, + }.calc_actual_weight(info) +} + impl From> for PostDispatchInfo { fn from(actual_weight: Option) -> Self { Self { @@ -521,6 +534,90 @@ impl RuntimeDbWeight { } } +/// One coefficient and its position in the `WeightToFeePolynomial`. +/// +/// One term of polynomial is calculated as: +/// +/// ```ignore +/// coeff_integer * x^(degree) + coeff_frac * x^(degree) +/// ``` +/// +/// The `negative` value encodes whether the term is added or substracted from the +/// overall polynomial result. +#[derive(Clone, Encode, Decode)] +pub struct WeightToFeeCoefficient { + /// The integral part of the coefficient. + pub coeff_integer: Balance, + /// The fractional part of the coefficient. + pub coeff_frac: Perbill, + /// True iff the coefficient should be interpreted as negative. + pub negative: bool, + /// Degree/exponent of the term. + pub degree: u8, +} + +/// A list of coefficients that represent one polynomial. +pub type WeightToFeeCoefficients = SmallVec<[WeightToFeeCoefficient; 4]>; + +/// A trait that describes the weight to fee calculation as polynomial. +/// +/// An implementor should only implement the `polynomial` function. +pub trait WeightToFeePolynomial { + /// The type that is returned as result from polynomial evaluation. + type Balance: BaseArithmetic + From + Copy; + + /// Returns a polynomial that describes the weight to fee conversion. + /// + /// This is the only function that should be manually implemented. Please note + /// that all calculation is done in the probably unsigned `Balance` type. This means + /// that the order of coefficients is important as putting the negative coefficients + /// first will most likely saturate the result to zero mid evaluation. + fn polynomial() -> WeightToFeeCoefficients; + + /// Calculates the fee from the passed `weight` according to the `polynomial`. + /// + /// This should not be overriden in most circumstances. Calculation is done in the + /// `Balance` type and never overflows. All evaluation is saturating. + fn calc(weight: &Weight) -> Self::Balance { + Self::polynomial().iter().fold(Self::Balance::saturated_from(0u32), |mut acc, args| { + let w = Self::Balance::saturated_from(*weight).saturating_pow(args.degree.into()); + + // The sum could get negative. Therefore we only sum with the accumulator. + // The Perbill Mul implementation is non overflowing. + let frac = args.coeff_frac * w; + let integer = args.coeff_integer.saturating_mul(w); + + if args.negative { + acc = acc.saturating_sub(frac); + acc = acc.saturating_sub(integer); + } else { + acc = acc.saturating_add(frac); + acc = acc.saturating_add(integer); + } + + acc + }) + } +} + +/// Implementor of `WeightToFeePolynomial` that maps one unit of weight to one unit of fee. +pub struct IdentityFee(sp_std::marker::PhantomData); + +impl WeightToFeePolynomial for IdentityFee where + T: BaseArithmetic + From + Copy +{ + type Balance = T; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec!(WeightToFeeCoefficient { + coeff_integer: 1u32.into(), + coeff_frac: Perbill::zero(), + negative: false, + degree: 1, + }) + } +} + #[cfg(test)] #[allow(dead_code)] mod tests { @@ -615,4 +712,91 @@ mod tests { assert_eq!(Call::::f21().get_dispatch_info().weight, 45600); assert_eq!(Call::::f2().get_dispatch_info().class, DispatchClass::Normal); } + + #[test] + fn extract_actual_weight_works() { + let pre = DispatchInfo { + weight: 1000, + .. Default::default() + }; + assert_eq!(extract_actual_weight(&Ok(Some(7).into()), &pre), 7); + assert_eq!(extract_actual_weight(&Ok(Some(1000).into()), &pre), 1000); + assert_eq!( + extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(9)), &pre), + 9 + ); + } + + #[test] + fn extract_actual_weight_caps_at_pre_weight() { + let pre = DispatchInfo { + weight: 1000, + .. Default::default() + }; + assert_eq!(extract_actual_weight(&Ok(Some(1250).into()), &pre), 1000); + assert_eq!( + extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(1300)), &pre), + 1000 + ); + } + + type Balance = u64; + + // 0.5x^3 + 2.333x2 + 7x - 10_000 + struct Poly; + impl WeightToFeePolynomial for Poly { + type Balance = Balance; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![ + WeightToFeeCoefficient { + coeff_integer: 0, + coeff_frac: Perbill::from_fraction(0.5), + negative: false, + degree: 3 + }, + WeightToFeeCoefficient { + coeff_integer: 2, + coeff_frac: Perbill::from_rational_approximation(1u32, 3u32), + negative: false, + degree: 2 + }, + WeightToFeeCoefficient { + coeff_integer: 7, + coeff_frac: Perbill::zero(), + negative: false, + degree: 1 + }, + WeightToFeeCoefficient { + coeff_integer: 10_000, + coeff_frac: Perbill::zero(), + negative: true, + degree: 0 + }, + ] + } + } + + #[test] + fn polynomial_works() { + assert_eq!(Poly::calc(&100), 514033); + assert_eq!(Poly::calc(&10_123), 518917034928); + } + + #[test] + fn polynomial_does_not_underflow() { + assert_eq!(Poly::calc(&0), 0); + } + + #[test] + fn polynomial_does_not_overflow() { + assert_eq!(Poly::calc(&Weight::max_value()), Balance::max_value() - 10_000); + } + + #[test] + fn identity_fee_works() { + assert_eq!(IdentityFee::::calc(&0), 0); + assert_eq!(IdentityFee::::calc(&50), 50); + assert_eq!(IdentityFee::::calc(&Weight::max_value()), Balance::max_value()); + } } diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml index 77899788d2d96e6f876e97d11a9c4f31408146a4..6685f65551fc6a8436f460b9d5eacdb3f4bcaa7e 100644 --- a/frame/support/test/Cargo.toml +++ b/frame/support/test/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-support-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -14,12 +14,12 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-io ={ path = "../../../primitives/io", default-features = false , version = "2.0.0-dev"} -sp-state-machine = { version = "0.8.0-dev", optional = true, path = "../../../primitives/state-machine" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../" } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/inherents" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../../primitives/io", default-features = false } +sp-state-machine = { version = "0.8.0-rc2", optional = true, path = "../../../primitives/state-machine" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/inherents" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/core" } trybuild = "1.0.17" pretty_assertions = "0.6.1" rustversion = "1.0.0" diff --git a/frame/support/test/src/lib.rs b/frame/support/test/src/lib.rs index f62f5522680ebd724ed991f4ec2074a308df6c1b..c0baf448eed850511b2cdc33e307d6758739da8f 100644 --- a/frame/support/test/src/lib.rs +++ b/frame/support/test/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Test crate for frame_support. Allow to make use of `frame_support::decl_storage`. //! See tests directory. diff --git a/frame/support/test/tests/construct_runtime_ui.rs b/frame/support/test/tests/construct_runtime_ui.rs index d094d73ba54e9a7de4dded597c5dd9f4aedfa97d..e1624c76830ae21849cd8dd6329476c779569bd6 100644 --- a/frame/support/test/tests/construct_runtime_ui.rs +++ b/frame/support/test/tests/construct_runtime_ui.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::env; diff --git a/frame/support/test/tests/decl_error.rs b/frame/support/test/tests/decl_error.rs index eb14ae7502fe3bbcd773575e0f776dea26e41448..9536d4e8195d4830bc00144985902961fca7ea59 100644 --- a/frame/support/test/tests/decl_error.rs +++ b/frame/support/test/tests/decl_error.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![recursion_limit="128"] diff --git a/frame/support/test/tests/decl_storage.rs b/frame/support/test/tests/decl_storage.rs index 77e538625a4fa82b011fac6a69f0167ac14f6df1..cda1d810d225ca55cfed587cc9322cf47566c999 100644 --- a/frame/support/test/tests/decl_storage.rs +++ b/frame/support/test/tests/decl_storage.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[cfg(test)] // Do not complain about unused `dispatch` and `dispatch_aux`. @@ -593,38 +594,40 @@ mod test_append_and_len { }); } + // `decode_len` should always return `None` for default assigments + // in `decl_storage!`. #[test] - fn len_works_for_default() { + fn len_works_ignores_default_assignment() { TestExternalities::default().execute_with(|| { // vec assert_eq!(JustVec::get(), vec![]); - assert_eq!(JustVec::decode_len(), Ok(0)); + assert_eq!(JustVec::decode_len(), None); assert_eq!(JustVecWithDefault::get(), vec![6, 9]); - assert_eq!(JustVecWithDefault::decode_len(), Ok(2)); + assert_eq!(JustVecWithDefault::decode_len(), None); assert_eq!(OptionVec::get(), None); - assert_eq!(OptionVec::decode_len(), Ok(0)); + assert_eq!(OptionVec::decode_len(), None); // map assert_eq!(MapVec::get(0), vec![]); - assert_eq!(MapVec::decode_len(0), Ok(0)); + assert_eq!(MapVec::decode_len(0), None); assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); - assert_eq!(MapVecWithDefault::decode_len(0), Ok(2)); + assert_eq!(MapVecWithDefault::decode_len(0), None); assert_eq!(OptionMapVec::get(0), None); - assert_eq!(OptionMapVec::decode_len(0), Ok(0)); + assert_eq!(OptionMapVec::decode_len(0), None); // Double map assert_eq!(DoubleMapVec::get(0, 0), vec![]); - assert_eq!(DoubleMapVec::decode_len(0, 1), Ok(0)); + assert_eq!(DoubleMapVec::decode_len(0, 1), None); assert_eq!(DoubleMapVecWithDefault::get(0, 0), vec![6, 9]); - assert_eq!(DoubleMapVecWithDefault::decode_len(0, 1), Ok(2)); + assert_eq!(DoubleMapVecWithDefault::decode_len(0, 1), None); assert_eq!(OptionDoubleMapVec::get(0, 0), None); - assert_eq!(OptionDoubleMapVec::decode_len(0, 1), Ok(0)); + assert_eq!(OptionDoubleMapVec::decode_len(0, 1), None); }); } } diff --git a/frame/support/test/tests/decl_storage_ui.rs b/frame/support/test/tests/decl_storage_ui.rs index 3aee5e98664131ee4d7f257016c601e10fe0f00d..d771b6e0eef83cd048a3decdd0d953a2f415f78d 100644 --- a/frame/support/test/tests/decl_storage_ui.rs +++ b/frame/support/test/tests/decl_storage_ui.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[test] fn decl_storage_ui() { diff --git a/frame/support/test/tests/decl_storage_ui/config_duplicate.rs b/frame/support/test/tests/decl_storage_ui/config_duplicate.rs index 0f2759e740d7ddb81fc2edf244dab3b7422dd8c1..4d510da9f893652be1381babff9fe09980baf753 100644 --- a/frame/support/test/tests/decl_storage_ui/config_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/config_duplicate.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub trait Trait { type Origin; diff --git a/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr index 761e3f3b7982492444854ec669094eb948f0c409..61f7c0bbe64a5ae48c4353a069953a34b675b633 100644 --- a/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr +++ b/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr @@ -1,5 +1,5 @@ error: `config()`/`get()` with the same name already defined. - --> $DIR/config_duplicate.rs:29:21 + --> $DIR/config_duplicate.rs:30:21 | -29 | pub Value2 config(value): u32; +30 | pub Value2 config(value): u32; | ^^^^^ diff --git a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs index a4e0158d5c5c50733905c8c8795f72416512c878..49897e625186855c41b1848036116df058a9d146 100644 --- a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub trait Trait { type Origin; diff --git a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr index 34d040f4e14f19a8fbfc1e904675ec6dacc5e963..02e7d41080339069a9a20224d7bf4baad2ff86e5 100644 --- a/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr +++ b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr @@ -1,5 +1,5 @@ error: `config()`/`get()` with the same name already defined. - --> $DIR/config_get_duplicate.rs:29:21 + --> $DIR/config_get_duplicate.rs:30:21 | -29 | pub Value2 config(value): u32; +30 | pub Value2 config(value): u32; | ^^^^^ diff --git a/frame/support/test/tests/decl_storage_ui/get_duplicate.rs b/frame/support/test/tests/decl_storage_ui/get_duplicate.rs index 9edbc25bf9d8327ae36339cb1d595b8713fdb572..2fa78f4d17c562d6aa3817fb3fd58cb4a1d9d6d2 100644 --- a/frame/support/test/tests/decl_storage_ui/get_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/get_duplicate.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub trait Trait { type Origin; diff --git a/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr index 130244196f67e03bb40de703fbb127d7bdecbfc8..d9ce420a6f2143ac015c5a9aa33b5153954e1d94 100644 --- a/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr +++ b/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr @@ -1,5 +1,5 @@ error: `config()`/`get()` with the same name already defined. - --> $DIR/get_duplicate.rs:29:21 + --> $DIR/get_duplicate.rs:30:21 | -29 | pub Value2 get(fn value) config(): u32; +30 | pub Value2 get(fn value) config(): u32; | ^^^^^ diff --git a/frame/support/test/tests/final_keys.rs b/frame/support/test/tests/final_keys.rs index ae23c5a64c200af647f0cd4387495742026ccc6c..e88389ade772bf0c5189f47ff6521fbbb508dfa6 100644 --- a/frame/support/test/tests/final_keys.rs +++ b/frame/support/test/tests/final_keys.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use frame_support::storage::unhashed; use codec::Encode; diff --git a/frame/support/test/tests/genesisconfig.rs b/frame/support/test/tests/genesisconfig.rs index bccffb737476b47fa9b8ebdccfce88139fb9370d..78b841d29501728e8e2eac048e6f2b465f19034b 100644 --- a/frame/support/test/tests/genesisconfig.rs +++ b/frame/support/test/tests/genesisconfig.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. pub trait Trait { type BlockNumber: codec::Codec + codec::EncodeLike + Default; diff --git a/frame/support/test/tests/instance.rs b/frame/support/test/tests/instance.rs index 5cb7fa1972a05f86ff13b3776f080368153431d4..45e280902a268b0d0a3c8d4d7e8e53ac846f9784 100644 --- a/frame/support/test/tests/instance.rs +++ b/frame/support/test/tests/instance.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![recursion_limit="128"] diff --git a/frame/support/test/tests/issue2219.rs b/frame/support/test/tests/issue2219.rs index 8d8152a5ad0f35b7b2485acb13d49c56b2075392..cd357ba2667cb18c096a61be827311badb4b8c34 100644 --- a/frame/support/test/tests/issue2219.rs +++ b/frame/support/test/tests/issue2219.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use frame_support::sp_runtime::generic; use frame_support::sp_runtime::traits::{BlakeTwo256, Block as _, Verify}; diff --git a/frame/support/test/tests/reserved_keyword.rs b/frame/support/test/tests/reserved_keyword.rs index 6f2bbb47474152b451d7cfe7667a099a02c50e65..382b2e498741fd6740dc7b1c94537706ce13ffac 100644 --- a/frame/support/test/tests/reserved_keyword.rs +++ b/frame/support/test/tests/reserved_keyword.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[rustversion::attr(not(stable), ignore)] #[test] diff --git a/frame/support/test/tests/reserved_keyword/on_initialize.stderr b/frame/support/test/tests/reserved_keyword/on_initialize.stderr index e899ef5d789426c620a9c92f7190a2ac5fdabd4f..dbe07195e89ddff6fbe0390a583cda4d553d13cb 100644 --- a/frame/support/test/tests/reserved_keyword/on_initialize.stderr +++ b/frame/support/test/tests/reserved_keyword/on_initialize.stderr @@ -2,38 +2,38 @@ error: Invalid call fn name: `on_finalize`, name is reserved and doesn't match e --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `on_initialize`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `on_runtime_upgrade`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `offchain_worker`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: Invalid call fn name: `deposit_event`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. --> $DIR/on_initialize.rs:31:1 | 31 | reserved!(on_finalize on_initialize on_runtime_upgrade offchain_worker deposit_event); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/frame/support/test/tests/system.rs b/frame/support/test/tests/system.rs index c7f60117bc526ec4e96745c9f74379e913b43316..821224d0a29cfd2ed7fa6c3f264d9f007832ede9 100644 --- a/frame/support/test/tests/system.rs +++ b/frame/support/test/tests/system.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use frame_support::codec::{Encode, Decode, EncodeLike}; diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml index 0e90009a16690799ed5e3a65049ef1c47267dc32..09289519292211ceddaa5465ee63fbb3353bdf8a 100644 --- a/frame/system/Cargo.toml +++ b/frame/system/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-system" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME system module" @@ -14,18 +14,18 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { path = "../../primitives/io", default-features = false, version = "2.0.0-dev"} -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-version = { version = "2.0.0-dev", default-features = false, path = "../../primitives/version" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io", default-features = false } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-version = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/version" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } impl-trait-for-tuples = "0.1.3" [dev-dependencies] criterion = "0.2.11" -sp-externalities = { version = "0.8.0-dev", path = "../../primitives/externalities" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../test-utils/runtime/client" } +sp-externalities = { version = "0.8.0-rc2", path = "../../primitives/externalities" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../test-utils/runtime/client" } [features] default = ["std"] diff --git a/frame/system/benches/bench.rs b/frame/system/benches/bench.rs index 6594862e5c6d56647620b14218cc4e05d9850764..95b9b88c705fb41c39af67700ac1b005804867d7 100644 --- a/frame/system/benches/bench.rs +++ b/frame/system/benches/bench.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use criterion::{Criterion, criterion_group, criterion_main, black_box}; use frame_system as system; @@ -75,6 +76,7 @@ impl system::Trait for Runtime { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/frame/system/benchmarking/Cargo.toml b/frame/system/benchmarking/Cargo.toml index 0518bd705dc2658a96e94b1f7043832c1d1cf439..14fb5206fe12792a94d075614d5b69e6b9b4d071 100644 --- a/frame/system/benchmarking/Cargo.toml +++ b/frame/system/benchmarking/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-system-benchmarking" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME System benchmarking" @@ -13,16 +13,16 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/runtime" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../../benchmarking" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../../system" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../../support" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../../primitives/core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/runtime" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../../benchmarking" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../../system" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../../support" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../../primitives/core" } [dev-dependencies] serde = { version = "1.0.101" } -sp-io ={ path = "../../../primitives/io", version = "2.0.0-dev"} +sp-io ={ version = "2.0.0-rc2", path = "../../../primitives/io" } [features] default = ["std"] diff --git a/frame/system/benchmarking/src/lib.rs b/frame/system/benchmarking/src/lib.rs index 22e6dba842741fc0deccb8230605af74bd8447e4..049fa5298c677076702256735e6017b994279d0d 100644 --- a/frame/system/benchmarking/src/lib.rs +++ b/frame/system/benchmarking/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Benchmarks for Utility Pallet diff --git a/frame/system/benchmarking/src/mock.rs b/frame/system/benchmarking/src/mock.rs index 1e72665c1557910f7eaccc35c3f5237170177c95..1e904302e3b9ee6ae31d3d7d41f39443fdb2ff28 100644 --- a/frame/system/benchmarking/src/mock.rs +++ b/frame/system/benchmarking/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock file for system benchmarking. @@ -65,6 +66,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); type AvailableBlockRatio = (); type MaximumBlockLength = (); type Version = (); diff --git a/frame/system/rpc/runtime-api/Cargo.toml b/frame/system/rpc/runtime-api/Cargo.toml index 2097e112663f51190b85210df9a29c9d3730f536..ef1cc7abac4311f3b41c1b198bad1b723b98f84b 100644 --- a/frame/system/rpc/runtime-api/Cargo.toml +++ b/frame/system/rpc/runtime-api/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "frame-system-rpc-runtime-api" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Runtime API definition required by System RPC extensions." @@ -12,7 +12,7 @@ description = "Runtime API definition required by System RPC extensions." targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-api = { version = "2.0.0-dev", default-features = false, path = "../../../../primitives/api" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../../../../primitives/api" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } [features] diff --git a/frame/system/rpc/runtime-api/src/lib.rs b/frame/system/rpc/runtime-api/src/lib.rs index 3b05bd162468e10e9a1d59712c2685332a5675bf..0ead94aabe016b739c4c8812618b1248d3116723 100644 --- a/frame/system/rpc/runtime-api/src/lib.rs +++ b/frame/system/rpc/runtime-api/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime API definition required by System RPC extensions. //! diff --git a/frame/system/src/accounts.scale b/frame/system/src/accounts.scale deleted file mode 100644 index bfd7e6277f20c53ceb1d664235bb6af18ec538ed..0000000000000000000000000000000000000000 Binary files a/frame/system/src/accounts.scale and /dev/null differ diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 8346b727b254bcd867d129fbf94a5a4ed11c8e10..2221b0591d1a8fb206566c53bbe3d39b64114497 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # System Module //! @@ -53,7 +54,9 @@ //! - [`CheckEra`]: Checks the era of the transaction. Contains a single payload of type `Era`. //! - [`CheckGenesis`]: Checks the provided genesis hash of the transaction. Must be a part of the //! signed payload of the transaction. -//! - [`CheckVersion`]: Checks that the runtime version is the same as the one encoded in the +//! - [`CheckSpecVersion`]: Checks that the runtime version is the same as the one used to sign the +//! transaction. +//! - [`CheckTxVersion`]: Checks that the transaction version is the same as the one used to sign the //! transaction. //! //! Lookup the runtime aggregator file (e.g. `node/runtime`) to see the full list of signed @@ -99,7 +102,7 @@ use sp_std::marker::PhantomData; use sp_std::fmt::Debug; use sp_version::RuntimeVersion; use sp_runtime::{ - RuntimeDebug, Perbill, DispatchOutcome, DispatchError, DispatchResult, + RuntimeDebug, Perbill, DispatchError, DispatchResult, generic::{self, Era}, transaction_validity::{ ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError, @@ -111,6 +114,7 @@ use sp_runtime::{ MaybeSerialize, MaybeSerializeDeserialize, MaybeMallocSizeOf, StaticLookup, One, Bounded, Dispatchable, DispatchInfoOf, PostDispatchInfoOf, }, + offchain::storage_lock::BlockNumberProvider, }; use sp_core::{ChangesTrieConfiguration, storage::well_known_keys}; @@ -123,8 +127,9 @@ use frame_support::{ }, weights::{ Weight, RuntimeDbWeight, DispatchInfo, PostDispatchInfo, DispatchClass, - FunctionOf, Pays, - } + FunctionOf, Pays, extract_actual_weight, + }, + dispatch::DispatchResultWithPostInfo, }; use codec::{Encode, Decode, FullCodec, EncodeLike}; @@ -208,6 +213,11 @@ pub trait Trait: 'static + Eq + Clone { /// The base weight of an Extrinsic in the block, independent of the of extrinsic being executed. type ExtrinsicBaseWeight: Get; + /// The maximal weight of a single Extrinsic. This should be set to at most + /// `MaximumBlockWeight - AverageOnInitializeWeight`. The limit only applies to extrinsics + /// containing `Normal` dispatch class calls. + type MaximumExtrinsicWeight: Get; + /// The maximum length of a block (in bytes). type MaximumBlockLength: Get; @@ -357,6 +367,60 @@ impl From for LastRuntimeUpgradeInfo { } } +/// An object to track the currently used extrinsic weight in a block. +#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)] +pub struct ExtrinsicsWeight { + normal: Weight, + operational: Weight, +} + +impl ExtrinsicsWeight { + /// Returns the total weight consumed by all extrinsics in the block. + pub fn total(&self) -> Weight { + self.normal.saturating_add(self.operational) + } + + /// Add some weight of a specific dispatch class, saturating at the numeric bounds of `Weight`. + pub fn add(&mut self, weight: Weight, class: DispatchClass) { + let value = self.get_mut(class); + *value = value.saturating_add(weight); + } + + /// Try to add some weight of a specific dispatch class, returning Err(()) if overflow would occur. + pub fn checked_add(&mut self, weight: Weight, class: DispatchClass) -> Result<(), ()> { + let value = self.get_mut(class); + *value = value.checked_add(weight).ok_or(())?; + Ok(()) + } + + /// Subtract some weight of a specific dispatch class, saturating at the numeric bounds of `Weight`. + pub fn sub(&mut self, weight: Weight, class: DispatchClass) { + let value = self.get_mut(class); + *value = value.saturating_sub(weight); + } + + /// Get the current weight of a specific dispatch class. + pub fn get(&self, class: DispatchClass) -> Weight { + match class { + DispatchClass::Operational => self.operational, + DispatchClass::Normal | DispatchClass::Mandatory => self.normal, + } + } + + /// Get a mutable reference to the current weight of a specific dispatch class. + fn get_mut(&mut self, class: DispatchClass) -> &mut Weight { + match class { + DispatchClass::Operational => &mut self.operational, + DispatchClass::Normal | DispatchClass::Mandatory => &mut self.normal, + } + } + + /// Set the weight of a specific dispatch class. + pub fn put(&mut self, new: Weight, class: DispatchClass) { + *self.get_mut(class) = new; + } +} + decl_storage! { trait Store for Module as System { /// The full account information for a particular account ID. @@ -366,8 +430,8 @@ decl_storage! { /// Total extrinsics count for the current block. ExtrinsicCount: Option; - /// Total weight for all extrinsics put together, for the current block. - AllExtrinsicsWeight: Option; + /// The current weight for the block. + BlockWeight get(fn block_weight): ExtrinsicsWeight; /// Total length (in bytes) for all extrinsics put together, for the current block. AllExtrinsicsLen: Option; @@ -481,6 +545,9 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { type Error = Error; + /// The maximum number of blocks to allow in mortal eras. + const BlockHashCount: T::BlockNumber = T::BlockHashCount::get(); + /// The maximum weight of a block. const MaximumBlockWeight: Weight = T::MaximumBlockWeight::get(); @@ -912,11 +979,6 @@ impl Module { ExtrinsicCount::get().unwrap_or_default() } - /// Gets a total weight of all executed extrinsics. - pub fn all_extrinsics_weight() -> Weight { - AllExtrinsicsWeight::get().unwrap_or_default() - } - pub fn all_extrinsics_len() -> u32 { AllExtrinsicsLen::get().unwrap_or_default() } @@ -936,12 +998,10 @@ impl Module { /// of block weight is more than the block weight limit. This is what the _unchecked_. /// /// Another potential use-case could be for the `on_initialize` and `on_finalize` hooks. - /// - /// If no previous weight exists, the function initializes the weight to zero. - pub fn register_extra_weight_unchecked(weight: Weight) { - let current_weight = AllExtrinsicsWeight::get().unwrap_or_default(); - let next_weight = current_weight.saturating_add(weight); - AllExtrinsicsWeight::put(next_weight); + pub fn register_extra_weight_unchecked(weight: Weight, class: DispatchClass) { + BlockWeight::mutate(|current_weight| { + current_weight.add(weight, class); + }); } /// Start the execution of a particular block. @@ -961,6 +1021,10 @@ impl Module { >::insert(*number - One::one(), parent_hash); >::put(txs_root); + // Remove previous block data from storage + BlockWeight::kill(); + + // Kill inspectable storage entries in state when `InitKind::Full`. if let InitKind::Full = kind { >::kill(); EventCount::kill(); @@ -972,7 +1036,6 @@ impl Module { pub fn finalize() -> T::Header { ExecutionPhase::kill(); ExtrinsicCount::kill(); - AllExtrinsicsWeight::kill(); AllExtrinsicsLen::kill(); let number = >::take(); @@ -1062,7 +1125,9 @@ impl Module { /// Set the current block weight. This should only be used in some integration tests. #[cfg(any(feature = "std", test))] pub fn set_block_limits(weight: Weight, len: usize) { - AllExtrinsicsWeight::put(weight); + BlockWeight::mutate(|current_weight| { + current_weight.put(weight, DispatchClass::Normal) + }); AllExtrinsicsLen::put(len as u32); } @@ -1090,13 +1155,14 @@ impl Module { } /// To be called immediately after an extrinsic has been applied. - pub fn note_applied_extrinsic(r: &DispatchOutcome, _encoded_len: u32, info: DispatchInfo) { + pub fn note_applied_extrinsic(r: &DispatchResultWithPostInfo, mut info: DispatchInfo) { + info.weight = extract_actual_weight(r, &info); Self::deposit_event( match r { - Ok(()) => RawEvent::ExtrinsicSuccess(info), + Ok(_) => RawEvent::ExtrinsicSuccess(info), Err(err) => { sp_runtime::print(err); - RawEvent::ExtrinsicFailed(err.clone(), info) + RawEvent::ExtrinsicFailed(err.error, info) }, } ); @@ -1203,6 +1269,15 @@ impl Happened for CallKillAccount { } } +impl BlockNumberProvider for Module +{ + type BlockNumber = ::BlockNumber; + + fn current_block_number() -> Self::BlockNumber { + Module::::block_number() + } +} + // Implement StoredMap for a simple single-item, kill-account-on-remove system. This works fine for // storing a single item which is required to not be empty/default for the account to exist. // Anything more complex will need more sophisticated logic. @@ -1290,29 +1365,73 @@ impl CheckWeight where } } + /// Checks if the current extrinsic does not exceed `MaximumExtrinsicWeight` limit. + fn check_extrinsic_weight( + info: &DispatchInfoOf, + ) -> Result<(), TransactionValidityError> { + match info.class { + // Mandatory and Operational transactions does not + DispatchClass::Mandatory | DispatchClass::Operational => Ok(()), + DispatchClass::Normal => { + let maximum_weight = T::MaximumExtrinsicWeight::get(); + let extrinsic_weight = info.weight.saturating_add(T::ExtrinsicBaseWeight::get()); + if extrinsic_weight > maximum_weight { + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(()) + } + } + } + } + /// Checks if the current extrinsic can fit into the block with respect to block weight limits. /// /// Upon successes, it returns the new block weight as a `Result`. - fn check_weight( + fn check_block_weight( info: &DispatchInfoOf, - ) -> Result { - let current_weight = Module::::all_extrinsics_weight(); + ) -> Result { let maximum_weight = T::MaximumBlockWeight::get(); - let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_weight; - if info.class == DispatchClass::Mandatory { + let mut all_weight = Module::::block_weight(); + match info.class { // If we have a dispatch that must be included in the block, it ignores all the limits. - let extrinsic_weight = info.weight.saturating_add(T::ExtrinsicBaseWeight::get()); - let next_weight = current_weight.saturating_add(extrinsic_weight); - Ok(next_weight) - } else { - let extrinsic_weight = info.weight.checked_add(T::ExtrinsicBaseWeight::get()) - .ok_or(InvalidTransaction::ExhaustsResources)?; - let next_weight = current_weight.checked_add(extrinsic_weight) - .ok_or(InvalidTransaction::ExhaustsResources)?; - if next_weight > limit { - Err(InvalidTransaction::ExhaustsResources.into()) - } else { - Ok(next_weight) + DispatchClass::Mandatory => { + let extrinsic_weight = info.weight.saturating_add(T::ExtrinsicBaseWeight::get()); + all_weight.add(extrinsic_weight, DispatchClass::Mandatory); + Ok(all_weight) + }, + // If we have a normal dispatch, we follow all the normal rules and limits. + DispatchClass::Normal => { + let normal_limit = Self::get_dispatch_limit_ratio(DispatchClass::Normal) * maximum_weight; + let extrinsic_weight = info.weight.checked_add(T::ExtrinsicBaseWeight::get()) + .ok_or(InvalidTransaction::ExhaustsResources)?; + all_weight.checked_add(extrinsic_weight, DispatchClass::Normal) + .map_err(|_| InvalidTransaction::ExhaustsResources)?; + if all_weight.get(DispatchClass::Normal) > normal_limit { + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(all_weight) + } + }, + // If we have an operational dispatch, allow it if we have not used our full + // "operational space" (independent of existing fullness). + DispatchClass::Operational => { + let operational_limit = Self::get_dispatch_limit_ratio(DispatchClass::Operational) * maximum_weight; + let normal_limit = Self::get_dispatch_limit_ratio(DispatchClass::Normal) * maximum_weight; + let operational_space = operational_limit.saturating_sub(normal_limit); + + let extrinsic_weight = info.weight.checked_add(T::ExtrinsicBaseWeight::get()) + .ok_or(InvalidTransaction::ExhaustsResources)?; + all_weight.checked_add(extrinsic_weight, DispatchClass::Operational) + .map_err(|_| InvalidTransaction::ExhaustsResources)?; + + // If it would fit in normally, its okay + if all_weight.total() <= maximum_weight || + // If we have not used our operational space + all_weight.get(DispatchClass::Operational) <= operational_space { + Ok(all_weight) + } else { + Err(InvalidTransaction::ExhaustsResources.into()) + } } } } @@ -1359,9 +1478,11 @@ impl CheckWeight where len: usize, ) -> Result<(), TransactionValidityError> { let next_len = Self::check_block_length(info, len)?; - let next_weight = Self::check_weight(info)?; + let next_weight = Self::check_block_weight(info)?; + Self::check_extrinsic_weight(info)?; + AllExtrinsicsLen::put(next_len); - AllExtrinsicsWeight::put(next_weight); + BlockWeight::put(next_weight); Ok(()) } @@ -1372,9 +1493,12 @@ impl CheckWeight where info: &DispatchInfoOf, len: usize, ) -> TransactionValidity { - // ignore the next weight and length. If they return `Ok`, then it is below the limit. + // ignore the next length. If they return `Ok`, then it is below the limit. let _ = Self::check_block_length(info, len)?; - let _ = Self::check_weight(info)?; + // during validation we skip block limit check. Since the `validate_transaction` + // call runs on an empty block anyway, by this we prevent `on_initialize` weight + // consumption from causing false negatives. + Self::check_extrinsic_weight(info)?; Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) } @@ -1449,8 +1573,8 @@ impl SignedExtension for CheckWeight where let unspent = post_info.calc_unspent(info); if unspent > 0 { - AllExtrinsicsWeight::mutate(|weight| { - *weight = weight.map(|w| w.saturating_sub(unspent)); + BlockWeight::mutate(|current_weight| { + current_weight.sub(unspent, info.class); }) } @@ -1653,14 +1777,49 @@ impl SignedExtension for CheckGenesis { } } +/// Ensure the transaction version registered in the transaction is the same as at present. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckTxVersion(sp_std::marker::PhantomData); + +impl Debug for CheckTxVersion { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckTxVersion") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl CheckTxVersion { + /// Create new `SignedExtension` to check transaction version. + pub fn new() -> Self { + Self(sp_std::marker::PhantomData) + } +} + +impl SignedExtension for CheckTxVersion { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = u32; + type Pre = (); + const IDENTIFIER: &'static str = "CheckTxVersion"; + + fn additional_signed(&self) -> Result { + Ok(>::runtime_version().transaction_version) + } +} + /// Ensure the runtime version registered in the transaction is the same as at present. #[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckVersion(sp_std::marker::PhantomData); +pub struct CheckSpecVersion(sp_std::marker::PhantomData); -impl Debug for CheckVersion { +impl Debug for CheckSpecVersion { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "CheckVersion") + write!(f, "CheckSpecVersion") } #[cfg(not(feature = "std"))] @@ -1669,19 +1828,19 @@ impl Debug for CheckVersion { } } -impl CheckVersion { +impl CheckSpecVersion { /// Create new `SignedExtension` to check runtime version. pub fn new() -> Self { Self(sp_std::marker::PhantomData) } } -impl SignedExtension for CheckVersion { +impl SignedExtension for CheckSpecVersion { type AccountId = T::AccountId; type Call = ::Call; type AdditionalSigned = u32; type Pre = (); - const IDENTIFIER: &'static str = "CheckVersion"; + const IDENTIFIER: &'static str = "CheckSpecVersion"; fn additional_signed(&self) -> Result { Ok(>::runtime_version().spec_version) @@ -1710,7 +1869,10 @@ pub(crate) mod tests { use sp_std::cell::RefCell; use sp_core::H256; use sp_runtime::{traits::{BlakeTwo256, IdentityLookup, SignedExtension}, testing::Header, DispatchError}; - use frame_support::{impl_outer_origin, parameter_types, assert_ok}; + use frame_support::{ + impl_outer_origin, parameter_types, assert_ok, assert_noop, + weights::WithPostDispatchInfo, + }; impl_outer_origin! { pub enum Origin for Test where system = super {} @@ -1722,9 +1884,10 @@ pub(crate) mod tests { parameter_types! { pub const BlockHashCount: u64 = 10; pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumExtrinsicWeight: Weight = 768; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const MaximumBlockLength: u32 = 1024; - pub const Version: RuntimeVersion = RuntimeVersion { + pub Version: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("test"), impl_name: sp_version::create_runtime_str!("system-test"), authoring_version: 1, @@ -1774,12 +1937,13 @@ pub(crate) mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type Event = u16; + type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type DbWeight = DbWeight; type BlockExecutionWeight = BlockExecutionWeight; type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = Version; @@ -1789,25 +1953,15 @@ pub(crate) mod tests { type OnKilledAccount = RecordKilled; } - impl From> for u16 { - fn from(e: Event) -> u16 { - match e { - Event::::ExtrinsicSuccess(..) => 100, - Event::::ExtrinsicFailed(..) => 101, - Event::::CodeUpdated => 102, - _ => 103, - } - } - } - type System = Module; + type SysEvent = ::Event; const CALL: &::Call = &Call; fn new_test_ext() -> sp_io::TestExternalities { let mut ext: sp_io::TestExternalities = GenesisConfig::default().build_storage::().unwrap().into(); // Add to each test the initial weight of a block - ext.execute_with(|| System::register_extra_weight_unchecked(::BlockExecutionWeight::get())); + ext.execute_with(|| System::register_extra_weight_unchecked(::BlockExecutionWeight::get(), DispatchClass::Mandatory)); ext } @@ -1858,14 +2012,14 @@ pub(crate) mod tests { InitKind::Full, ); System::note_finished_extrinsics(); - System::deposit_event(1u16); + System::deposit_event(SysEvent::CodeUpdated); System::finalize(); assert_eq!( System::events(), vec![ EventRecord { phase: Phase::Finalization, - event: 1u16, + event: SysEvent::CodeUpdated, topics: vec![], } ] @@ -1878,22 +2032,131 @@ pub(crate) mod tests { &Default::default(), InitKind::Full, ); - System::deposit_event(32u16); + System::deposit_event(SysEvent::NewAccount(32)); System::note_finished_initialize(); - System::deposit_event(42u16); - System::note_applied_extrinsic(&Ok(()), 0, Default::default()); - System::note_applied_extrinsic(&Err(DispatchError::BadOrigin), 0, Default::default()); + System::deposit_event(SysEvent::KilledAccount(42)); + System::note_applied_extrinsic(&Ok(().into()), Default::default()); + System::note_applied_extrinsic( + &Err(DispatchError::BadOrigin.into()), + Default::default() + ); System::note_finished_extrinsics(); - System::deposit_event(3u16); + System::deposit_event(SysEvent::NewAccount(3)); System::finalize(); assert_eq!( System::events(), vec![ - EventRecord { phase: Phase::Initialization, event: 32u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(1), event: 101u16, topics: vec![] }, - EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } + EventRecord { + phase: Phase::Initialization, + event: SysEvent::NewAccount(32), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: SysEvent::KilledAccount(42), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: SysEvent::ExtrinsicSuccess(Default::default()), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: SysEvent::ExtrinsicFailed( + DispatchError::BadOrigin.into(), + Default::default() + ), + topics: vec![] + }, + EventRecord { + phase: Phase::Finalization, + event: SysEvent::NewAccount(3), + topics: vec![] + }, + ] + ); + }); + } + + #[test] + fn deposit_event_uses_actual_weight() { + new_test_ext().execute_with(|| { + System::initialize( + &1, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + System::note_finished_initialize(); + + let pre_info = DispatchInfo { + weight: 1000, + .. Default::default() + }; + System::note_applied_extrinsic( + &Ok(Some(300).into()), + pre_info, + ); + System::note_applied_extrinsic( + &Ok(Some(1000).into()), + pre_info, + ); + System::note_applied_extrinsic( + // values over the pre info should be capped at pre dispatch value + &Ok(Some(1200).into()), + pre_info, + ); + System::note_applied_extrinsic( + &Err(DispatchError::BadOrigin.with_weight(999)), + pre_info, + ); + + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: SysEvent::ExtrinsicSuccess( + DispatchInfo { + weight: 300, + .. Default::default() + }, + ), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: SysEvent::ExtrinsicSuccess( + DispatchInfo { + weight: 1000, + .. Default::default() + }, + ), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + event: SysEvent::ExtrinsicSuccess( + DispatchInfo { + weight: 1000, + .. Default::default() + }, + ), + topics: vec![] + }, + EventRecord { + phase: Phase::ApplyExtrinsic(3), + event: SysEvent::ExtrinsicFailed( + DispatchError::BadOrigin.into(), + DispatchInfo { + weight: 999, + .. Default::default() + }, + ), + topics: vec![] + }, ] ); }); @@ -1920,9 +2183,9 @@ pub(crate) mod tests { ]; // We deposit a few events with different sets of topics. - System::deposit_event_indexed(&topics[0..3], 1u16); - System::deposit_event_indexed(&topics[0..1], 2u16); - System::deposit_event_indexed(&topics[1..2], 3u16); + System::deposit_event_indexed(&topics[0..3], SysEvent::NewAccount(1)); + System::deposit_event_indexed(&topics[0..1], SysEvent::NewAccount(2)); + System::deposit_event_indexed(&topics[1..2], SysEvent::NewAccount(3)); System::finalize(); @@ -1932,17 +2195,17 @@ pub(crate) mod tests { vec![ EventRecord { phase: Phase::Finalization, - event: 1u16, + event: SysEvent::NewAccount(1), topics: topics[0..3].to_vec(), }, EventRecord { phase: Phase::Finalization, - event: 2u16, + event: SysEvent::NewAccount(2), topics: topics[0..1].to_vec(), }, EventRecord { phase: Phase::Finalization, - event: 3u16, + event: SysEvent::NewAccount(3), topics: topics[1..2].to_vec(), } ] @@ -2033,7 +2296,9 @@ pub(crate) mod tests { let len = 0_usize; let reset_check_weight = |i, f, s| { - AllExtrinsicsWeight::put(s); + BlockWeight::mutate(|current_weight| { + current_weight.put(s, DispatchClass::Normal) + }); let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, i, len); if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } }; @@ -2053,17 +2318,19 @@ pub(crate) mod tests { let len = 0_usize; // We allow 75% for normal transaction, so we put 25% - extrinsic base weight - AllExtrinsicsWeight::put(256 - ::ExtrinsicBaseWeight::get()); + BlockWeight::mutate(|current_weight| { + current_weight.put(256 - ::ExtrinsicBaseWeight::get(), DispatchClass::Normal) + }); let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); - assert_eq!(AllExtrinsicsWeight::get().unwrap(), info.weight + 256); + assert_eq!(BlockWeight::get().total(), info.weight + 256); assert!( CheckWeight::::post_dispatch(pre, &info, &post_info, len, &Ok(())) .is_ok() ); assert_eq!( - AllExtrinsicsWeight::get().unwrap(), + BlockWeight::get().total(), post_info.actual_weight.unwrap() + 256, ); }) @@ -2076,11 +2343,13 @@ pub(crate) mod tests { let post_info = PostDispatchInfo { actual_weight: Some(700), }; let len = 0_usize; - AllExtrinsicsWeight::put(128); + BlockWeight::mutate(|current_weight| { + current_weight.put(128, DispatchClass::Normal) + }); let pre = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &info, len).unwrap(); assert_eq!( - AllExtrinsicsWeight::get().unwrap(), + BlockWeight::get().total(), info.weight + 128 + ::ExtrinsicBaseWeight::get(), ); @@ -2089,7 +2358,7 @@ pub(crate) mod tests { .is_ok() ); assert_eq!( - AllExtrinsicsWeight::get().unwrap(), + BlockWeight::get().total(), info.weight + 128 + ::ExtrinsicBaseWeight::get(), ); }) @@ -2102,11 +2371,11 @@ pub(crate) mod tests { let len = 0_usize; // Initial weight from `BlockExecutionWeight` - assert_eq!(System::all_extrinsics_weight(), ::BlockExecutionWeight::get()); + assert_eq!(System::block_weight().total(), ::BlockExecutionWeight::get()); let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &free, len); assert!(r.is_ok()); assert_eq!( - System::all_extrinsics_weight(), + System::block_weight().total(), ::ExtrinsicBaseWeight::get() + ::BlockExecutionWeight::get() ); }) @@ -2114,26 +2383,52 @@ pub(crate) mod tests { #[test] fn mandatory_extrinsic_doesnt_care_about_limits() { + fn check(call: impl FnOnce(&DispatchInfo, usize)) { + new_test_ext().execute_with(|| { + let max = DispatchInfo { + weight: Weight::max_value(), + class: DispatchClass::Mandatory, + ..Default::default() + }; + let len = 0_usize; + + call(&max, len); + }); + } + + check(|max, len| { + assert_ok!(CheckWeight::::do_pre_dispatch(max, len)); + assert_eq!(System::block_weight().total(), Weight::max_value()); + assert!(System::block_weight().total() > ::MaximumBlockWeight::get()); + }); + check(|max, len| { + assert_ok!(CheckWeight::::do_validate(max, len)); + }); + } + + #[test] + fn normal_extrinsic_limited_by_maximum_extrinsic_weight() { new_test_ext().execute_with(|| { let max = DispatchInfo { - weight: Weight::max_value(), - class: DispatchClass::Mandatory, + weight: MaximumExtrinsicWeight::get() + 1, + class: DispatchClass::Normal, ..Default::default() }; let len = 0_usize; - assert_ok!(CheckWeight::::do_pre_dispatch(&max, len)); - assert_eq!(System::all_extrinsics_weight(), Weight::max_value()); - assert!(System::all_extrinsics_weight() > ::MaximumBlockWeight::get()); + assert_noop!( + CheckWeight::::do_validate(&max, len), + InvalidTransaction::ExhaustsResources + ); }); } #[test] fn register_extra_weight_unchecked_doesnt_care_about_limits() { new_test_ext().execute_with(|| { - System::register_extra_weight_unchecked(Weight::max_value()); - assert_eq!(System::all_extrinsics_weight(), Weight::max_value()); - assert!(System::all_extrinsics_weight() > ::MaximumBlockWeight::get()); + System::register_extra_weight_unchecked(Weight::max_value(), DispatchClass::Normal); + assert_eq!(System::block_weight().total(), Weight::max_value()); + assert!(System::block_weight().total() > ::MaximumBlockWeight::get()); }); } @@ -2151,10 +2446,45 @@ pub(crate) mod tests { let len = 0_usize; assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); - assert_eq!(System::all_extrinsics_weight(), 768); + assert_eq!(System::block_weight().total(), 768); assert_ok!(CheckWeight::::do_pre_dispatch(&rest_operational, len)); assert_eq!(::MaximumBlockWeight::get(), 1024); - assert_eq!(System::all_extrinsics_weight(), ::MaximumBlockWeight::get()); + assert_eq!(System::block_weight().total(), ::MaximumBlockWeight::get()); + }); + } + + #[test] + fn dispatch_order_does_not_effect_weight_logic() { + new_test_ext().execute_with(|| { + // We switch the order of `full_block_with_normal_and_operational` + let max_normal = DispatchInfo { weight: 753, ..Default::default() }; + let rest_operational = DispatchInfo { weight: 251, class: DispatchClass::Operational, ..Default::default() }; + + let len = 0_usize; + + assert_ok!(CheckWeight::::do_pre_dispatch(&rest_operational, len)); + // Extra 15 here from block execution + base extrinsic weight + assert_eq!(System::block_weight().total(), 266); + assert_ok!(CheckWeight::::do_pre_dispatch(&max_normal, len)); + assert_eq!(::MaximumBlockWeight::get(), 1024); + assert_eq!(System::block_weight().total(), ::MaximumBlockWeight::get()); + }); + } + + #[test] + fn operational_works_on_full_block() { + new_test_ext().execute_with(|| { + // An on_initialize takes up the whole block! (Every time!) + System::register_extra_weight_unchecked(Weight::max_value(), DispatchClass::Mandatory); + let dispatch_normal = DispatchInfo { weight: 251, class: DispatchClass::Normal, ..Default::default() }; + let dispatch_operational = DispatchInfo { weight: 251, class: DispatchClass::Operational, ..Default::default() }; + let len = 0_usize; + + assert_noop!(CheckWeight::::do_pre_dispatch(&dispatch_normal, len), InvalidTransaction::ExhaustsResources); + // Thank goodness we can still do an operational transaction to possibly save the blockchain. + assert_ok!(CheckWeight::::do_pre_dispatch(&dispatch_operational, len)); + // Not too much though + assert_noop!(CheckWeight::::do_pre_dispatch(&dispatch_operational, len), InvalidTransaction::ExhaustsResources); }); } @@ -2167,7 +2497,9 @@ pub(crate) mod tests { let normal_limit = normal_weight_limit(); // given almost full block - AllExtrinsicsWeight::put(normal_limit); + BlockWeight::mutate(|current_weight| { + current_weight.put(normal_limit, DispatchClass::Normal) + }); // will not fit. assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, &normal, len).is_err()); // will fit. @@ -2182,7 +2514,7 @@ pub(crate) mod tests { } #[test] - fn signed_ext_check_weight_priority_works() { + fn signed_ext() { new_test_ext().execute_with(|| { let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: Pays::Yes }; let op = DispatchInfo { weight: 100, class: DispatchClass::Operational, pays_fee: Pays::Yes }; @@ -2322,7 +2654,11 @@ pub(crate) mod tests { assert_eq!( System::events(), - vec![EventRecord { phase: Phase::Initialization, event: 102u16, topics: vec![] }], + vec![EventRecord { + phase: Phase::Initialization, + event: SysEvent::CodeUpdated, + topics: vec![], + }], ); }); } diff --git a/frame/system/src/offchain.rs b/frame/system/src/offchain.rs index 04cd3001e43a3899cdbdafaa7fb3a1eeb9bed9db..42699362a36a30aba55985cb213bcfc6d1ab0c92 100644 --- a/frame/system/src/offchain.rs +++ b/frame/system/src/offchain.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Module helpers for off-chain calls. //! @@ -382,6 +383,7 @@ impl Clone for Account where /// ```ignore /// // im-online specific crypto /// type RuntimeAppPublic = ImOnline(sr25519::Public); +/// /// // wrapped "raw" crypto /// type GenericPublic = sr25519::Public; /// type GenericSignature = sr25519::Signature; diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index 7691421bbfed16b4726d1eb1f3752fe8868026d8..cda7904f7579d51bc4be02fa893aa549d07b98db 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-timestamp" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME Timestamp Module" @@ -16,19 +16,19 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io", optional = true } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -sp-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../primitives/timestamp" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io", optional = true } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/inherents" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +sp-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/timestamp" } impl-trait-for-tuples = "0.1.3" [dev-dependencies] -sp-io ={ version = "2.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/timestamp/src/benchmarking.rs b/frame/timestamp/src/benchmarking.rs index c468bf82fba6f9570c471ce7aa615f2658db3389..9b1c976229e665e330e62788d5a338589b4427c6 100644 --- a/frame/timestamp/src/benchmarking.rs +++ b/frame/timestamp/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Timestamp pallet benchmarking. @@ -34,6 +35,7 @@ benchmarks! { set { let t in 1 .. MAX_TIME; }: _(RawOrigin::None, t.into()) + verify { ensure!(Timestamp::::now() == t.into(), "Time was not set."); } @@ -43,6 +45,7 @@ benchmarks! { Timestamp::::set(RawOrigin::None.into(), t.into())?; ensure!(DidUpdate::exists(), "Time was not set."); }: { Timestamp::::on_finalize(t.into()); } + verify { ensure!(!DidUpdate::exists(), "Time was not removed."); } diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index 31021e088786959b11213ebebc389aeb7aaf89ba..6d38919f31b1b2688a8ce4533897f290e396d2c3 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Timestamp Module //! @@ -152,12 +153,12 @@ decl_module! { /// - `O(T)` where `T` complexity of `on_timestamp_set` /// - 1 storage read and 1 storage mutation (codec `O(1)`). (because of `DidUpdate::take` in `on_finalize`) /// - 1 event handler `on_timestamp_set` `O(T)`. - /// - Benchmark: 8.523 (min squares analysis) + /// - Benchmark: 7.678 (min squares analysis) /// - NOTE: This benchmark was done for a runtime with insignificant `on_timestamp_set` handlers. /// New benchmarking is needed when adding new handlers. /// # #[weight = ( - T::DbWeight::get().reads_writes(2, 1) + 9_000_000, + T::DbWeight::get().reads_writes(2, 1) + 8_000_000, DispatchClass::Mandatory )] fn set(origin, #[compact] now: T::Moment) { @@ -177,13 +178,13 @@ decl_module! { /// dummy `on_initialize` to return the weight used in `on_finalize`. fn on_initialize() -> Weight { // weight of `on_finalize` - 6_000_000 + 5_000_000 } /// # /// - `O(1)` /// - 1 storage deletion (codec `O(1)`). - /// - Benchmark: 5.105 µs (min squares analysis) + /// - Benchmark: 4.928 µs (min squares analysis) /// # fn on_finalize() { assert!(::DidUpdate::take(), "Timestamp must be updated once in the block"); @@ -328,6 +329,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml index a969f3008688435c0401c0d91eb0988919d90a03..17e05fa40ff88e414b7425d0c67cdedc671cc33c 100644 --- a/frame/transaction-payment/Cargo.toml +++ b/frame/transaction-payment/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-transaction-payment" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage transaction payments" @@ -13,17 +13,18 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-dev", default-features = false, path = "./rpc/runtime-api" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-rc2", default-features = false, path = "./rpc/runtime-api" } +smallvec = "1.4.0" [dev-dependencies] -sp-io = { version = "2.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -sp-storage = { version = "2.0.0-dev", path = "../../primitives/storage" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +sp-storage = { version = "2.0.0-rc2", path = "../../primitives/storage" } [features] default = ["std"] diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 35f421915af3975a6ad820523a45207a564af327..3ca2f4be8e308b37373bf307dbd9204d3196b5b1 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-transaction-payment-rpc" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "RPC interface for the transaction payment module." @@ -16,10 +16,10 @@ codec = { package = "parity-scale-codec", version = "1.3.0" } jsonrpc-core = "14.0.3" jsonrpc-core-client = "14.0.5" jsonrpc-derive = "14.0.3" -sp-core = { version = "2.0.0-dev", path = "../../../primitives/core" } -sp-rpc = { version = "2.0.0-dev", path = "../../../primitives/rpc" } +sp-core = { version = "2.0.0-rc2", path = "../../../primitives/core" } +sp-rpc = { version = "2.0.0-rc2", path = "../../../primitives/rpc" } serde = { version = "1.0.101", features = ["derive"] } -sp-runtime = { version = "2.0.0-dev", path = "../../../primitives/runtime" } -sp-api = { version = "2.0.0-dev", path = "../../../primitives/api" } -sp-blockchain = { version = "2.0.0-dev", path = "../../../primitives/blockchain" } -pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-dev", path = "./runtime-api" } +sp-runtime = { version = "2.0.0-rc2", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0-rc2", path = "../../../primitives/api" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../../primitives/blockchain" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-rc2", path = "./runtime-api" } diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml index 1170e043eea84dccf37aef9ba1bd9bb35ad7bb08..e4be938b3dfa283b71b3dfc9caf10c7f52cfaeef 100644 --- a/frame/transaction-payment/rpc/runtime-api/Cargo.toml +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-transaction-payment-rpc-runtime-api" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "RPC runtime API for transaction payment FRAME pallet" @@ -13,11 +13,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-api = { version = "2.0.0-dev", default-features = false, path = "../../../../primitives/api" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../../../../primitives/api" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../../../support" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../../../support" } [dev-dependencies] serde_json = "1.0.41" diff --git a/frame/transaction-payment/rpc/runtime-api/src/lib.rs b/frame/transaction-payment/rpc/runtime-api/src/lib.rs index 77b6e3b45464e5bc7837ce619a43f7d283cc4bb7..17a8bcdf44e87a695e703515801a56f03ffc4d8e 100644 --- a/frame/transaction-payment/rpc/runtime-api/src/lib.rs +++ b/frame/transaction-payment/rpc/runtime-api/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime API definition for transaction payment module. @@ -25,7 +26,7 @@ use codec::{Encode, Codec, Decode}; use serde::{Serialize, Deserialize, Serializer, Deserializer}; use sp_runtime::traits::{MaybeDisplay, MaybeFromStr}; -/// Some information related to a dispatchable that can be queried from the runtime. +/// Information related to a dispatchable's class, weight, and fee that can be queried from the runtime. #[derive(Eq, PartialEq, Encode, Decode, Default)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] @@ -34,8 +35,8 @@ pub struct RuntimeDispatchInfo { pub weight: Weight, /// Class of this dispatch. pub class: DispatchClass, - /// The partial inclusion fee of this dispatch. This does not include tip or anything else which - /// is dependent on the signature (aka. depends on a `SignedExtension`). + /// The inclusion fee of this dispatch. This does not include a tip or anything else that + /// depends on the signature (i.e. depends on a `SignedExtension`). #[cfg_attr(feature = "std", serde(bound(serialize = "Balance: std::fmt::Display")))] #[cfg_attr(feature = "std", serde(serialize_with = "serialize_as_string"))] #[cfg_attr(feature = "std", serde(bound(deserialize = "Balance: std::str::FromStr")))] diff --git a/frame/transaction-payment/rpc/src/lib.rs b/frame/transaction-payment/rpc/src/lib.rs index 945b0119d7236dd4108d84978fb017b736f318cf..d99907a6ac3f4e112a91682affca029a84ee179c 100644 --- a/frame/transaction-payment/rpc/src/lib.rs +++ b/frame/transaction-payment/rpc/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! RPC interface for the transaction payment module. diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index f6334c658ac4c3cb26873b1e05b316707f59ac82..78c638b4844e293bcf7677e8027fb3a97c658b32 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Transaction Payment Module //! @@ -36,11 +37,14 @@ use codec::{Encode, Decode}; use frame_support::{ decl_storage, decl_module, traits::{Currency, Get, OnUnbalanced, ExistenceRequirement, WithdrawReason, Imbalance}, - weights::{Weight, DispatchInfo, PostDispatchInfo, GetDispatchInfo, Pays}, + weights::{ + Weight, DispatchInfo, PostDispatchInfo, GetDispatchInfo, Pays, WeightToFeePolynomial, + WeightToFeeCoefficient, + }, dispatch::DispatchResult, }; use sp_runtime::{ - Fixed128, + Fixed128, FixedPointNumber, FixedPointOperand, transaction_validity::{ TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError, TransactionValidity, @@ -71,7 +75,7 @@ pub trait Trait: frame_system::Trait { type TransactionByteFee: Get>; /// Convert a weight value into a deductible fee based on the currency type. - type WeightToFee: Convert>; + type WeightToFee: WeightToFeePolynomial>; /// Update the multiplier of the next block, based on the previous block's weight. type FeeMultiplierUpdate: Convert; @@ -79,7 +83,7 @@ pub trait Trait: frame_system::Trait { decl_storage! { trait Store for Module as TransactionPayment { - pub NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::from_parts(0); + pub NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::from_inner(0); } } @@ -88,19 +92,26 @@ decl_module! { /// The fee to be paid for making a transaction; the per-byte portion. const TransactionByteFee: BalanceOf = T::TransactionByteFee::get(); + /// The polynomial that is applied in order to derive fee from weight. + const WeightToFee: Vec>> = + T::WeightToFee::polynomial().to_vec(); + fn on_finalize() { NextFeeMultiplier::mutate(|fm| { - *fm = T::FeeMultiplierUpdate::convert(*fm) + *fm = T::FeeMultiplierUpdate::convert(*fm); }); } } } -impl Module { +impl Module where + BalanceOf: FixedPointOperand +{ /// Query the data that we know about the fee of a given `call`. /// - /// As this module is not and cannot be aware of the internals of a signed extension, it only - /// interprets them as some encoded value and takes their length into account. + /// This module is not and cannot be aware of the internals of a signed extension, for example + /// a tip. It only interprets the extrinsic as some encoded value and accounts for its weight + /// and length, the runtime's extrinsic base weight, and the current fee multiplier. /// /// All dispatchables must be annotated with weight and will have some fee info. This function /// always returns. @@ -129,17 +140,24 @@ impl Module { /// Compute the final fee value for a particular transaction. /// /// The final fee is composed of: - /// - _base_fee_: This is the minimum amount a user pays for a transaction. - /// - _len_fee_: This is the amount paid merely to pay for size of the transaction. - /// - _weight_fee_: This amount is computed based on the weight of the transaction. Unlike - /// size-fee, this is not input dependent and reflects the _complexity_ of the execution - /// and the time it consumes. - /// - _targeted_fee_adjustment_: This is a multiplier that can tune the final fee based on + /// - `base_fee`: This is the minimum amount a user pays for a transaction. It is declared + /// as a base _weight_ in the runtime and converted to a fee using `WeightToFee`. + /// - `len_fee`: The length fee, the amount paid for the encoded length (in bytes) of the + /// transaction. + /// - `weight_fee`: This amount is computed based on the weight of the transaction. Weight + /// accounts for the execution time of a transaction. + /// - `targeted_fee_adjustment`: This is a multiplier that can tune the final fee based on /// the congestion of the network. - /// - (optional) _tip_: if included in the transaction, it will be added on top. Only signed - /// transactions can have a tip. + /// - (Optional) `tip`: If included in the transaction, the tip will be added on top. Only + /// signed transactions can have a tip. /// - /// final_fee = base_fee + targeted_fee_adjustment(len_fee + weight_fee) + tip; + /// The base fee and adjusted weight and length fees constitute the _inclusion fee,_ which is + /// the minimum fee for a transaction to be included in a block. + /// + /// ```ignore + /// inclusion_fee = base_fee + targeted_fee_adjustment * (len_fee + weight_fee); + /// final_fee = inclusion_fee + tip; + /// ``` pub fn compute_fee( len: u32, info: &DispatchInfoOf, @@ -147,42 +165,70 @@ impl Module { ) -> BalanceOf where T::Call: Dispatchable, { - if info.pays_fee == Pays::Yes { + Self::compute_fee_raw(len, info.weight, tip, info.pays_fee) + } + + /// Compute the actual post dispatch fee for a particular transaction. + /// + /// Identical to `compute_fee` with the only difference that the post dispatch corrected + /// weight is used for the weight fee calculation. + pub fn compute_actual_fee( + len: u32, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + tip: BalanceOf, + ) -> BalanceOf where + T::Call: Dispatchable, + { + Self::compute_fee_raw(len, post_info.calc_actual_weight(info), tip, info.pays_fee) + } + + fn compute_fee_raw( + len: u32, + weight: Weight, + tip: BalanceOf, + pays_fee: Pays, + ) -> BalanceOf { + if pays_fee == Pays::Yes { let len = >::from(len); let per_byte = T::TransactionByteFee::get(); let len_fee = per_byte.saturating_mul(len); - let unadjusted_weight_fee = Self::weight_to_fee(info.weight); + let unadjusted_weight_fee = Self::weight_to_fee(weight); // the adjustable part of the fee let adjustable_fee = len_fee.saturating_add(unadjusted_weight_fee); let targeted_fee_adjustment = NextFeeMultiplier::get(); - let adjusted_fee = targeted_fee_adjustment.saturated_multiply_accumulate(adjustable_fee.saturated_into()); + let adjusted_fee = targeted_fee_adjustment.saturating_mul_acc_int(adjustable_fee); let base_fee = Self::weight_to_fee(T::ExtrinsicBaseWeight::get()); - base_fee.saturating_add(adjusted_fee.saturated_into()).saturating_add(tip) + base_fee.saturating_add(adjusted_fee).saturating_add(tip) } else { tip } } +} +impl Module { /// Compute the fee for the specified weight. /// /// This fee is already adjusted by the per block fee adjustment factor and is therefore /// the share that the weight contributes to the overall fee of a transaction. + /// + /// This function is generic in order to supply the contracts module with a way + /// to calculate the gas price. The contracts module is not able to put the necessary + /// `BalanceOf` contraints on its trait. This function is not to be used by this module. pub fn weight_to_fee_with_adjustment(weight: Weight) -> Balance where Balance: UniqueSaturatedFrom { - let fee = UniqueSaturatedInto::::unique_saturated_into(Self::weight_to_fee(weight)); - UniqueSaturatedFrom::unique_saturated_from( - NextFeeMultiplier::get().saturated_multiply_accumulate(fee) - ) + let fee: u128 = Self::weight_to_fee(weight).unique_saturated_into(); + Balance::unique_saturated_from(NextFeeMultiplier::get().saturating_mul_acc_int(fee)) } fn weight_to_fee(weight: Weight) -> BalanceOf { // cap the weight to the maximum defined in runtime, otherwise it will be the // `Bounded` maximum of its data type, which is not desired. let capped_weight = weight.min(::MaximumBlockWeight::get()); - T::WeightToFee::convert(capped_weight) + T::WeightToFee::calc(&capped_weight) } } @@ -193,7 +239,7 @@ pub struct ChargeTransactionPayment(#[codec(compact)] Ba impl ChargeTransactionPayment where T::Call: Dispatchable, - BalanceOf: Send + Sync, + BalanceOf: Send + Sync + FixedPointOperand, { /// utility constructor. Used only in client/factory code. pub fn from(fee: BalanceOf) -> Self { @@ -242,14 +288,14 @@ impl sp_std::fmt::Debug for ChargeTransactionPayment } impl SignedExtension for ChargeTransactionPayment where - BalanceOf: Send + Sync + From, + BalanceOf: Send + Sync + From + FixedPointOperand, T::Call: Dispatchable, { const IDENTIFIER: &'static str = "ChargeTransactionPayment"; type AccountId = T::AccountId; type Call = T::Call; type AdditionalSigned = (); - type Pre = (BalanceOf, Self::AccountId, Option>); + type Pre = (BalanceOf, Self::AccountId, Option>, BalanceOf); fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } fn validate( @@ -275,20 +321,26 @@ impl SignedExtension for ChargeTransactionPayment whe info: &DispatchInfoOf, len: usize ) -> Result { - let (_, imbalance) = self.withdraw_fee(who, info, len)?; - Ok((self.0, who.clone(), imbalance)) + let (fee, imbalance) = self.withdraw_fee(who, info, len)?; + Ok((self.0, who.clone(), imbalance, fee)) } fn post_dispatch( pre: Self::Pre, info: &DispatchInfoOf, post_info: &PostDispatchInfoOf, - _len: usize, + len: usize, _result: &DispatchResult, ) -> Result<(), TransactionValidityError> { - let (tip, who, imbalance) = pre; + let (tip, who, imbalance, fee) = pre; if let Some(payed) = imbalance { - let refund = Module::::weight_to_fee_with_adjustment(post_info.calc_unspent(info)); + let actual_fee = Module::::compute_actual_fee( + len as u32, + info, + post_info, + tip, + ); + let refund = fee.saturating_sub(actual_fee); let actual_payment = match T::Currency::deposit_into_existing(&who, refund) { Ok(refund_imbalance) => { // The refund cannot be larger than the up front payed max weight. @@ -313,11 +365,13 @@ impl SignedExtension for ChargeTransactionPayment whe #[cfg(test)] mod tests { use super::*; - use core::num::NonZeroI128; use codec::Encode; use frame_support::{ - impl_outer_dispatch, impl_outer_origin, parameter_types, - weights::{DispatchClass, DispatchInfo, PostDispatchInfo, GetDispatchInfo, Weight}, + impl_outer_dispatch, impl_outer_origin, impl_outer_event, parameter_types, + weights::{ + DispatchClass, DispatchInfo, PostDispatchInfo, GetDispatchInfo, Weight, + WeightToFeePolynomial, WeightToFeeCoefficients, WeightToFeeCoefficient, + }, }; use pallet_balances::Call as BalancesCall; use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; @@ -328,6 +382,7 @@ mod tests { Perbill, }; use std::cell::RefCell; + use smallvec::smallvec; const CALL: &::Call = &Call::Balances(BalancesCall::transfer(2, 69)); @@ -339,6 +394,13 @@ mod tests { } } + impl_outer_event! { + pub enum Event for Runtime { + system, + pallet_balances, + } + } + #[derive(Clone, PartialEq, Eq, Debug)] pub struct Runtime; @@ -373,12 +435,13 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -394,7 +457,7 @@ mod tests { impl pallet_balances::Trait for Runtime { type Balance = u64; - type Event = (); + type Event = Event; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; @@ -409,10 +472,17 @@ mod tests { fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) } } - pub struct WeightToFee(u64); - impl Convert for WeightToFee { - fn convert(t: Weight) -> u64 { - WEIGHT_TO_FEE.with(|v| *v.borrow() * (t as u64)) + pub struct WeightToFee; + impl WeightToFeePolynomial for WeightToFee { + type Balance = u64; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![WeightToFeeCoefficient { + degree: 1, + coeff_frac: Perbill::zero(), + coeff_integer: WEIGHT_TO_FEE.with(|v| *v.borrow()), + negative: false, + }] } } @@ -491,7 +561,7 @@ mod tests { /// create a transaction info struct from weight. Handy to avoid building the whole struct. pub fn info_from_weight(w: Weight) -> DispatchInfo { - // pays: yes -- class: normal + // pays_fee: Pays::Yes -- class: DispatchClass::Normal DispatchInfo { weight: w, ..Default::default() } } @@ -547,7 +617,7 @@ mod tests { .execute_with(|| { let len = 10; - NextFeeMultiplier::put(Fixed128::from_rational(1, NonZeroI128::new(2).unwrap())); + NextFeeMultiplier::put(Fixed128::saturating_from_rational(1, 2)); let pre = ChargeTransactionPayment::::from(5 /* tipped */) .pre_dispatch(&2, CALL, &info_from_weight(100), len) @@ -635,7 +705,7 @@ mod tests { .execute_with(|| { // all fees should be x1.5 - NextFeeMultiplier::put(Fixed128::from_rational(1, NonZeroI128::new(2).unwrap())); + NextFeeMultiplier::put(Fixed128::saturating_from_rational(1, 2)); let len = 10; assert!( @@ -663,7 +733,7 @@ mod tests { .execute_with(|| { // all fees should be x1.5 - NextFeeMultiplier::put(Fixed128::from_rational(1, NonZeroI128::new(2).unwrap())); + NextFeeMultiplier::put(Fixed128::saturating_from_rational(1, 2)); assert_eq!( TransactionPayment::query_info(xt, len), @@ -692,7 +762,7 @@ mod tests { .execute_with(|| { // Next fee multiplier is zero - assert_eq!(NextFeeMultiplier::get(), Fixed128::from_natural(0)); + assert_eq!(NextFeeMultiplier::get(), Fixed128::saturating_from_integer(0)); // Tip only, no fees works let dispatch_info = DispatchInfo { @@ -732,7 +802,7 @@ mod tests { .execute_with(|| { // Add a next fee multiplier - NextFeeMultiplier::put(Fixed128::from_rational(1, NonZeroI128::new(2).unwrap())); // = 1/2 = .5 + NextFeeMultiplier::put(Fixed128::saturating_from_rational(1, 2)); // = 1/2 = .5 // Base fee is unaffected by multiplier let dispatch_info = DispatchInfo { weight: 0, @@ -755,6 +825,39 @@ mod tests { }); } + #[test] + fn compute_fee_works_with_negative_multiplier() { + ExtBuilder::default() + .base_weight(100) + .byte_fee(10) + .balance_factor(0) + .build() + .execute_with(|| + { + // Add a next fee multiplier + NextFeeMultiplier::put(Fixed128::saturating_from_rational(-1, 2)); // = -1/2 = -.5 + // Base fee is unaffected by multiplier + let dispatch_info = DispatchInfo { + weight: 0, + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + assert_eq!(Module::::compute_fee(0, &dispatch_info, 0), 100); + + // Everything works together :) + let dispatch_info = DispatchInfo { + weight: 123, + class: DispatchClass::Operational, + pays_fee: Pays::Yes, + }; + // 123 weight, 456 length, 100 base + // adjustable fee = (123 * 1) + (456 * 10) = 4683 + // adjusted fee = 4683 - (4683 * -.5) = 4683 - 2341.5 = 4683 - 2341 = 2342 + // final fee = 100 + 2342 + 789 tip = 3231 + assert_eq!(Module::::compute_fee(456, &dispatch_info, 789), 3231); + }); + } + #[test] fn compute_fee_does_not_overflow() { ExtBuilder::default() @@ -789,6 +892,8 @@ mod tests { .build() .execute_with(|| { + // So events are emitted + System::set_block_number(10); let len = 10; let pre = ChargeTransactionPayment::::from(5 /* tipped */) .pre_dispatch(&2, CALL, &info_from_weight(100), len) @@ -805,6 +910,14 @@ mod tests { .is_ok() ); assert_eq!(Balances::free_balance(2), 0); + // Transfer Event + assert!(System::events().iter().any(|event| { + event.event == Event::pallet_balances(pallet_balances::RawEvent::Transfer(2, 3, 80)) + })); + // Killed Event + assert!(System::events().iter().any(|event| { + event.event == Event::system(system::RawEvent::KilledAccount(2)) + })); }); } @@ -830,4 +943,73 @@ mod tests { assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5); }); } + + #[test] + fn zero_transfer_on_free_transaction() { + ExtBuilder::default() + .balance_factor(10) + .base_weight(5) + .build() + .execute_with(|| + { + // So events are emitted + System::set_block_number(10); + let len = 10; + let dispatch_info = DispatchInfo { + weight: 100, + pays_fee: Pays::No, + class: DispatchClass::Normal, + }; + let user = 69; + let pre = ChargeTransactionPayment::::from(0) + .pre_dispatch(&user, CALL, &dispatch_info, len) + .unwrap(); + assert_eq!(Balances::total_balance(&user), 0); + assert!( + ChargeTransactionPayment:: + ::post_dispatch(pre, &dispatch_info, &default_post_info(), len, &Ok(())) + .is_ok() + ); + assert_eq!(Balances::total_balance(&user), 0); + // No events for such a scenario + assert_eq!(System::events().len(), 0); + }); + } + + #[test] + fn refund_consistent_with_actual_weight() { + ExtBuilder::default() + .balance_factor(10) + .base_weight(7) + .build() + .execute_with(|| + { + let info = info_from_weight(100); + let post_info = post_info_from_weight(33); + let prev_balance = Balances::free_balance(2); + let len = 10; + let tip = 5; + + NextFeeMultiplier::put(Fixed128::saturating_from_rational(1, 4)); + + let pre = ChargeTransactionPayment::::from(tip) + .pre_dispatch(&2, CALL, &info, len) + .unwrap(); + + ChargeTransactionPayment:: + ::post_dispatch(pre, &info, &post_info, len, &Ok(())) + .unwrap(); + + let refund_based_fee = prev_balance - Balances::free_balance(2); + let actual_fee = Module:: + ::compute_actual_fee(len as u32, &info, &post_info, tip); + + // 33 weight, 10 length, 7 base + // adjustable fee = (33 * 1) + (10 * 1) = 43 + // adjusted fee = 43 + (43 * .25) = 43 + 10.75 = 43 + 10 = 53 + // final fee = 7 + 53 + 5 tip = 65 + assert_eq!(actual_fee, 65); + assert_eq!(refund_based_fee, actual_fee); + }); + } } diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml index c00ae225c1eaeda5180e8d6005f451305a92b439..17c716fdcd12f228a82c63fe7a9f3cbc1b87d8b2 100644 --- a/frame/treasury/Cargo.toml +++ b/frame/treasury/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-treasury" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet to manage treasury" @@ -14,17 +14,17 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -pallet-balances = { version = "2.0.0-dev", default-features = false, path = "../balances" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +pallet-balances = { version = "2.0.0-rc2", default-features = false, path = "../balances" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-io ={ version = "2.0.0-dev", path = "../../primitives/io" } -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } +sp-io ={ version = "2.0.0-rc2", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } [features] default = ["std"] diff --git a/frame/treasury/src/benchmarking.rs b/frame/treasury/src/benchmarking.rs index f901576c95d4b0c8d384737502654672ccd8a795..8dddf3581aef2f1cd459c615465af1988778ed24 100644 --- a/frame/treasury/src/benchmarking.rs +++ b/frame/treasury/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Treasury pallet benchmarking. diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index 270a710a2c29e31cd15435e3a242988c931b1dc7..d1fed8fa2860a78d0888a52870f1920c1cb1a387 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Treasury Module //! diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs index 18b1d1c50eebd9c283e98861b736bd87f0fdd83a..0b68c51a1080c731e97e0be97422d387f919129e 100644 --- a/frame/treasury/src/tests.rs +++ b/frame/treasury/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Treasury pallet tests. @@ -74,6 +75,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml index a830f8ab5b57f405ac8ec94d1e3d63ee09e55c12..769e94c1bdf7c30c6c4fdd042add994decc73ab9 100644 --- a/frame/utility/Cargo.toml +++ b/frame/utility/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-utility" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME utilities pallet" @@ -14,18 +14,18 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../primitives/core" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } [features] default = ["std"] diff --git a/frame/utility/src/benchmarking.rs b/frame/utility/src/benchmarking.rs index fc8783b49aa87aaf0813bcc467defae82abc7bf3..4e77c8e44a676f02377cd7c54e789dafa60efafb 100644 --- a/frame/utility/src/benchmarking.rs +++ b/frame/utility/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Benchmarks for Utility Pallet diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index 1ff71af53595bc01188a486e824ac13ce098b084..546af51bdd7c43b08fc2d76080505045a8a25b5a 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Utility Module //! A module with helpers for dispatch management. @@ -66,11 +67,11 @@ use codec::{Encode, Decode}; use sp_core::TypeId; use sp_io::hashing::blake2_256; use frame_support::{decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, RuntimeDebug}; -use frame_support::{traits::{Get, ReservableCurrency, Currency}, +use frame_support::{traits::{Get, ReservableCurrency, Currency, Filter}, weights::{Weight, GetDispatchInfo, DispatchClass, FunctionOf, Pays}, dispatch::{DispatchResultWithPostInfo, DispatchErrorWithPostInfo, PostDispatchInfo}, }; -use frame_system::{self as system, ensure_signed}; +use frame_system::{self as system, ensure_signed, ensure_root}; use sp_runtime::{DispatchError, DispatchResult, traits::Dispatchable}; mod tests; @@ -84,7 +85,8 @@ pub trait Trait: frame_system::Trait { type Event: From> + Into<::Event>; /// The overarching call type. - type Call: Parameter + Dispatchable + GetDispatchInfo + From>; + type Call: Parameter + Dispatchable + + GetDispatchInfo + From>; /// The currency mechanism. type Currency: ReservableCurrency; @@ -102,6 +104,9 @@ pub trait Trait: frame_system::Trait { /// The maximum amount of signatories allowed in the multisig. type MaxSignatories: Get; + + /// Is a given call compatible with the proxying subsystem? + type IsCallable: Filter<::Call>; } /// A global extrinsic index, formed as the extrinsic index within a block, together with that @@ -163,6 +168,8 @@ decl_error! { WrongTimepoint, /// A timepoint was given, yet no multisig operation is underway. UnexpectedTimepoint, + /// A call with a `false` IsCallable filter was attempted. + Uncallable, } } @@ -190,6 +197,8 @@ decl_event! { /// A multisig operation has been cancelled. First param is the account that is /// cancelling, third is the multisig account, fourth is hash of the call. MultisigCancelled(AccountId, Timepoint, AccountId, CallHash), + /// A call with a `false` IsCallable filter was attempted. + Uncallable(u32), } } @@ -229,7 +238,8 @@ decl_module! { /// Send a batch of dispatch calls. /// - /// This will execute until the first one fails and then stop. + /// This will execute until the first one fails and then stop. Calls must fulfil the + /// `IsCallable` filter unless the origin is `Root`. /// /// May be called from any origin. /// @@ -265,7 +275,12 @@ decl_module! { Pays::Yes, )] fn batch(origin, calls: Vec<::Call>) { + let is_root = ensure_root(origin.clone()).is_ok(); for (index, call) in calls.into_iter().enumerate() { + if !is_root && !T::IsCallable::filter(&call) { + Self::deposit_event(Event::::Uncallable(index as u32)); + return Ok(()) + } let result = call.dispatch(origin.clone()); if let Err(e) = result { Self::deposit_event(Event::::BatchInterrupted(index as u32, e.error)); @@ -277,6 +292,8 @@ decl_module! { /// Send a call through an indexed pseudonym of the sender. /// + /// Calls must each fulfil the `IsCallable` filter. + /// /// The dispatch origin for this call must be _Signed_. /// /// # @@ -292,6 +309,7 @@ decl_module! { )] fn as_sub(origin, index: u16, call: Box<::Call>) -> DispatchResult { let who = ensure_signed(origin)?; + ensure!(T::IsCallable::filter(&call), Error::::Uncallable); let pseudonym = Self::sub_account_id(who, index); call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into()) .map(|_| ()).map_err(|e| e.error) @@ -300,7 +318,8 @@ decl_module! { /// Register approval for a dispatch to be made from a deterministic composite account if /// approved by a total of `threshold - 1` of `other_signatories`. /// - /// If there are enough, then dispatch the call. + /// If there are enough, then dispatch the call. Calls must each fulfil the `IsCallable` + /// filter. /// /// Payment: `MultisigDepositBase` will be reserved if this is the first approval, plus /// `threshold` times `MultisigDepositFactor`. It is returned once this dispatch happens or @@ -363,6 +382,7 @@ decl_module! { call: Box<::Call>, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; + ensure!(T::IsCallable::filter(call.as_ref()), Error::::Uncallable); ensure!(threshold >= 1, Error::::ZeroThreshold); let max_sigs = T::MaxSignatories::get() as usize; ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index 360ff78d308c9235d85c04a1829eb01f3748b9b2..daf3d6c53ade37ce4d2ecd0767b83ccf3b0d758e 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Tests for Utility Pallet @@ -74,6 +75,7 @@ impl frame_system::Trait for Test { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); @@ -97,6 +99,16 @@ parameter_types! { pub const MultisigDepositFactor: u64 = 1; pub const MaxSignatories: u16 = 3; } + +pub struct TestIsCallable; +impl Filter for TestIsCallable { + fn filter(c: &Call) -> bool { + match *c { + Call::Balances(pallet_balances::Call::transfer(..)) => true, + _ => false, + } + } +} impl Trait for Test { type Event = TestEvent; type Call = Call; @@ -104,6 +116,7 @@ impl Trait for Test { type MultisigDepositBase = MultisigDepositBase; type MultisigDepositFactor = MultisigDepositFactor; type MaxSignatories = MaxSignatories; + type IsCallable = TestIsCallable; } type System = frame_system::Module; type Balances = pallet_balances::Module; @@ -377,6 +390,17 @@ fn multisig_1_of_3_works() { }); } +#[test] +fn multisig_filters() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::System(frame_system::Call::remark(vec![]))); + assert_noop!( + Utility::as_multi(Origin::signed(1), 1, vec![], None, call.clone()), + Error::::Uncallable, + ); + }); +} + #[test] fn as_sub_works() { new_test_ext().execute_with(|| { @@ -397,6 +421,17 @@ fn as_sub_works() { }); } +#[test] +fn as_sub_filters() { + new_test_ext().execute_with(|| { + assert_noop!(Utility::as_sub( + Origin::signed(1), + 1, + Box::new(Call::System(frame_system::Call::remark(vec![]))), + ), Error::::Uncallable); + }); +} + #[test] fn batch_with_root_works() { new_test_ext().execute_with(|| { @@ -427,6 +462,18 @@ fn batch_with_signed_works() { }); } +#[test] +fn batch_with_signed_filters() { + new_test_ext().execute_with(|| { + assert_ok!( + Utility::batch(Origin::signed(1), vec![ + Call::System(frame_system::Call::remark(vec![])) + ]), + ); + expect_event(RawEvent::Uncallable(0)); + }); +} + #[test] fn batch_early_exit_works() { new_test_ext().execute_with(|| { diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 79430990c32474410bcb6ebfd1dae8cf7a34bec2..314abd08d0cdb17fcd8eb9fc9fb3a579757abb97 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "pallet-vesting" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME pallet for manage vesting" @@ -15,17 +15,17 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } enumflags2 = { version = "0.6.2" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0-dev", default-features = false, path = "../support" } -frame-system = { version = "2.0.0-dev", default-features = false, path = "../system" } -frame-benchmarking = { version = "2.0.0-dev", default-features = false, path = "../benchmarking", optional = true } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } [dev-dependencies] -sp-core = { version = "2.0.0-dev", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0-dev", path = "../balances" } -sp-storage = { version = "2.0.0-dev", path = "../../primitives/storage" } +sp-io = { version = "2.0.0-rc2", path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc2", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0-rc2", path = "../balances" } +sp-storage = { version = "2.0.0-rc2", path = "../../primitives/storage" } hex-literal = "0.2.1" [features] @@ -34,7 +34,6 @@ std = [ "serde", "codec/std", "sp-std/std", - "sp-io/std", "sp-runtime/std", "frame-support/std", "frame-system/std", diff --git a/frame/vesting/src/benchmarking.rs b/frame/vesting/src/benchmarking.rs index 10f19af65ee186ab1be9b5b0c6b5a194de1b3524..24cdc28c97f20f1e45531ec5fa61d024985562d4 100644 --- a/frame/vesting/src/benchmarking.rs +++ b/frame/vesting/src/benchmarking.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Vesting pallet benchmarking. diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 6d1b88efbcd65325ee8d0f6cbbaa0045488618d1..63a092da309c6f6dd67b91146d901bcde0db123c 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Vesting Module //! @@ -57,7 +58,6 @@ use frame_support::traits::{ Currency, LockableCurrency, VestingSchedule, WithdrawReason, LockIdentifier, ExistenceRequirement, Get }; - use frame_system::{self as system, ensure_signed}; mod benchmarking; @@ -395,6 +395,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); diff --git a/primitives/allocator/Cargo.toml b/primitives/allocator/Cargo.toml index 8530e0df0e7d22246eb4effa84ab35bd74fb7bab..7bf9ffd43f560f80d911b27a79f5975b902ecade 100644 --- a/primitives/allocator/Cargo.toml +++ b/primitives/allocator/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-allocator" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Collection of allocator implementations." @@ -13,9 +13,9 @@ documentation = "https://docs.rs/sp-allocator" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { version = "2.0.0-dev", path = "../std", default-features = false } -sp-core = { version = "2.0.0-dev", path = "../core", default-features = false } -sp-wasm-interface = { version = "2.0.0-dev", path = "../wasm-interface", default-features = false } +sp-std = { version = "2.0.0-rc2", path = "../std", default-features = false } +sp-core = { version = "2.0.0-rc2", path = "../core", default-features = false } +sp-wasm-interface = { version = "2.0.0-rc2", path = "../wasm-interface", default-features = false } log = { version = "0.4.8", optional = true } derive_more = { version = "0.99.2", optional = true } diff --git a/primitives/allocator/src/error.rs b/primitives/allocator/src/error.rs index 9357bc456003bd440f6067c41e567d1c8ad302b8..7b634af4d5b295e4fd0cc3691778186319bcde75 100644 --- a/primitives/allocator/src/error.rs +++ b/primitives/allocator/src/error.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. /// The error type used by the allocators. #[derive(sp_core::RuntimeDebug)] diff --git a/primitives/allocator/src/freeing_bump.rs b/primitives/allocator/src/freeing_bump.rs index 0d15ed11f74e0ba6fb22d1d3dde0b35e3e04f2ad..a9cb89c55b5712e805155b0ddf07fcce043b5696 100644 --- a/primitives/allocator/src/freeing_bump.rs +++ b/primitives/allocator/src/freeing_bump.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! This module implements a freeing-bump allocator. //! diff --git a/primitives/allocator/src/lib.rs b/primitives/allocator/src/lib.rs index 0efadbc7f6d60299ee5104600884b3f34692d8e5..b7cfce8048354d8f005af6e9c5d88d480bfa2e92 100644 --- a/primitives/allocator/src/lib.rs +++ b/primitives/allocator/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Collection of allocator implementations. //! diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml index 43decc4f6e60b62e2057661469158e72d78a592d..980049235c22a5c361e2ba5201891b1c1b370076 100644 --- a/primitives/api/Cargo.toml +++ b/primitives/api/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-api" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate runtime api primitives" @@ -13,16 +13,16 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-api-proc-macro = { version = "2.0.0-dev", path = "proc-macro" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../runtime" } -sp-version = { version = "2.0.0-dev", default-features = false, path = "../version" } -sp-state-machine = { version = "0.8.0-dev", optional = true, path = "../../primitives/state-machine" } +sp-api-proc-macro = { version = "2.0.0-rc2", path = "proc-macro" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../runtime" } +sp-version = { version = "2.0.0-rc2", default-features = false, path = "../version" } +sp-state-machine = { version = "0.8.0-rc2", optional = true, path = "../../primitives/state-machine" } hash-db = { version = "0.15.2", optional = true } [dev-dependencies] -sp-test-primitives = { version = "2.0.0-dev", path = "../test-primitives" } +sp-test-primitives = { version = "2.0.0-rc2", path = "../test-primitives" } [features] default = [ "std" ] diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml index a970b3e750a87941b9cb4dd05f7411664e3a378c..ce53ee997086d41c09309137a2f183f8ac0dd046 100644 --- a/primitives/api/proc-macro/Cargo.toml +++ b/primitives/api/proc-macro/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-api-proc-macro" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Macros for declaring and implementing runtime apis." diff --git a/primitives/api/proc-macro/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs index 440176bc468585e76cde32d3e07627e550d59a42..7e1391b7b57bd3dcfd5db10feaa9de8aa08dd09b 100644 --- a/primitives/api/proc-macro/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::utils::{ generate_crate_access, generate_hidden_includes, generate_runtime_mod_name_for_trait, diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs index 72c833a18c8d3c2bc2e5a819f0ade423be04fdd2..2878bd2c136837a7fed3dbb03e99802f32f0078d 100644 --- a/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::utils::{ generate_crate_access, generate_hidden_includes, diff --git a/primitives/api/proc-macro/src/lib.rs b/primitives/api/proc-macro/src/lib.rs index 12f435bd166dff2a579346ff8a710faec6bf89ba..4dd48094683d9fd02dc46f9155260e8e79e43ff8 100644 --- a/primitives/api/proc-macro/src/lib.rs +++ b/primitives/api/proc-macro/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macros for declaring and implementing runtime apis. diff --git a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index 0767c804a637e2983c52affc97c69f4aea47ce62..028ef57939fed6083287f8593c19cc0678db8692 100644 --- a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::utils::{ generate_crate_access, generate_hidden_includes, diff --git a/primitives/api/proc-macro/src/utils.rs b/primitives/api/proc-macro/src/utils.rs index 1a79cf6c1ef5b5f046ac98229b3f4203f46ce45b..534ddcfddd96e131a6d827c92386fd3aeb5945fe 100644 --- a/primitives/api/proc-macro/src/utils.rs +++ b/primitives/api/proc-macro/src/utils.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use proc_macro2::{TokenStream, Span}; diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index f8a22c45665ffd899f19b4e7200bd31a2a7c4bd4..ec15c1eae71d068217b0f5d2846bd0455786ceda 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate runtime api //! diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml index a945399f1b66ea830721a630c546888ece019830..59b1e76ad9e5f355dbf6a09f3402f557d84d611d 100644 --- a/primitives/api/test/Cargo.toml +++ b/primitives/api/test/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-api-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,22 +12,22 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-api = { version = "2.0.0-dev", path = "../" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sp-version = { version = "2.0.0-dev", path = "../../version" } -sp-runtime = { version = "2.0.0-dev", path = "../../runtime" } -sp-blockchain = { version = "2.0.0-dev", path = "../../blockchain" } -sp-consensus = { version = "0.8.0-dev", path = "../../../primitives/consensus/common" } -sc-block-builder = { version = "0.8.0-dev", path = "../../../client/block-builder" } +sp-api = { version = "2.0.0-rc2", path = "../" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../test-utils/runtime/client" } +sp-version = { version = "2.0.0-rc2", path = "../../version" } +sp-runtime = { version = "2.0.0-rc2", path = "../../runtime" } +sp-blockchain = { version = "2.0.0-rc2", path = "../../blockchain" } +sp-consensus = { version = "0.8.0-rc2", path = "../../../primitives/consensus/common" } +sc-block-builder = { version = "0.8.0-rc2", path = "../../../client/block-builder" } codec = { package = "parity-scale-codec", version = "1.3.0" } -sp-state-machine = { version = "0.8.0-dev", path = "../../../primitives/state-machine" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../../primitives/state-machine" } trybuild = "1.0.17" rustversion = "1.0.0" [dev-dependencies] criterion = "0.3.0" -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sp-core = { version = "2.0.0-dev", path = "../../core" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../test-utils/runtime/client" } +sp-core = { version = "2.0.0-rc2", path = "../../core" } [[bench]] name = "bench" diff --git a/primitives/api/test/benches/bench.rs b/primitives/api/test/benches/bench.rs index 9a90ca6e38b8501c4e7286d7919f56613d539df1..280b7079028735c897d0e5db517f41da2de0c0ef 100644 --- a/primitives/api/test/benches/bench.rs +++ b/primitives/api/test/benches/bench.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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. +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use criterion::{Criterion, criterion_group, criterion_main}; use substrate_test_runtime_client::{ diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index 4a8c8cd6628c895dec8bbf5a920b15684471380b..f16f0bbe71c562640fb5b89203433a795f811b33 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_api::{ RuntimeApiInfo, decl_runtime_apis, impl_runtime_apis, mock_impl_runtime_apis, diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index a907ac80957200d8135ee50e3782420c134a3411..555104446ae2ef4a9e01e91c8b9ea4b375835960 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_api::ProvideRuntimeApi; use substrate_test_runtime_client::{ diff --git a/primitives/api/test/tests/trybuild.rs b/primitives/api/test/tests/trybuild.rs index 910771f9389691d61b1c84069fdf6090e242f80b..2f7fd6d06bcd34c3724d6fa39422d4f7890392cc 100644 --- a/primitives/api/test/tests/trybuild.rs +++ b/primitives/api/test/tests/trybuild.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::env; diff --git a/primitives/api/test/tests/ui/declaring_old_block.rs b/primitives/api/test/tests/ui/declaring_old_block.rs index ba98bf9bf688317b4a8d6dd940b61112fba82485..fb741590282249c692af3b9233f59a95fa3b0b5b 100644 --- a/primitives/api/test/tests/ui/declaring_old_block.rs +++ b/primitives/api/test/tests/ui/declaring_old_block.rs @@ -1,5 +1,3 @@ -use sp_runtime::traits::Block as BlockT; - sp_api::decl_runtime_apis! { pub trait Api { fn test(); diff --git a/primitives/api/test/tests/ui/declaring_old_block.stderr b/primitives/api/test/tests/ui/declaring_old_block.stderr index 448dc38594321e5b7f11c0ccfeb4f4d6e6414862..50dd37582c603d5d355472e2003b1813d18ecb67 100644 --- a/primitives/api/test/tests/ui/declaring_old_block.stderr +++ b/primitives/api/test/tests/ui/declaring_old_block.stderr @@ -1,19 +1,11 @@ error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally. - --> $DIR/declaring_old_block.rs:4:23 + --> $DIR/declaring_old_block.rs:2:23 | -4 | pub trait Api { +2 | pub trait Api { | ^^^^^^ error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! - --> $DIR/declaring_old_block.rs:4:16 + --> $DIR/declaring_old_block.rs:2:16 | -4 | pub trait Api { +2 | pub trait Api { | ^^^^^ - -warning: unused import: `sp_runtime::traits::Block as BlockT` - --> $DIR/declaring_old_block.rs:1:5 - | -1 | use sp_runtime::traits::Block as BlockT; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs index 67bb9cab10502cc7ef33fe9106d95221547a9a99..e3c7ae8a39ab748557c5d160f35e24dfcd0a353d 100644 --- a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs +++ b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs @@ -1,5 +1,3 @@ -use sp_runtime::traits::Block as BlockT; - sp_api::decl_runtime_apis! { pub trait Api { fn test(); diff --git a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr index fe445b822dd88a25e340beb75fc834a5ff85febf..778de3c9d15f7ff9caf94b858182af78ff260bd1 100644 --- a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr +++ b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr @@ -1,13 +1,5 @@ error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally. - --> $DIR/declaring_own_block_with_different_name.rs:4:19 + --> $DIR/declaring_own_block_with_different_name.rs:2:19 | -4 | pub trait Api { +2 | pub trait Api { | ^^^^^^ - -warning: unused import: `sp_runtime::traits::Block as BlockT` - --> $DIR/declaring_own_block_with_different_name.rs:1:5 - | -1 | use sp_runtime::traits::Block as BlockT; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr index f927912879ad037b448c24d3193679432a43d9f0..b08f056b57d1cde69d57a5cf9e2337c46a70cbe5 100644 --- a/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr +++ b/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr @@ -2,4 +2,6 @@ error: No api implementation given! --> $DIR/empty_impl_runtime_apis_call.rs:17:1 | 17 | sp_api::impl_runtime_apis! {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr index 4f112e91bb7a9c45eec3692e7c4dc3c9f8fc2790..46f138fccd5ecdd1c57c7e24d6ccacd1bf7472dc 100644 --- a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr @@ -21,20 +21,11 @@ error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for tr | |_- type in trait 16 | 17 | sp_api::impl_runtime_apis! { - | -^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | _expected `u64`, found struct `std::string::String` - | | -18 | | impl self::Api for Runtime { -19 | | fn test(data: String) {} -20 | | } -... | -32 | | } -33 | | } - | |_- in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `std::string::String` | = note: expected fn pointer `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` found fn pointer `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/impl_incorrect_method_signature.rs:17:1 @@ -46,10 +37,9 @@ error[E0308]: mismatched types ... | 32 | | } 33 | | } - | | ^ - | | | - | |_expected `u64`, found struct `std::string::String` - | in this macro invocation + | |_^ expected `u64`, found struct `std::string::String` + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/impl_incorrect_method_signature.rs:19:11 diff --git a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs index 2122a6991ae5a9c6f38a0a9de9abdcc05b0641ca..76555a825dc8415c591455398ad931d43d6d7d5f 100644 --- a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs +++ b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs @@ -15,8 +15,6 @@ sp_api::decl_runtime_apis! { } mod second { - use super::*; - sp_api::decl_runtime_apis! { pub trait Api { fn test2(data: u64); diff --git a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr index 24ee66f84b314d345dd7b5d86638293b140eedb1..17ee56d409a66e34fcaec32af8644385fe5ef520 100644 --- a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr +++ b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr @@ -1,13 +1,5 @@ error: Two traits with the same name detected! The trait name is used to generate its ID. Please rename one trait at the declaration! - --> $DIR/impl_two_traits_with_same_name.rs:32:15 + --> $DIR/impl_two_traits_with_same_name.rs:30:15 | -32 | impl second::Api for Runtime { +30 | impl second::Api for Runtime { | ^^^ - -warning: unused import: `super::*` - --> $DIR/impl_two_traits_with_same_name.rs:18:6 - | -18 | use super::*; - | ^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/mock_only_one_block_type.rs b/primitives/api/test/tests/ui/mock_only_one_block_type.rs index 969b21d7378d75b6b2bb28c1ca118aa041015784..f49cafd23a00122bd53976c0656e0779f3d3fb5d 100644 --- a/primitives/api/test/tests/ui/mock_only_one_block_type.rs +++ b/primitives/api/test/tests/ui/mock_only_one_block_type.rs @@ -1,5 +1,3 @@ -use substrate_test_runtime_client::runtime::Block; - struct Block2; sp_api::decl_runtime_apis! { diff --git a/primitives/api/test/tests/ui/mock_only_one_block_type.stderr b/primitives/api/test/tests/ui/mock_only_one_block_type.stderr index 1abc8db726a160e151cb47abf6b745d5630b1851..1831d0485b473a3d33ca1bafce6c2fa67f6b78a2 100644 --- a/primitives/api/test/tests/ui/mock_only_one_block_type.stderr +++ b/primitives/api/test/tests/ui/mock_only_one_block_type.stderr @@ -1,19 +1,11 @@ error: Block type should be the same between all runtime apis. - --> $DIR/mock_only_one_block_type.rs:22:12 + --> $DIR/mock_only_one_block_type.rs:20:12 | -22 | impl Api2 for MockApi { +20 | impl Api2 for MockApi { | ^^^^^^ error: First block type found here - --> $DIR/mock_only_one_block_type.rs:18:11 + --> $DIR/mock_only_one_block_type.rs:16:11 | -18 | impl Api for MockApi { +16 | impl Api for MockApi { | ^^^^^ - -warning: unused import: `substrate_test_runtime_client::runtime::Block` - --> $DIR/mock_only_one_block_type.rs:1:5 - | -1 | use substrate_test_runtime_client::runtime::Block; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/mock_only_one_error_type.stderr b/primitives/api/test/tests/ui/mock_only_one_error_type.stderr index 7cec5246ca825a742bfad7a52ba446bd2be4f4c7..b190c2134fafa6d4312b856f391c905a1d5c72b3 100644 --- a/primitives/api/test/tests/ui/mock_only_one_error_type.stderr +++ b/primitives/api/test/tests/ui/mock_only_one_error_type.stderr @@ -14,10 +14,7 @@ error[E0277]: the trait bound `u32: std::convert::From` is ... | 26 | | } 27 | | } - | | ^ - | | | - | |_the trait `std::convert::From` is not implemented for `u32` - | in this macro invocation + | |_^ the trait `std::convert::From` is not implemented for `u32` | = help: the following implementations were found: > @@ -25,3 +22,4 @@ error[E0277]: the trait bound `u32: std::convert::From` is > > and 18 others + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/api/test/tests/ui/mock_only_one_self_type.rs b/primitives/api/test/tests/ui/mock_only_one_self_type.rs index 4b29ec2a6ab07e7a08689549423e03687501543d..617031b4d5f1a1f37c974ed8d826f43e49003233 100644 --- a/primitives/api/test/tests/ui/mock_only_one_self_type.rs +++ b/primitives/api/test/tests/ui/mock_only_one_self_type.rs @@ -1,5 +1,3 @@ -use substrate_test_runtime_client::runtime::Block; - sp_api::decl_runtime_apis! { pub trait Api { fn test(data: u64); diff --git a/primitives/api/test/tests/ui/mock_only_one_self_type.stderr b/primitives/api/test/tests/ui/mock_only_one_self_type.stderr index 996d1d44c044c151bc5e57e93e83d3749e86a80c..5f1e29b281c8504d39a355028882099b40298810 100644 --- a/primitives/api/test/tests/ui/mock_only_one_self_type.stderr +++ b/primitives/api/test/tests/ui/mock_only_one_self_type.stderr @@ -1,19 +1,11 @@ error: Self type should not change between runtime apis - --> $DIR/mock_only_one_self_type.rs:21:23 + --> $DIR/mock_only_one_self_type.rs:19:23 | -21 | impl Api2 for MockApi2 { +19 | impl Api2 for MockApi2 { | ^^^^^^^^ error: First self type found here - --> $DIR/mock_only_one_self_type.rs:17:22 + --> $DIR/mock_only_one_self_type.rs:15:22 | -17 | impl Api for MockApi { +15 | impl Api for MockApi { | ^^^^^^^ - -warning: unused import: `substrate_test_runtime_client::runtime::Block` - --> $DIR/mock_only_one_self_type.rs:1:5 - | -1 | use substrate_test_runtime_client::runtime::Block; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/mock_only_self_reference.stderr b/primitives/api/test/tests/ui/mock_only_self_reference.stderr index 9c1658b0a6cea1260b082eee7afea6d2521c66ac..6d1ac0e9a25636bb2645037c5925b092422ad3d1 100644 --- a/primitives/api/test/tests/ui/mock_only_self_reference.stderr +++ b/primitives/api/test/tests/ui/mock_only_self_reference.stderr @@ -22,20 +22,11 @@ error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for tr | |_- type in trait ... 12 | sp_api::mock_impl_runtime_apis! { - | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | _expected `u64`, found `()` - | | -13 | | impl Api for MockApi { -14 | | fn test(self, data: u64) {} -15 | | -16 | | fn test2(&mut self, data: u64) {} -17 | | } -18 | | } - | |_- in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `()` | = note: expected fn pointer `fn(&MockApi, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` found fn pointer `fn(&MockApi, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<()>, std::vec::Vec<_>) -> std::result::Result<_, _>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0053]: method `Api_test2_runtime_api_impl` has an incompatible type for trait --> $DIR/mock_only_self_reference.rs:12:1 @@ -49,17 +40,8 @@ error[E0053]: method `Api_test2_runtime_api_impl` has an incompatible type for t | |_- type in trait ... 12 | sp_api::mock_impl_runtime_apis! { - | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | _expected `u64`, found `()` - | | -13 | | impl Api for MockApi { -14 | | fn test(self, data: u64) {} -15 | | -16 | | fn test2(&mut self, data: u64) {} -17 | | } -18 | | } - | |_- in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `()` | = note: expected fn pointer `fn(&MockApi, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` found fn pointer `fn(&MockApi, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId, substrate_test_runtime::Extrinsic>>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<()>, std::vec::Vec<_>) -> std::result::Result<_, _>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr index 1d7d0a78a86df87ac01b1d30a757a5a0695e265e..cc2a5f05cd5ffea8251c8b280eae656ddf550d4f 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr @@ -21,20 +21,11 @@ error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for tr | |_- type in trait 16 | 17 | sp_api::impl_runtime_apis! { - | -^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | _expected `u64`, found `&u64` - | | -18 | | impl self::Api for Runtime { -19 | | fn test(data: &u64) { -20 | | unimplemented!() -... | -34 | | } -35 | | } - | |_- in this macro invocation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `&u64` | = note: expected fn pointer `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec<_>) -> std::result::Result<_, _>` found fn pointer `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<&u64>, std::vec::Vec<_>) -> std::result::Result<_, _>` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/type_reference_in_impl_runtime_apis_call.rs:17:1 @@ -46,10 +37,9 @@ error[E0308]: mismatched types ... | 34 | | } 35 | | } - | | ^ - | | | - | |_expected `u64`, found `&u64` - | in this macro invocation + | |_^ expected `u64`, found `&u64` + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/type_reference_in_impl_runtime_apis_call.rs:19:11 diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml index be9e5e5a1116ddcf883c5cbd40ee5f026855ab38..2da6b316277f54e493fb8de1073b50841a896c8b 100644 --- a/primitives/application-crypto/Cargo.toml +++ b/primitives/application-crypto/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-application-crypto" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" description = "Provides facilities for generating application specific crypto wrapper types." -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" documentation = "https://docs.rs/sp-application-crypto" @@ -14,11 +14,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "2.0.0-dev", default-features = false, path = "../core" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../primitives/io" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } [features] default = [ "std" ] diff --git a/primitives/application-crypto/src/ecdsa.rs b/primitives/application-crypto/src/ecdsa.rs new file mode 100644 index 0000000000000000000000000000000000000000..287ac8f3afcff000b5de63223e8c1157b8794d4d --- /dev/null +++ b/primitives/application-crypto/src/ecdsa.rs @@ -0,0 +1,61 @@ +// Copyright 2019-2020 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 . + +//! Ecdsa crypto types. + +use crate::{RuntimePublic, KeyTypeId}; + +use sp_std::vec::Vec; + +pub use sp_core::ecdsa::*; + +mod app { + use sp_core::testing::ECDSA; + + crate::app_crypto!(super, ECDSA); + + impl crate::traits::BoundToRuntimeAppPublic for Public { + type Public = Self; + } +} + +pub use app::{Public as AppPublic, Signature as AppSignature}; +#[cfg(feature = "full_crypto")] +pub use app::Pair as AppPair; + +impl RuntimePublic for Public { + type Signature = Signature; + + fn all(key_type: KeyTypeId) -> crate::Vec { + sp_io::crypto::ecdsa_public_keys(key_type) + } + + fn generate_pair(key_type: KeyTypeId, seed: Option>) -> Self { + sp_io::crypto::ecdsa_generate(key_type, seed) + } + + fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option { + sp_io::crypto::ecdsa_sign(key_type, self, msg.as_ref()) + } + + fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { + sp_io::crypto::ecdsa_verify(&signature, msg.as_ref(), self) + } + + fn to_raw_vec(&self) -> Vec { + sp_core::crypto::Public::to_raw_vec(self) + } +} diff --git a/primitives/application-crypto/src/ed25519.rs b/primitives/application-crypto/src/ed25519.rs index 5be79ff4f7985a54e9eb0c34fb3552f3cf062bb1..e761745cf5425a9a51d1499b5c10e5b849aabae1 100644 --- a/primitives/application-crypto/src/ed25519.rs +++ b/primitives/application-crypto/src/ed25519.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Ed25519 crypto types. @@ -23,27 +24,13 @@ use sp_std::vec::Vec; pub use sp_core::ed25519::*; mod app { - use sp_core::crypto::{CryptoTypePublicPair, Public as TraitPublic}; use sp_core::testing::ED25519; - use sp_core::ed25519::CRYPTO_ID; crate::app_crypto!(super, ED25519); impl crate::traits::BoundToRuntimeAppPublic for Public { type Public = Self; } - - impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } - } - - impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } - } } pub use app::{Public as AppPublic, Signature as AppSignature}; diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs index 8bad474ede81e1281648953b035be1dbd1cc63ee..6b5cf8857fb5b754dd27613089e275c4f03ed50f 100644 --- a/primitives/application-crypto/src/lib.rs +++ b/primitives/application-crypto/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Traits and macros for constructing application specific strongly typed crypto wrappers. @@ -25,7 +26,7 @@ pub use sp_core::{self, crypto::{CryptoType, CryptoTypePublicPair, Public, Deriv #[doc(hidden)] #[cfg(feature = "full_crypto")] pub use sp_core::crypto::{SecretStringError, DeriveJunction, Ss58Codec, Pair}; -pub use sp_core::crypto::{KeyTypeId, key_types}; +pub use sp_core::crypto::{KeyTypeId, CryptoTypeId, key_types}; #[doc(hidden)] pub use codec; @@ -33,10 +34,15 @@ pub use codec; #[cfg(feature = "std")] pub use serde; #[doc(hidden)] -pub use sp_std::{ops::Deref, vec::Vec}; +pub use sp_std::{ + convert::TryFrom, + ops::Deref, + vec::Vec, +}; pub mod ed25519; pub mod sr25519; +pub mod ecdsa; mod traits; pub use traits::*; @@ -54,11 +60,11 @@ pub use traits::*; #[macro_export] macro_rules! app_crypto { ($module:ident, $key_type:expr) => { - $crate::app_crypto_public_full_crypto!($module::Public, $key_type); - $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type); - $crate::app_crypto_signature_full_crypto!($module::Signature, $key_type); + $crate::app_crypto_public_full_crypto!($module::Public, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_signature_full_crypto!($module::Signature, $key_type, $module::CRYPTO_ID); $crate::app_crypto_signature_common!($module::Signature, $key_type); - $crate::app_crypto_pair!($module::Pair, $key_type); + $crate::app_crypto_pair!($module::Pair, $key_type, $module::CRYPTO_ID); }; } @@ -75,9 +81,9 @@ macro_rules! app_crypto { #[macro_export] macro_rules! app_crypto { ($module:ident, $key_type:expr) => { - $crate::app_crypto_public_not_full_crypto!($module::Public, $key_type); - $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type); - $crate::app_crypto_signature_not_full_crypto!($module::Signature, $key_type); + $crate::app_crypto_public_not_full_crypto!($module::Public, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type, $module::CRYPTO_ID); + $crate::app_crypto_signature_not_full_crypto!($module::Signature, $key_type, $module::CRYPTO_ID); $crate::app_crypto_signature_common!($module::Signature, $key_type); }; } @@ -86,7 +92,7 @@ macro_rules! app_crypto { /// Application-specific type whose identifier is `$key_type`. #[macro_export] macro_rules! app_crypto_pair { - ($pair:ty, $key_type:expr) => { + ($pair:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $pair crypto; this has no specific App. #[derive(Clone)] @@ -141,6 +147,7 @@ macro_rules! app_crypto_pair { type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } impl $crate::AppPair for Pair { @@ -183,7 +190,7 @@ macro_rules! app_crypto_pair_functions_if_std { #[doc(hidden)] #[macro_export] macro_rules! app_crypto_public_full_crypto { - ($public:ty, $key_type:expr) => { + ($public:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( @@ -206,6 +213,7 @@ macro_rules! app_crypto_public_full_crypto { type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } } } @@ -217,7 +225,7 @@ macro_rules! app_crypto_public_full_crypto { #[doc(hidden)] #[macro_export] macro_rules! app_crypto_public_not_full_crypto { - ($public:ty, $key_type:expr) => { + ($public:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( @@ -236,6 +244,7 @@ macro_rules! app_crypto_public_not_full_crypto { type Public = Public; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } } } @@ -246,7 +255,7 @@ macro_rules! app_crypto_public_not_full_crypto { #[doc(hidden)] #[macro_export] macro_rules! app_crypto_public_common { - ($public:ty, $sig:ty, $key_type:expr) => { + ($public:ty, $sig:ty, $key_type:expr, $crypto_type:expr) => { $crate::app_crypto_public_common_if_std!(); impl AsRef<[u8]> for Public { @@ -259,6 +268,10 @@ macro_rules! app_crypto_public_common { impl $crate::Public for Public { fn from_slice(x: &[u8]) -> Self { Self(<$public>::from_slice(x)) } + + fn to_public_crypto_pair(&self) -> $crate::CryptoTypePublicPair { + $crate::CryptoTypePublicPair($crypto_type, self.to_raw_vec()) + } } impl $crate::AppPublic for Public { @@ -267,6 +280,8 @@ macro_rules! app_crypto_public_common { impl $crate::RuntimeAppPublic for Public where $public: $crate::RuntimePublic { const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; + type Signature = Signature; fn all() -> $crate::Vec { @@ -293,6 +308,21 @@ macro_rules! app_crypto_public_common { <$public as $crate::RuntimePublic>::to_raw_vec(&self.0) } } + + impl From for $crate::CryptoTypePublicPair { + fn from(key: Public) -> Self { + (&key).into() + } + } + + impl From<&Public> for $crate::CryptoTypePublicPair { + fn from(key: &Public) -> Self { + $crate::CryptoTypePublicPair( + $crypto_type, + $crate::Public::to_raw_vec(key), + ) + } + } } } @@ -355,7 +385,7 @@ macro_rules! app_crypto_public_common_if_std { #[doc(hidden)] #[macro_export] macro_rules! app_crypto_signature_full_crypto { - ($sig:ty, $key_type:expr) => { + ($sig:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive(Clone, Default, Eq, PartialEq, @@ -377,6 +407,7 @@ macro_rules! app_crypto_signature_full_crypto { type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } } } @@ -388,7 +419,7 @@ macro_rules! app_crypto_signature_full_crypto { #[doc(hidden)] #[macro_export] macro_rules! app_crypto_signature_not_full_crypto { - ($sig:ty, $key_type:expr) => { + ($sig:ty, $key_type:expr, $crypto_type:expr) => { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive(Clone, Default, Eq, PartialEq, @@ -406,6 +437,7 @@ macro_rules! app_crypto_signature_not_full_crypto { type Public = Public; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; + const CRYPTO_ID: $crate::CryptoTypeId = $crypto_type; } } } @@ -430,6 +462,14 @@ macro_rules! app_crypto_signature_common { impl $crate::AppSignature for Signature { type Generic = $sig; } + + impl $crate::TryFrom<$crate::Vec> for Signature { + type Error = (); + + fn try_from(data: $crate::Vec) -> Result { + Ok(<$sig>::try_from(data.as_slice())?.into()) + } + } } } diff --git a/primitives/application-crypto/src/sr25519.rs b/primitives/application-crypto/src/sr25519.rs index a0f2cef1c4e45b6150be335ac271e3dd592febbe..4700e0f756717345ca68e1c320bdf185f4a6fa47 100644 --- a/primitives/application-crypto/src/sr25519.rs +++ b/primitives/application-crypto/src/sr25519.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Sr25519 crypto types. @@ -23,27 +24,13 @@ use sp_std::vec::Vec; pub use sp_core::sr25519::*; mod app { - use sp_core::crypto::{CryptoTypePublicPair, Public as TraitPublic}; use sp_core::testing::SR25519; - use sp_core::sr25519::CRYPTO_ID; crate::app_crypto!(super, SR25519); impl crate::traits::BoundToRuntimeAppPublic for Public { type Public = Self; } - - impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } - } - - impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } - } } pub use app::{Public as AppPublic, Signature as AppSignature}; diff --git a/primitives/application-crypto/src/traits.rs b/primitives/application-crypto/src/traits.rs index 2af039a88df4c3734fbce447072ebcd051ebcc41..f06e194aefddf07a5ee377508b21f55ccd785156 100644 --- a/primitives/application-crypto/src/traits.rs +++ b/primitives/application-crypto/src/traits.rs @@ -1,24 +1,25 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[cfg(feature = "full_crypto")] use sp_core::crypto::Pair; use codec::Codec; -use sp_core::crypto::{KeyTypeId, CryptoType, IsWrappedBy, Public}; +use sp_core::crypto::{KeyTypeId, CryptoType, CryptoTypeId, IsWrappedBy, Public}; use sp_std::{fmt::Debug, vec::Vec}; /// An application-specific key. @@ -38,6 +39,8 @@ pub trait AppKey: 'static + Send + Sync + Sized + CryptoType + Clone { /// An identifier for this application-specific key type. const ID: KeyTypeId; + /// The identifier of the crypto type of this application-specific key type. + const CRYPTO_ID: CryptoTypeId; } /// Type which implements Hash in std, not when no-std (std variant). @@ -115,6 +118,8 @@ pub trait RuntimePublic: Sized { pub trait RuntimeAppPublic: Sized { /// An identifier for this application-specific key type. const ID: KeyTypeId; + /// The identifier of the crypto type of this application-specific key type. + const CRYPTO_ID: CryptoTypeId; /// The signature that will be generated when signing with the corresponding private key. type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone; diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml index 47b477ddd37df6e11207dd86e68d670d5a8e9225..df7fc5169877cbb1bf1b15e91d244f2b241e16b5 100644 --- a/primitives/application-crypto/test/Cargo.toml +++ b/primitives/application-crypto/test/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-application-crypto-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" description = "Integration tests for application-crypto" -license = "GPL-3.0" +license = "Apache-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -13,8 +13,8 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../core" } -substrate-test-runtime-client = { version = "2.0.0-dev", path = "../../../test-utils/runtime/client" } -sp-runtime = { version = "2.0.0-dev", path = "../../runtime" } -sp-api = { version = "2.0.0-dev", path = "../../api" } -sp-application-crypto = { version = "2.0.0-dev", path = "../" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../core" } +substrate-test-runtime-client = { version = "2.0.0-rc2", path = "../../../test-utils/runtime/client" } +sp-runtime = { version = "2.0.0-rc2", path = "../../runtime" } +sp-api = { version = "2.0.0-rc2", path = "../../api" } +sp-application-crypto = { version = "2.0.0-rc2", path = "../" } diff --git a/primitives/application-crypto/test/src/ecdsa.rs b/primitives/application-crypto/test/src/ecdsa.rs new file mode 100644 index 0000000000000000000000000000000000000000..9b5619b7c123e28ebc41559c69e52588f1e5ce76 --- /dev/null +++ b/primitives/application-crypto/test/src/ecdsa.rs @@ -0,0 +1,42 @@ +// Copyright 2019-2020 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 . + +//! Integration tests for ecdsa + +use sp_runtime::generic::BlockId; +use sp_core::{ + crypto::Pair, + testing::{KeyStore, ECDSA}, +}; +use substrate_test_runtime_client::{ + TestClientBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt, + runtime::TestAPI, +}; +use sp_api::ProvideRuntimeApi; +use sp_application_crypto::ecdsa::{AppPair, AppPublic}; + +#[test] +fn ecdsa_works_in_runtime() { + let keystore = KeyStore::new(); + let test_client = TestClientBuilder::new().set_keystore(keystore.clone()).build(); + let (signature, public) = test_client.runtime_api() + .test_ecdsa_crypto(&BlockId::Number(0)) + .expect("Tests `ecdsa` crypto."); + + let supported_keys = keystore.read().keys(ECDSA).unwrap(); + assert!(supported_keys.contains(&public.clone().into())); + assert!(AppPair::verify(&signature, "ecdsa", &AppPublic::from(public))); +} diff --git a/primitives/application-crypto/test/src/ed25519.rs b/primitives/application-crypto/test/src/ed25519.rs index 1d72962829a53309ed4146a5f8657820ba15b697..ecdaabc30f10c06be086d3896080ee66a18cfc57 100644 --- a/primitives/application-crypto/test/src/ed25519.rs +++ b/primitives/application-crypto/test/src/ed25519.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Integration tests for ed25519 diff --git a/primitives/application-crypto/test/src/lib.rs b/primitives/application-crypto/test/src/lib.rs index cb045e81a7871c5b72003266656f17a346cc17bd..b78539239691adb9baa606c780d903eecec47265 100644 --- a/primitives/application-crypto/test/src/lib.rs +++ b/primitives/application-crypto/test/src/lib.rs @@ -1,22 +1,25 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Integration tests for application crypto #[cfg(test)] mod ed25519; #[cfg(test)] -mod sr25519; \ No newline at end of file +mod sr25519; +#[cfg(test)] +mod ecdsa; diff --git a/primitives/application-crypto/test/src/sr25519.rs b/primitives/application-crypto/test/src/sr25519.rs index f2c7c48b2bc91c0329ecaad7541be5f13f3f754c..55aaf1eac43b25aa8215b9bf7fc6dad4c45ba8d7 100644 --- a/primitives/application-crypto/test/src/sr25519.rs +++ b/primitives/application-crypto/test/src/sr25519.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Integration tests for sr25519 diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml index 70efb4ac4a852df086d14a00f506c0ab826411d2..5953d89e9c52222b1ef5d604486c2819fb6429f2 100644 --- a/primitives/arithmetic/Cargo.toml +++ b/primitives/arithmetic/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-arithmetic" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Minimal fixed point arithmetic primitives and types for runtime." @@ -17,15 +17,15 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } integer-sqrt = "0.1.2" num-traits = { version = "0.2.8", default-features = false } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-debug-derive = { version = "2.0.0-dev", default-features = false, path = "../../primitives/debug-derive" } -primitive-types = { version = "0.7.0", default-features = false } +sp-debug-derive = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/debug-derive" } [dev-dependencies] rand = "0.7.2" criterion = "0.3" serde_json = "1.0" +primitive-types = "0.7.0" [features] default = ["std"] @@ -35,7 +35,6 @@ std = [ "sp-std/std", "serde", "sp-debug-derive/std", - "primitive-types/std", ] [[bench]] diff --git a/primitives/arithmetic/benches/bench.rs b/primitives/arithmetic/benches/bench.rs index 1dbcf260affc33cd6962ebd64dd58d8636e581ad..7a576c8af144bdd3e18b0c71236cbbeb13e9960e 100644 --- a/primitives/arithmetic/benches/bench.rs +++ b/primitives/arithmetic/benches/bench.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use criterion::{Criterion, Throughput, BenchmarkId, criterion_group, criterion_main}; use sp_arithmetic::biguint::{BigUint, Single}; diff --git a/primitives/arithmetic/fuzzer/Cargo.lock b/primitives/arithmetic/fuzzer/Cargo.lock deleted file mode 100644 index 3a4187437ae7312ec7016cb9e41638a018cfcbbf..0000000000000000000000000000000000000000 --- a/primitives/arithmetic/fuzzer/Cargo.lock +++ /dev/null @@ -1,401 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "arbitrary" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" - -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" - -[[package]] -name = "autocfg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" - -[[package]] -name = "bitvec" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" - -[[package]] -name = "byte-slice-cast" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" - -[[package]] -name = "byteorder" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" - -[[package]] -name = "c2-chacha" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -dependencies = [ - "ppv-lite86", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "fixed-hash" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "getrandom" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "honggfuzz" -version = "0.5.45" -dependencies = [ - "arbitrary", - "lazy_static", - "memmap", -] - -[[package]] -name = "impl-codec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "integer-sqrt" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65877bf7d44897a473350b1046277941cee20b263397e90869c50b6e766088b" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" - -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" -dependencies = [ - "autocfg", -] - -[[package]] -name = "parity-scale-codec" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f509c5e67ca0605ee17dcd3f91ef41cadd685c75a298fb6261b781a5acb3f910" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0ec292e92e8ec7c58e576adacc1e3f399c597c8f263c42f18420abe58e7245" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" - -[[package]] -name = "primitive-types" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4336f4f5d5524fa60bcbd6fe626f9223d8142a50e7053e979acdf0da41ab975" -dependencies = [ - "fixed-hash", - "impl-codec", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro2" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -dependencies = [ - "c2-chacha", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "serde" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sp-arithmetic" -version = "2.0.0-alpha.3" -dependencies = [ - "integer-sqrt", - "num-traits", - "parity-scale-codec", - "serde", - "sp-debug-derive", - "sp-std", -] - -[[package]] -name = "sp-arithmetic-fuzzer" -version = "2.0.0" -dependencies = [ - "honggfuzz", - "num-bigint", - "num-traits", - "primitive-types", - "sp-arithmetic", -] - -[[package]] -name = "sp-debug-derive" -version = "2.0.0-alpha.3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sp-std" -version = "2.0.0-alpha.3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "toml" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -dependencies = [ - "serde", -] - -[[package]] -name = "uint" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" -dependencies = [ - "byteorder", - "crunchy", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/primitives/arithmetic/fuzzer/Cargo.toml b/primitives/arithmetic/fuzzer/Cargo.toml index f145c2cd9040c9594490a9674adca967d3dde447..f870152f54840ebd98461d1b67b43644ec59c555 100644 --- a/primitives/arithmetic/fuzzer/Cargo.toml +++ b/primitives/arithmetic/fuzzer/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-arithmetic-fuzzer" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Fuzzer for fixed point arithmetic primitives." @@ -14,8 +14,8 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-arithmetic = { version = "2.0.0-dev", path = ".." } -honggfuzz = "0.5" +sp-arithmetic = { version = "2.0.0-rc2", path = ".." } +honggfuzz = "0.5.49" primitive-types = "0.7.0" num-bigint = "0.2" num-traits = "0.2" @@ -31,3 +31,7 @@ path = "src/per_thing_rational.rs" [[bin]] name = "rational128" path = "src/rational128.rs" + +[[bin]] +name = "fixed" +path = "src/fixed.rs" \ No newline at end of file diff --git a/primitives/arithmetic/fuzzer/src/biguint.rs b/primitives/arithmetic/fuzzer/src/biguint.rs index f217b080d25fa80c5c2199efb1440add203e9f06..0966c128954a7e4984ad2f168a46cc295b6077ef 100644 --- a/primitives/arithmetic/fuzzer/src/biguint.rs +++ b/primitives/arithmetic/fuzzer/src/biguint.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Running //! Running this fuzzer can be done with `cargo hfuzz run biguint`. `honggfuzz` CLI options can diff --git a/primitives/arithmetic/fuzzer/src/fixed.rs b/primitives/arithmetic/fuzzer/src/fixed.rs new file mode 100644 index 0000000000000000000000000000000000000000..115d7dbbdba05536e8780a8c82db1aeb0da0fb57 --- /dev/null +++ b/primitives/arithmetic/fuzzer/src/fixed.rs @@ -0,0 +1,82 @@ +// This file is part of Substrate. + +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run fixed`. `honggfuzz` CLI options can +//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. +//! +//! # Debugging a panic +//! Once a panic is found, it can be debugged with +//! `cargo hfuzz run-debug fixed hfuzz_workspace/fixed/*.fuzz`. +//! +//! # More information +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/). + +use honggfuzz::fuzz; +use sp_arithmetic::{FixedPointNumber, Fixed64, traits::Saturating}; + +fn main() { + loop { + fuzz!(|data: (i32, i32)| { + let x: i128 = data.0.into(); + let y: i128 = data.1.into(); + + // Check `from_rational` and division are consistent. + if y != 0 { + let f1 = Fixed64::saturating_from_integer(x) / Fixed64::saturating_from_integer(y); + let f2 = Fixed64::saturating_from_rational(x, y); + assert_eq!(f1.into_inner(), f2.into_inner()); + } + + // Check `saturating_mul`. + let a = Fixed64::saturating_from_rational(2, 5); + let b = a.saturating_mul(Fixed64::saturating_from_integer(x)); + let n = b.into_inner() as i128; + let m = 2i128 * x * Fixed64::accuracy() as i128 / 5i128; + assert_eq!(n, m); + + // Check `saturating_mul` and division are inverse. + if x != 0 { + assert_eq!(a, b / Fixed64::saturating_from_integer(x)); + } + + // Check `reciprocal`. + let r = a.reciprocal().unwrap().reciprocal().unwrap(); + assert_eq!(a, r); + + // Check addition. + let a = Fixed64::saturating_from_integer(x); + let b = Fixed64::saturating_from_integer(y); + let c = Fixed64::saturating_from_integer(x.saturating_add(y)); + assert_eq!(a.saturating_add(b), c); + + // Check substraction. + let a = Fixed64::saturating_from_integer(x); + let b = Fixed64::saturating_from_integer(y); + let c = Fixed64::saturating_from_integer(x.saturating_sub(y)); + assert_eq!(a.saturating_sub(b), c); + + // Check `saturating_mul_acc_int`. + let a = Fixed64::saturating_from_rational(2, 5); + let b = a.saturating_mul_acc_int(x); + let xx = Fixed64::saturating_from_integer(x); + let d = a.saturating_mul(xx).saturating_add(xx).into_inner() as i128 / Fixed64::accuracy() as i128; + assert_eq!(b, d); + }); + } +} diff --git a/primitives/arithmetic/fuzzer/src/per_thing_rational.rs b/primitives/arithmetic/fuzzer/src/per_thing_rational.rs index c2dda3de2299cb713114a856c6eafbedf2d91be2..0820a35100aee1217f37f75b0657f9761b6926c7 100644 --- a/primitives/arithmetic/fuzzer/src/per_thing_rational.rs +++ b/primitives/arithmetic/fuzzer/src/per_thing_rational.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Running //! Running this fuzzer can be done with `cargo hfuzz run per_thing_rational`. `honggfuzz` CLI options can diff --git a/primitives/arithmetic/fuzzer/src/rational128.rs b/primitives/arithmetic/fuzzer/src/rational128.rs index 586a165272244bc0ab8ee7a7ec5c5813de9b0a0e..7a33e46991aa1ed38ba581d2b594b9bf1f161be4 100644 --- a/primitives/arithmetic/fuzzer/src/rational128.rs +++ b/primitives/arithmetic/fuzzer/src/rational128.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! # Running //! Running this fuzzer can be done with `cargo hfuzz run rational128`. `honggfuzz` CLI options can diff --git a/primitives/arithmetic/src/biguint.rs b/primitives/arithmetic/src/biguint.rs index 6c3ca58a52d1f72c21fa548adcb5728e03be0ddf..41e2c759a59679a25eda9d42655eee83559cd4b4 100644 --- a/primitives/arithmetic/src/biguint.rs +++ b/primitives/arithmetic/src/biguint.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Infinite precision unsigned integer for substrate runtime. @@ -150,7 +151,7 @@ impl BigUint { // has the ability to cause this. There is nothing to do if the number already has 1 // limb only. call it a day and return. if self.len().is_zero() { return; } - let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(0); + let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(self.len() - 1); if index > 0 { self.digits = self.digits[index..].to_vec() @@ -580,19 +581,19 @@ pub mod tests { fn strip_works() { let mut a = BigUint::from_limbs(&[0, 1, 0]); a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1, 0] }); + assert_eq!(a.digits, vec![1, 0]); let mut a = BigUint::from_limbs(&[0, 0, 1]); a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1] }); + assert_eq!(a.digits, vec![1]); let mut a = BigUint::from_limbs(&[0, 0]); a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); + assert_eq!(a.digits, vec![0]); let mut a = BigUint::from_limbs(&[0, 0, 0]); a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); + assert_eq!(a.digits, vec![0]); } #[test] diff --git a/primitives/arithmetic/src/fixed.rs b/primitives/arithmetic/src/fixed.rs new file mode 100644 index 0000000000000000000000000000000000000000..bc657c5ede3976401a7956c2144d3978433eedb7 --- /dev/null +++ b/primitives/arithmetic/src/fixed.rs @@ -0,0 +1,1533 @@ +// Copyright 2020 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 . + +//! Decimal Fixed Point implementations for Substrate runtime. + +use sp_std::{ops::{self, Add, Sub, Mul, Div}, fmt::Debug, prelude::*, convert::{TryInto, TryFrom}}; +use codec::{Encode, Decode}; +use crate::{ + helpers_128bit::multiply_by_rational, PerThing, + traits::{ + SaturatedConversion, CheckedSub, CheckedAdd, CheckedMul, CheckedDiv, CheckedNeg, + Bounded, Saturating, UniqueSaturatedInto, Zero, One, Signed + }, +}; + +#[cfg(feature = "std")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +/// Integer types that can be used to interact with `FixedPointNumber` implementations. +pub trait FixedPointOperand: Copy + Clone + Bounded + Zero + Saturating + + PartialOrd + UniqueSaturatedInto + TryFrom + CheckedNeg {} + +impl FixedPointOperand for i128 {} +impl FixedPointOperand for u128 {} +impl FixedPointOperand for i64 {} +impl FixedPointOperand for u64 {} +impl FixedPointOperand for i32 {} +impl FixedPointOperand for u32 {} +impl FixedPointOperand for i16 {} +impl FixedPointOperand for u16 {} +impl FixedPointOperand for i8 {} +impl FixedPointOperand for u8 {} + +/// Something that implements a decimal fixed point number. +/// +/// The precision is given by `Self::DIV`, i.e. `1 / DIV` can be represented. +/// +/// Each type can store numbers from `Self::Inner::min_value() / Self::DIV` +/// to `Self::Inner::max_value() / Self::DIV`. +/// This is also referred to as the _accuracy_ of the type in the documentation. +pub trait FixedPointNumber: + Sized + Copy + Default + Debug + + Saturating + Bounded + + Eq + PartialEq + Ord + PartialOrd + + CheckedSub + CheckedAdd + CheckedMul + CheckedDiv + + Add + Sub + Div + Mul +{ + /// The underlying data type used for this fixed point number. + type Inner: Debug + One + CheckedMul + CheckedDiv + CheckedNeg + Signed + FixedPointOperand; + + /// Precision of this fixed point implementation. It should be a power of `10`. + const DIV: Self::Inner; + + /// Precision of this fixed point implementation. + fn accuracy() -> Self::Inner { + Self::DIV + } + + /// Builds this type from an integer number. + fn from_inner(int: Self::Inner) -> Self; + + /// Consumes `self` and returns the inner raw value. + fn into_inner(self) -> Self::Inner; + + /// Returns the negation. + fn negate(self) -> Self { + Self::from_inner(-self.into_inner()) + } + + /// Creates self from an integer number `int`. + /// + /// Returns `Self::max` or `Self::min` if `int` exceeds accuracy. + fn saturating_from_integer>(int: N) -> Self { + Self::from_inner(int.unique_saturated_into().saturating_mul(Self::DIV)) + } + + /// Creates `self` from an integer number `int`. + /// + /// Returns `None` if `int` exceeds accuracy. + fn checked_from_integer(int: Self::Inner) -> Option { + int.checked_mul(&Self::DIV).map(|inner| Self::from_inner(inner)) + } + + /// Creates `self` from a rational number. Equal to `n / d`. + /// + /// Panics if `d = 0`. Returns `Self::max` or `Self::min` if `n / d` exceeds accuracy. + fn saturating_from_rational(n: N, d: D) -> Self { + if d == D::zero() { + panic!("attempt to divide by zero") + } + Self::checked_from_rational(n, d).unwrap_or(to_bound(n, d)) + } + + /// Creates `self` from a rational number. Equal to `n / d`. + /// + /// Returns `None` if `d == 0` or `n / d` exceeds accuracy. + fn checked_from_rational(n: N, d: D) -> Option { + if d == D::zero() { + return None + } + + let n: I129 = n.into(); + let d: I129 = d.into(); + let negative = n.negative != d.negative; + + multiply_by_rational(n.value, Self::DIV.unique_saturated_into(), d.value).ok() + .and_then(|value| from_i129(I129 { value, negative })) + .map(|inner| Self::from_inner(inner)) + } + + /// Checked multiplication for integer type `N`. Equal to `self * n`. + /// + /// Returns `None` if the result does not fit in `N`. + fn checked_mul_int(self, n: N) -> Option { + let lhs: I129 = self.into_inner().into(); + let rhs: I129 = n.into(); + let negative = lhs.negative != rhs.negative; + + multiply_by_rational(lhs.value, rhs.value, Self::DIV.unique_saturated_into()).ok() + .and_then(|value| from_i129(I129 { value, negative })) + } + + /// Saturating multiplication for integer type `N`. Equal to `self * n`. + /// + /// Returns `N::min` or `N::max` if the result does not fit in `N`. + fn saturating_mul_int(self, n: N) -> N { + self.checked_mul_int(n).unwrap_or(to_bound(self.into_inner(), n)) + } + + /// Checked division for integer type `N`. Equal to `self / d`. + /// + /// Returns `None` if the result does not fit in `N` or `d == 0`. + fn checked_div_int(self, d: N) -> Option { + let lhs: I129 = self.into_inner().into(); + let rhs: I129 = d.into(); + let negative = lhs.negative != rhs.negative; + + lhs.value.checked_div(rhs.value) + .and_then(|n| n.checked_div(Self::DIV.unique_saturated_into())) + .and_then(|value| from_i129(I129 { value, negative })) + } + + /// Saturating division for integer type `N`. Equal to `self / d`. + /// + /// Panics if `d == 0`. Returns `N::min` or `N::max` if the result does not fit in `N`. + fn saturating_div_int(self, d: N) -> N { + if d == N::zero() { + panic!("attempt to divide by zero") + } + self.checked_div_int(d).unwrap_or(to_bound(self.into_inner(), d)) + } + + /// Saturating multiplication for integer type `N`, adding the result back. + /// Equal to `self * n + n`. + /// + /// Returns `N::min` or `N::max` if the multiplication or final result does not fit in `N`. + fn saturating_mul_acc_int(self, n: N) -> N { + if self.is_negative() && n > N::zero() { + n.saturating_sub(self.negate().saturating_mul_int(n)) + } else { + self.saturating_mul_int(n).saturating_add(n) + } + } + + /// Saturating absolute value. + /// + /// Returns `Self::max` if `self == Self::min`. + fn saturating_abs(self) -> Self { + let inner = self.into_inner(); + if inner.is_positive() { + self + } else { + Self::from_inner(inner.checked_neg().unwrap_or(Self::Inner::max_value())) + } + } + + /// Takes the reciprocal (inverse). Equal to `1 / self`. + /// + /// Returns `None` if `self = 0`. + fn reciprocal(self) -> Option { + Self::one().checked_div(&self) + } + + /// Returns zero. + fn zero() -> Self { + Self::from_inner(Self::Inner::zero()) + } + + /// Checks if the number is zero. + fn is_zero(&self) -> bool { + self.into_inner() == Self::Inner::zero() + } + + /// Returns one. + fn one() -> Self { + Self::from_inner(Self::DIV) + } + + /// Checks if the number is one. + fn is_one(&self) -> bool { + self.into_inner() == Self::Inner::one() + } + + /// Checks if the number is positive. + fn is_positive(self) -> bool { + self.into_inner() >= Self::Inner::zero() + } + + /// Checks if the number is negative. + fn is_negative(self) -> bool { + self.into_inner() < Self::Inner::zero() + } + + /// Returns the integer part. + fn trunc(self) -> Self { + self.into_inner().checked_div(&Self::DIV) + .expect("panics only if DIV is zero, DIV is not zero; qed") + .checked_mul(&Self::DIV) + .map(|inner| Self::from_inner(inner)) + .expect("can not overflow since fixed number is >= integer part") + } + + /// Returns the fractional part. + /// + /// Note: the returned fraction will be non-negative for negative numbers, + /// except in the case where the integer part is zero. + fn frac(self) -> Self { + let integer = self.trunc(); + let fractional = self.saturating_sub(integer); + if integer == Self::zero() { + fractional + } else { + fractional.saturating_abs() + } + } + + /// Returns the smallest integer greater than or equal to a number. + /// + /// Saturates to `Self::max` (truncated) if the result does not fit. + fn ceil(self) -> Self { + if self.is_negative() { + self.trunc() + } else { + self.saturating_add(Self::one()).trunc() + } + } + + /// Returns the largest integer less than or equal to a number. + /// + /// Saturates to `Self::min` (truncated) if the result does not fit. + fn floor(self) -> Self { + if self.is_negative() { + self.saturating_sub(Self::one()).trunc() + } else { + self.trunc() + } + } + + /// Returns the number rounded to the nearest integer. Rounds half-way cases away from 0.0. + /// + /// Saturates to `Self::min` or `Self::max` (truncated) if the result does not fit. + fn round(self) -> Self { + let n = self.frac().saturating_mul(Self::saturating_from_integer(10)); + if n < Self::saturating_from_integer(5) { + self.trunc() + } else { + let extra = Self::saturating_from_integer(self.into_inner().signum()); + (self.saturating_add(extra)).trunc() + } + } +} + +/// Data type used as intermediate storage in some computations to avoid overflow. +struct I129 { + value: u128, + negative: bool, +} + +impl From for I129 { + fn from(n: N) -> I129 { + if n < N::zero() { + let value: u128 = n.checked_neg() + .map(|n| n.unique_saturated_into()) + .unwrap_or(N::max_value().unique_saturated_into().saturating_add(1)); + I129 { value, negative: true } + } else { + I129 { value: n.unique_saturated_into(), negative: false } + } + } +} + +/// Transforms an `I129` to `N` if it is possible. +fn from_i129(n: I129) -> Option { + let max_plus_one: u128 = N::max_value().unique_saturated_into().saturating_add(1); + if n.negative && N::min_value() < N::zero() && n.value == max_plus_one { + Some(N::min_value()) + } else { + let unsigned_inner: N = n.value.try_into().ok()?; + let inner = if n.negative { unsigned_inner.checked_neg()? } else { unsigned_inner }; + Some(inner) + } +} + +/// Returns `R::max` if the sign of `n * m` is positive, `R::min` otherwise. +fn to_bound(n: N, m: D) -> R { + if (n < N::zero()) != (m < D::zero()) { + R::min_value() + } else { + R::max_value() + } +} + +macro_rules! implement_fixed { + ( + $name:ident, + $test_mod:ident, + $inner_type:ty, + $div:tt, + $title:expr $(,)? + ) => { + /// A fixed point number representation in the range. + /// + #[doc = $title] + #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] + pub struct $name($inner_type); + + impl From<$inner_type> for $name { + fn from(int: $inner_type) -> Self { + $name::saturating_from_integer(int) + } + } + + impl From<(N, D)> for $name { + fn from(r: (N, D)) -> Self { + $name::saturating_from_rational(r.0, r.1) + } + } + + impl FixedPointNumber for $name { + type Inner = $inner_type; + + const DIV: Self::Inner = $div; + + fn from_inner(inner: Self::Inner) -> Self { + Self(inner) + } + + fn into_inner(self) -> Self::Inner { + self.0 + } + } + + impl Saturating for $name { + fn saturating_add(self, rhs: Self) -> Self { + Self(self.0.saturating_add(rhs.0)) + } + + fn saturating_sub(self, rhs: Self) -> Self { + Self(self.0.saturating_sub(rhs.0)) + } + + fn saturating_mul(self, rhs: Self) -> Self { + self.checked_mul(&rhs).unwrap_or(to_bound(self.0, rhs.0)) + } + + fn saturating_pow(self, exp: usize) -> Self { + if exp == 0 { + return Self::saturating_from_integer(1); + } + + let exp = exp as u32; + let msb_pos = 32 - exp.leading_zeros(); + + let mut result = Self::saturating_from_integer(1); + let mut pow_val = self; + for i in 0..msb_pos { + if ((1 << i) & exp) > 0 { + result = result.saturating_mul(pow_val); + } + pow_val = pow_val.saturating_mul(pow_val); + } + result + } + } + + impl ops::Neg for $name { + type Output = Self; + + fn neg(self) -> Self::Output { + Self(-self.0) + } + } + + impl ops::Add for $name { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } + } + + impl ops::Sub for $name { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } + } + + impl ops::Mul for $name { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self.checked_mul(&rhs) + .unwrap_or_else(|| panic!("attempt to multiply with overflow")) + } + } + + impl ops::Div for $name { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + if rhs.0 == 0 { + panic!("attempt to divide by zero") + } + self.checked_div(&rhs) + .unwrap_or_else(|| panic!("attempt to divide with overflow")) + } + } + + impl CheckedSub for $name { + fn checked_sub(&self, rhs: &Self) -> Option { + self.0.checked_sub(rhs.0).map(Self) + } + } + + impl CheckedAdd for $name { + fn checked_add(&self, rhs: &Self) -> Option { + self.0.checked_add(rhs.0).map(Self) + } + } + + impl CheckedDiv for $name { + fn checked_div(&self, other: &Self) -> Option { + if other.0 == 0 { + return None + } + + let lhs: I129 = self.0.into(); + let rhs: I129 = other.0.into(); + let negative = lhs.negative != rhs.negative; + + multiply_by_rational(lhs.value, Self::DIV as u128, rhs.value).ok() + .and_then(|value| from_i129(I129 { value, negative })) + .map(Self) + } + } + + impl CheckedMul for $name { + fn checked_mul(&self, other: &Self) -> Option { + let lhs: I129 = self.0.into(); + let rhs: I129 = other.0.into(); + let negative = lhs.negative != rhs.negative; + + multiply_by_rational(lhs.value, rhs.value, Self::DIV as u128).ok() + .and_then(|value| from_i129(I129 { value, negative })) + .map(Self) + } + } + + impl Bounded for $name { + fn min_value() -> Self { + Self(::Inner::min_value()) + } + + fn max_value() -> Self { + Self(::Inner::max_value()) + } + } + + impl sp_std::fmt::Debug for $name { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + let integral = { + let int = self.0 / Self::accuracy(); + let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" }; + format!("{}{}", signum_for_zero, int) + }; + let precision = (Self::accuracy() as f64).log10() as usize; + let fractional = format!("{:0>weight$}", (self.0 % Self::accuracy()).abs(), weight=precision); + write!(f, "{}({}.{})", stringify!($name), integral, fractional) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } + } + + impl From

for $name { + fn from(p: P) -> Self { + let accuracy = P::ACCURACY.saturated_into(); + let value = p.deconstruct().saturated_into(); + $name::saturating_from_rational(value, accuracy) + } + } + + #[cfg(feature = "std")] + impl sp_std::fmt::Display for $name { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "{}", self.0) + } + } + + #[cfg(feature = "std")] + impl sp_std::str::FromStr for $name { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let inner: ::Inner = s.parse() + .map_err(|_| "invalid string input for fixed point number")?; + Ok(Self::from_inner(inner)) + } + } + + // Manual impl `Serialize` as serde_json does not support i128. + // TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed. + #[cfg(feature = "std")] + impl Serialize for $name { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } + } + + // Manual impl `Deserialize` as serde_json does not support i128. + // TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed. + #[cfg(feature = "std")] + impl<'de> Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + use sp_std::str::FromStr; + let s = String::deserialize(deserializer)?; + $name::from_str(&s).map_err(|err_str| de::Error::custom(err_str)) + } + } + + #[cfg(test)] + mod $test_mod { + use super::*; + use crate::{Perbill, Percent, Permill, Perquintill}; + + fn max() -> $name { + $name::max_value() + } + + fn min() -> $name { + $name::min_value() + } + + fn precision() -> usize { + ($name::accuracy() as f64).log10() as usize + } + + #[test] + fn macro_preconditions() { + assert!($name::DIV > 0); + } + + #[test] + fn from_i129_works() { + let a = I129 { + value: 1, + negative: true, + }; + + // Can't convert negative number to unsigned. + assert_eq!(from_i129::(a), None); + + let a = I129 { + value: u128::max_value() - 1, + negative: false, + }; + + // Max - 1 value fits. + assert_eq!(from_i129::(a), Some(u128::max_value() - 1)); + + let a = I129 { + value: u128::max_value(), + negative: false, + }; + + // Max value fits. + assert_eq!(from_i129::(a), Some(u128::max_value())); + + let a = I129 { + value: i128::max_value() as u128 + 1, + negative: true, + }; + + // Min value fits. + assert_eq!(from_i129::(a), Some(i128::min_value())); + + let a = I129 { + value: i128::max_value() as u128 + 1, + negative: false, + }; + + // Max + 1 does not fit. + assert_eq!(from_i129::(a), None); + + let a = I129 { + value: i128::max_value() as u128, + negative: false, + }; + + // Max value fits. + assert_eq!(from_i129::(a), Some(i128::max_value())); + } + + #[test] + fn to_bound_works() { + let a = 1i32; + let b = 1i32; + + // Pos + Pos => Max. + assert_eq!(to_bound::<_, _, i32>(a, b), i32::max_value()); + + let a = -1i32; + let b = -1i32; + + // Neg + Neg => Max. + assert_eq!(to_bound::<_, _, i32>(a, b), i32::max_value()); + + let a = 1i32; + let b = -1i32; + + // Pos + Neg => Min. + assert_eq!(to_bound::<_, _, i32>(a, b), i32::min_value()); + + let a = -1i32; + let b = 1i32; + + // Neg + Pos => Min. + assert_eq!(to_bound::<_, _, i32>(a, b), i32::min_value()); + + let a = 1i32; + let b = -1i32; + + // Pos + Neg => Min (unsigned). + assert_eq!(to_bound::<_, _, u32>(a, b), 0); + } + + #[test] + fn op_neg_works() { + let a = $name::saturating_from_integer(5); + let b = -a; + + // Positive. + assert_eq!($name::saturating_from_integer(-5), b); + + let a = $name::saturating_from_integer(-5); + let b = -a; + + // Negative + assert_eq!($name::saturating_from_integer(5), b); + + let a = $name::max_value(); + let b = -a; + + // Max. + assert_eq!($name::min_value() + $name::from_inner(1), b); + + let a = $name::min_value() + $name::from_inner(1); + let b = -a; + + // Min. + assert_eq!($name::max_value(), b); + + let a = $name::zero(); + let b = -a; + + // Zero. + assert_eq!(a, b); + } + + #[test] + fn op_checked_add_overflow_works() { + let a = $name::max_value(); + let b = 1.into(); + assert!(a.checked_add(&b).is_none()); + } + + #[test] + fn op_add_works() { + let a = $name::saturating_from_rational(5, 2); + let b = $name::saturating_from_rational(1, 2); + + // Positive case: 6/2 = 3. + assert_eq!($name::saturating_from_integer(3), a + b); + + let b = $name::saturating_from_rational(1, -2); + + // Negative case: 4/2 = 2. + assert_eq!($name::saturating_from_integer(2), a + b); + } + + #[test] + fn op_checked_sub_underflow_works() { + let a = $name::min_value(); + let b = 1.into(); + assert!(a.checked_sub(&b).is_none()); + } + + #[test] + fn op_sub_works() { + let a = $name::saturating_from_rational(5, 2); + let b = $name::saturating_from_rational(1, 2); + + // Negative case: 4/2 = 2. + assert_eq!($name::saturating_from_integer(2), a - b); + + let b = $name::saturating_from_rational(1, -2); + + // Positive case: 6/2 = 3. + assert_eq!($name::saturating_from_integer(3), a - b); + } + + #[test] + fn op_checked_mul_overflow_works() { + let a = $name::max_value(); + let b = 2.into(); + assert!(a.checked_mul(&b).is_none()); + } + + #[test] + fn op_mul_works() { + let a = $name::saturating_from_integer(42); + let b = $name::saturating_from_integer(2); + assert_eq!($name::saturating_from_integer(84), a * b); + + let a = $name::saturating_from_integer(42); + let b = $name::saturating_from_integer(-2); + assert_eq!($name::saturating_from_integer(-84), a * b); + } + + #[test] + #[should_panic(expected = "attempt to divide by zero")] + fn op_div_panics_on_zero_divisor() { + let a = $name::saturating_from_integer(1); + let b = 0.into(); + let _c = a / b; + } + + #[test] + fn op_checked_div_overflow_works() { + let a = $name::min_value(); + let b = (-1).into(); + assert!(a.checked_div(&b).is_none()); + } + + #[test] + fn op_div_works() { + let a = $name::saturating_from_integer(42); + let b = $name::saturating_from_integer(2); + assert_eq!($name::saturating_from_integer(21), a / b); + + let a = $name::saturating_from_integer(42); + let b = $name::saturating_from_integer(-2); + assert_eq!($name::saturating_from_integer(-21), a / b); + } + + #[test] + fn from_integer_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + // Cases where integer fits. + let a = $name::saturating_from_integer(42); + assert_eq!(a.into_inner(), 42 * accuracy); + + let a = $name::saturating_from_integer(-42); + assert_eq!(a.into_inner(), -42 * accuracy); + + // Max/min integers that fit. + let a = $name::saturating_from_integer(inner_max / accuracy); + assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy); + + let a = $name::saturating_from_integer(inner_min / accuracy); + assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy); + + // Cases where integer doesn't fit, so it saturates. + let a = $name::saturating_from_integer(inner_max / accuracy + 1); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_integer(inner_min / accuracy - 1); + assert_eq!(a.into_inner(), inner_min); + } + + #[test] + fn checked_from_integer_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + // Cases where integer fits. + let a = $name::checked_from_integer(42) + .expect("42 * accuracy <= inner_max; qed"); + assert_eq!(a.into_inner(), 42 * accuracy); + + let a = $name::checked_from_integer(-42) + .expect("-42 * accuracy >= inner_min; qed"); + assert_eq!(a.into_inner(), -42 * accuracy); + + // Max/min integers that fit. + let a = $name::checked_from_integer(inner_max / accuracy) + .expect("(inner_max / accuracy) * accuracy <= inner_max; qed"); + assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy); + + let a = $name::checked_from_integer(inner_min / accuracy) + .expect("(inner_min / accuracy) * accuracy <= inner_min; qed"); + assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy); + + // Cases where integer doesn't fit, so it returns `None`. + let a = $name::checked_from_integer(inner_max / accuracy + 1); + assert_eq!(a, None); + + let a = $name::checked_from_integer(inner_min / accuracy - 1); + assert_eq!(a, None); + } + + #[test] + fn from_inner_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + + assert_eq!(max(), $name::from_inner(inner_max)); + assert_eq!(min(), $name::from_inner(inner_min)); + } + + #[test] + #[should_panic(expected = "attempt to divide by zero")] + fn saturating_from_rational_panics_on_zero_divisor() { + let _ = $name::saturating_from_rational(1, 0); + } + + #[test] + fn saturating_from_rational_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + let a = $name::saturating_from_rational(5, 2); + + // Positive case: 2.5 + assert_eq!(a.into_inner(), 25 * accuracy / 10); + + let a = $name::saturating_from_rational(-5, 2); + + // Negative case: -2.5 + assert_eq!(a.into_inner(), -25 * accuracy / 10); + + let a = $name::saturating_from_rational(5, -2); + + // Other negative case: -2.5 + assert_eq!(a.into_inner(), -25 * accuracy / 10); + + let a = $name::saturating_from_rational(-5, -2); + + // Other positive case: 2.5 + assert_eq!(a.into_inner(), 25 * accuracy / 10); + + // Max - 1. + let a = $name::saturating_from_rational(inner_max - 1, accuracy); + assert_eq!(a.into_inner(), inner_max - 1); + + // Min + 1. + let a = $name::saturating_from_rational(inner_min + 1, accuracy); + assert_eq!(a.into_inner(), inner_min + 1); + + // Max. + let a = $name::saturating_from_rational(inner_max, accuracy); + assert_eq!(a.into_inner(), inner_max); + + // Min. + let a = $name::saturating_from_rational(inner_min, accuracy); + assert_eq!(a.into_inner(), inner_min); + + // Max + 1, saturates. + let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy); + assert_eq!(a.into_inner(), inner_max); + + // Min - 1, saturates. + let a = $name::saturating_from_rational(inner_max as u128 + 2, -accuracy); + assert_eq!(a.into_inner(), inner_min); + + // Zero. + let a = $name::saturating_from_rational(0, 1); + assert_eq!(a.into_inner(), 0); + + let a = $name::saturating_from_rational(inner_max, -accuracy); + assert_eq!(a.into_inner(), -inner_max); + + let a = $name::saturating_from_rational(inner_min, -accuracy); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_min + 1, -accuracy); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_max - 1, accuracy); + assert_eq!(a.into_inner(), inner_max - 1); + + let a = $name::saturating_from_rational(inner_min + 1, accuracy); + assert_eq!(a.into_inner(), inner_min + 1); + + let a = $name::saturating_from_rational(inner_max, 1); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_min, 1); + assert_eq!(a.into_inner(), inner_min); + + let a = $name::saturating_from_rational(inner_min, -1); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_max, -1); + assert_eq!(a.into_inner(), inner_min); + + let a = $name::saturating_from_rational(inner_max, inner_max); + assert_eq!(a.into_inner(), accuracy); + + let a = $name::saturating_from_rational(inner_min, inner_min); + assert_eq!(a.into_inner(), accuracy); + + let a = $name::saturating_from_rational(inner_max, -inner_max); + assert_eq!(a.into_inner(), -accuracy); + + let a = $name::saturating_from_rational(-inner_max, inner_max); + assert_eq!(a.into_inner(), -accuracy); + + let a = $name::saturating_from_rational(inner_max, 3 * accuracy); + assert_eq!(a.into_inner(), inner_max / 3); + + let a = $name::saturating_from_rational(inner_max, -3 * accuracy); + assert_eq!(a.into_inner(), -inner_max / 3); + + let a = $name::saturating_from_rational(inner_min, 2 * accuracy); + assert_eq!(a.into_inner(), inner_min / 2); + + let a = $name::saturating_from_rational(inner_min, accuracy / -3); + assert_eq!(a.into_inner(), inner_max); + + let a = $name::saturating_from_rational(inner_min, accuracy / 3); + assert_eq!(a.into_inner(), inner_min); + + let a = $name::saturating_from_rational(1, accuracy); + assert_eq!(a.into_inner(), 1); + + let a = $name::saturating_from_rational(1, -accuracy); + assert_eq!(a.into_inner(), -1); + + // Out of accuracy. + let a = $name::saturating_from_rational(1, accuracy + 1); + assert_eq!(a.into_inner(), 0); + + let a = $name::saturating_from_rational(1, -accuracy - 1); + assert_eq!(a.into_inner(), 0); + } + + #[test] + fn checked_from_rational_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + // Divide by zero => None. + let a = $name::checked_from_rational(1, 0); + assert_eq!(a, None); + + // Max - 1. + let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_max - 1); + + // Min + 1. + let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_min + 1); + + // Max. + let a = $name::checked_from_rational(inner_max, accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_max); + + // Min. + let a = $name::checked_from_rational(inner_min, accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_min); + + // Max + 1 => Overflow => None. + let a = $name::checked_from_rational(inner_min, -accuracy); + assert_eq!(a, None); + + // Min - 1 => Underflow => None. + let a = $name::checked_from_rational(inner_max as u128 + 2, -accuracy); + assert_eq!(a, None); + + let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_max / 3); + + let a = $name::checked_from_rational(inner_max, -3 * accuracy).unwrap(); + assert_eq!(a.into_inner(), -inner_max / 3); + + let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap(); + assert_eq!(a.into_inner(), inner_min / 2); + + let a = $name::checked_from_rational(inner_min, accuracy / -3); + assert_eq!(a, None); + + let a = $name::checked_from_rational(inner_min, accuracy / 3); + assert_eq!(a, None); + + let a = $name::checked_from_rational(1, accuracy).unwrap(); + assert_eq!(a.into_inner(), 1); + + let a = $name::checked_from_rational(1, -accuracy).unwrap(); + assert_eq!(a.into_inner(), -1); + + let a = $name::checked_from_rational(1, accuracy + 1).unwrap(); + assert_eq!(a.into_inner(), 0); + + let a = $name::checked_from_rational(1, -accuracy - 1).unwrap(); + assert_eq!(a.into_inner(), 0); + } + + #[test] + fn checked_mul_int_works() { + let a = $name::saturating_from_integer(2); + // Max - 1. + assert_eq!(a.checked_mul_int((i128::max_value() - 1) / 2), Some(i128::max_value() - 1)); + // Max. + assert_eq!(a.checked_mul_int(i128::max_value() / 2), Some(i128::max_value() - 1)); + // Max + 1 => None. + assert_eq!(a.checked_mul_int(i128::max_value() / 2 + 1), None); + + // Min - 1. + assert_eq!(a.checked_mul_int((i128::min_value() + 1) / 2), Some(i128::min_value() + 2)); + // Min. + assert_eq!(a.checked_mul_int(i128::min_value() / 2), Some(i128::min_value())); + // Min + 1 => None. + assert_eq!(a.checked_mul_int(i128::min_value() / 2 - 1), None); + + let a = $name::saturating_from_rational(1, 2); + assert_eq!(a.checked_mul_int(42i128), Some(21)); + assert_eq!(a.checked_mul_int(i128::max_value()), Some(i128::max_value() / 2)); + assert_eq!(a.checked_mul_int(i128::min_value()), Some(i128::min_value() / 2)); + + let b = $name::saturating_from_rational(1, -2); + assert_eq!(b.checked_mul_int(42i128), Some(-21)); + assert_eq!(b.checked_mul_int(u128::max_value()), None); + assert_eq!(b.checked_mul_int(i128::max_value()), Some(i128::max_value() / -2)); + assert_eq!(b.checked_mul_int(i128::min_value()), Some(i128::min_value() / -2)); + + let c = $name::saturating_from_integer(255); + assert_eq!(c.checked_mul_int(2i8), None); + assert_eq!(c.checked_mul_int(2i128), Some(510)); + assert_eq!(c.checked_mul_int(i128::max_value()), None); + assert_eq!(c.checked_mul_int(i128::min_value()), None); + } + + #[test] + fn saturating_mul_int_works() { + let a = $name::saturating_from_integer(2); + // Max - 1. + assert_eq!(a.saturating_mul_int((i128::max_value() - 1) / 2), i128::max_value() - 1); + // Max. + assert_eq!(a.saturating_mul_int(i128::max_value() / 2), i128::max_value() - 1); + // Max + 1 => saturates to max. + assert_eq!(a.saturating_mul_int(i128::max_value() / 2 + 1), i128::max_value()); + + // Min - 1. + assert_eq!(a.saturating_mul_int((i128::min_value() + 1) / 2), i128::min_value() + 2); + // Min. + assert_eq!(a.saturating_mul_int(i128::min_value() / 2), i128::min_value()); + // Min + 1 => saturates to min. + assert_eq!(a.saturating_mul_int(i128::min_value() / 2 - 1), i128::min_value()); + + let a = $name::saturating_from_rational(1, 2); + assert_eq!(a.saturating_mul_int(42i32), 21); + assert_eq!(a.saturating_mul_int(i128::max_value()), i128::max_value() / 2); + assert_eq!(a.saturating_mul_int(i128::min_value()), i128::min_value() / 2); + + let b = $name::saturating_from_rational(1, -2); + assert_eq!(b.saturating_mul_int(42i32), -21); + assert_eq!(b.saturating_mul_int(i128::max_value()), i128::max_value() / -2); + assert_eq!(b.saturating_mul_int(i128::min_value()), i128::min_value() / -2); + assert_eq!(b.saturating_mul_int(u128::max_value()), u128::min_value()); + + let c = $name::saturating_from_integer(255); + assert_eq!(c.saturating_mul_int(2i8), i8::max_value()); + assert_eq!(c.saturating_mul_int(-2i8), i8::min_value()); + assert_eq!(c.saturating_mul_int(i128::max_value()), i128::max_value()); + assert_eq!(c.saturating_mul_int(i128::min_value()), i128::min_value()); + } + + #[test] + fn checked_mul_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + + let a = $name::saturating_from_integer(2); + + // Max - 1. + let b = $name::from_inner(inner_max - 1); + assert_eq!(a.checked_mul(&(b/2.into())), Some(b)); + + // Max. + let c = $name::from_inner(inner_max); + assert_eq!(a.checked_mul(&(c/2.into())), Some(b)); + + // Max + 1 => None. + let e = $name::from_inner(1); + assert_eq!(a.checked_mul(&(c/2.into()+e)), None); + + // Min + 1. + let b = $name::from_inner(inner_min + 1) / 2.into(); + let c = $name::from_inner(inner_min + 2); + assert_eq!(a.checked_mul(&b), Some(c)); + + // Min. + let b = $name::from_inner(inner_min) / 2.into(); + let c = $name::from_inner(inner_min); + assert_eq!(a.checked_mul(&b), Some(c)); + + // Min - 1 => None. + let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1); + assert_eq!(a.checked_mul(&b), None); + + let a = $name::saturating_from_rational(1, 2); + let b = $name::saturating_from_rational(1, -2); + let c = $name::saturating_from_integer(255); + + assert_eq!(a.checked_mul(&42.into()), Some(21.into())); + assert_eq!(b.checked_mul(&42.into()), Some((-21).into())); + assert_eq!(c.checked_mul(&2.into()), Some(510.into())); + + assert_eq!(b.checked_mul(&$name::max_value()), $name::max_value().checked_div(&(-2).into())); + assert_eq!(b.checked_mul(&$name::min_value()), $name::min_value().checked_div(&(-2).into())); + + assert_eq!(c.checked_mul(&$name::max_value()), None); + assert_eq!(c.checked_mul(&$name::min_value()), None); + + assert_eq!(a.checked_mul(&$name::max_value()), $name::max_value().checked_div(&2.into())); + assert_eq!(a.checked_mul(&$name::min_value()), $name::min_value().checked_div(&2.into())); + } + + #[test] + fn checked_div_int_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + let a = $name::from_inner(inner_max); + let b = $name::from_inner(inner_min); + let c = $name::zero(); + let d = $name::one(); + let e = $name::saturating_from_integer(6); + let f = $name::saturating_from_integer(5); + + assert_eq!(e.checked_div_int(2.into()), Some(3)); + assert_eq!(f.checked_div_int(2.into()), Some(2)); + + assert_eq!(a.checked_div_int(i128::max_value()), Some(0)); + assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy))); + assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1)); + assert_eq!(a.checked_div_int(1i8), None); + + assert_eq!(a.checked_div_int(-2), Some(-inner_max / (2 * accuracy))); + assert_eq!(a.checked_div_int(inner_max / -accuracy), Some(-1)); + + assert_eq!(b.checked_div_int(i128::min_value()), Some(0)); + assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy))); + assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1)); + assert_eq!(b.checked_div_int(1i8), None); + + assert_eq!(b.checked_div_int(-2), Some(-(inner_min / (2 * accuracy)))); + assert_eq!(b.checked_div_int(-(inner_min / accuracy)), Some(-1)); + + assert_eq!(c.checked_div_int(1), Some(0)); + assert_eq!(c.checked_div_int(i128::max_value()), Some(0)); + assert_eq!(c.checked_div_int(i128::min_value()), Some(0)); + assert_eq!(c.checked_div_int(1i8), Some(0)); + + assert_eq!(d.checked_div_int(1), Some(1)); + assert_eq!(d.checked_div_int(i32::max_value()), Some(0)); + assert_eq!(d.checked_div_int(i32::min_value()), Some(0)); + assert_eq!(d.checked_div_int(1i8), Some(1)); + + assert_eq!(a.checked_div_int(0), None); + assert_eq!(b.checked_div_int(0), None); + assert_eq!(c.checked_div_int(0), None); + assert_eq!(d.checked_div_int(0), None); + } + + #[test] + #[should_panic(expected = "attempt to divide by zero")] + fn saturating_div_int_panics_when_divisor_is_zero() { + let _ = $name::one().saturating_div_int(0); + } + + #[test] + fn saturating_div_int_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + let accuracy = $name::accuracy(); + + let a = $name::saturating_from_integer(5); + assert_eq!(a.saturating_div_int(2), 2); + + let a = $name::saturating_from_integer(5); + assert_eq!(a.saturating_div_int(-2), -2); + + let a = $name::min_value(); + assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128); + + let a = $name::min_value(); + assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128); + } + + #[test] + fn saturating_abs_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + + assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value()); + assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value()); + assert_eq!($name::zero().saturating_abs(), 0.into()); + assert_eq!($name::saturating_from_rational(-1, 2).saturating_abs(), (1, 2).into()); + } + + #[test] + fn saturating_mul_acc_int_works() { + assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8); + assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8); + + assert_eq!($name::one().saturating_mul_acc_int(i128::max_value()), i128::max_value()); + assert_eq!($name::one().saturating_mul_acc_int(i128::min_value()), i128::min_value()); + + assert_eq!($name::one().saturating_mul_acc_int(u128::max_value() / 2), u128::max_value() - 1); + assert_eq!($name::one().saturating_mul_acc_int(u128::min_value()), u128::min_value()); + + let a = $name::saturating_from_rational(-1, 2); + assert_eq!(a.saturating_mul_acc_int(42i8), 21i8); + assert_eq!(a.saturating_mul_acc_int(42u8), 21u8); + assert_eq!(a.saturating_mul_acc_int(u128::max_value() - 1), u128::max_value() / 2); + } + + #[test] + fn saturating_pow_should_work() { + assert_eq!($name::saturating_from_integer(2).saturating_pow(0), $name::saturating_from_integer(1)); + assert_eq!($name::saturating_from_integer(2).saturating_pow(1), $name::saturating_from_integer(2)); + assert_eq!($name::saturating_from_integer(2).saturating_pow(2), $name::saturating_from_integer(4)); + assert_eq!($name::saturating_from_integer(2).saturating_pow(3), $name::saturating_from_integer(8)); + assert_eq!($name::saturating_from_integer(2).saturating_pow(50), + $name::saturating_from_integer(1125899906842624i64)); + + // Saturating. + assert_eq!($name::saturating_from_integer(2).saturating_pow(68), $name::max_value()); + + assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into()); + assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into()); + assert_eq!($name::saturating_from_integer(-1).saturating_pow(1001), (-1).into()); + assert_eq!($name::saturating_from_integer(1).saturating_pow(usize::max_value()), (1).into()); + assert_eq!($name::saturating_from_integer(-1).saturating_pow(usize::max_value()), (-1).into()); + assert_eq!($name::saturating_from_integer(-1).saturating_pow(usize::max_value() - 1), (1).into()); + + assert_eq!($name::saturating_from_integer(114209).saturating_pow(5), $name::max_value()); + + assert_eq!($name::saturating_from_integer(1).saturating_pow(usize::max_value()), (1).into()); + assert_eq!($name::saturating_from_integer(0).saturating_pow(usize::max_value()), (0).into()); + assert_eq!($name::saturating_from_integer(2).saturating_pow(usize::max_value()), $name::max_value()); + } + + #[test] + fn checked_div_works() { + let inner_max = <$name as FixedPointNumber>::Inner::max_value(); + let inner_min = <$name as FixedPointNumber>::Inner::min_value(); + + let a = $name::from_inner(inner_max); + let b = $name::from_inner(inner_min); + let c = $name::zero(); + let d = $name::one(); + let e = $name::saturating_from_integer(6); + let f = $name::saturating_from_integer(5); + + assert_eq!(e.checked_div(&2.into()), Some(3.into())); + assert_eq!(f.checked_div(&2.into()), Some((5, 2).into())); + + assert_eq!(a.checked_div(&inner_max.into()), Some(1.into())); + assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2))); + assert_eq!(a.checked_div(&$name::max_value()), Some(1.into())); + assert_eq!(a.checked_div(&d), Some(a)); + + assert_eq!(a.checked_div(&(-2).into()), Some($name::from_inner(-inner_max / 2))); + assert_eq!(a.checked_div(&-$name::max_value()), Some((-1).into())); + + assert_eq!(b.checked_div(&b), Some($name::one())); + assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2))); + + assert_eq!(b.checked_div(&(-2).into()), Some($name::from_inner(inner_min / -2))); + assert_eq!(b.checked_div(&a), Some((-1).into())); + + assert_eq!(c.checked_div(&1.into()), Some(0.into())); + assert_eq!(c.checked_div(&$name::max_value()), Some(0.into())); + assert_eq!(c.checked_div(&$name::min_value()), Some(0.into())); + + assert_eq!(d.checked_div(&1.into()), Some(1.into())); + + assert_eq!(a.checked_div(&$name::one()), Some(a)); + assert_eq!(b.checked_div(&$name::one()), Some(b)); + assert_eq!(c.checked_div(&$name::one()), Some(c)); + assert_eq!(d.checked_div(&$name::one()), Some(d)); + + assert_eq!(a.checked_div(&$name::zero()), None); + assert_eq!(b.checked_div(&$name::zero()), None); + assert_eq!(c.checked_div(&$name::zero()), None); + assert_eq!(d.checked_div(&$name::zero()), None); + } + + #[test] + fn trunc_works() { + let n = $name::saturating_from_rational(5, 2).trunc(); + assert_eq!(n, $name::saturating_from_integer(2)); + + let n = $name::saturating_from_rational(-5, 2).trunc(); + assert_eq!(n, $name::saturating_from_integer(-2)); + } + + #[test] + fn frac_works() { + let n = $name::saturating_from_rational(5, 2); + let i = n.trunc(); + let f = n.frac(); + + assert_eq!(n, i + f); + + let n = $name::saturating_from_rational(-5, 2); + let i = n.trunc(); + let f = n.frac(); + + assert_eq!(n, i - f); + + let n = $name::saturating_from_rational(5, 2) + .frac() + .saturating_mul(10.into()); + assert_eq!(n, 5.into()); + + let n = $name::saturating_from_rational(1, 2) + .frac() + .saturating_mul(10.into()); + assert_eq!(n, 5.into()); + + // The sign is attached to the integer part unless it is zero. + let n = $name::saturating_from_rational(-5, 2) + .frac() + .saturating_mul(10.into()); + assert_eq!(n, 5.into()); + + let n = $name::saturating_from_rational(-1, 2) + .frac() + .saturating_mul(10.into()); + assert_eq!(n, (-5).into()); + } + + #[test] + fn ceil_works() { + let n = $name::saturating_from_rational(5, 2); + assert_eq!(n.ceil(), 3.into()); + + let n = $name::saturating_from_rational(-5, 2); + assert_eq!(n.ceil(), (-2).into()); + + // On the limits: + let n = $name::max_value(); + assert_eq!(n.ceil(), n.trunc()); + + let n = $name::min_value(); + assert_eq!(n.ceil(), n.trunc()); + } + + #[test] + fn floor_works() { + let n = $name::saturating_from_rational(5, 2); + assert_eq!(n.floor(), 2.into()); + + let n = $name::saturating_from_rational(-5, 2); + assert_eq!(n.floor(), (-3).into()); + + // On the limits: + let n = $name::max_value(); + assert_eq!(n.floor(), n.trunc()); + + let n = $name::min_value(); + assert_eq!(n.floor(), n.trunc()); + } + + #[test] + fn round_works() { + let n = $name::zero(); + assert_eq!(n.round(), n); + + let n = $name::one(); + assert_eq!(n.round(), n); + + let n = $name::saturating_from_rational(5, 2); + assert_eq!(n.round(), 3.into()); + + let n = $name::saturating_from_rational(-5, 2); + assert_eq!(n.round(), (-3).into()); + + // Saturating: + let n = $name::max_value(); + assert_eq!(n.round(), n.trunc()); + + let n = $name::min_value(); + assert_eq!(n.round(), n.trunc()); + + // On the limit: + + // floor(max - 1) + 0.33.. + let n = $name::max_value() + .saturating_sub(1.into()) + .trunc() + .saturating_add((1, 3).into()); + + assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc()); + + // floor(min + 1) - 0.33.. + let n = $name::min_value() + .saturating_add(1.into()) + .trunc() + .saturating_sub((1, 3).into()); + + assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc()); + + // floor(max - 1) + 0.5 + let n = $name::max_value() + .saturating_sub(1.into()) + .trunc() + .saturating_add((1, 2).into()); + + assert_eq!(n.round(), $name::max_value().trunc()); + + // floor(min + 1) - 0.5 + let n = $name::min_value() + .saturating_add(1.into()) + .trunc() + .saturating_sub((1, 2).into()); + + assert_eq!(n.round(), $name::min_value().trunc()); + } + + #[test] + fn perthing_into_works() { + let ten_percent_percent: $name = Percent::from_percent(10).into(); + assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10); + + let ten_percent_permill: $name = Permill::from_percent(10).into(); + assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10); + + let ten_percent_perbill: $name = Perbill::from_percent(10).into(); + assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10); + + let ten_percent_perquintill: $name = Perquintill::from_percent(10).into(); + assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10); + } + + #[test] + fn fmt_should_work() { + let zero = $name::zero(); + assert_eq!(format!("{:?}", zero), format!("{}(0.{:0>weight$})", stringify!($name), 0, weight=precision())); + + let one = $name::one(); + assert_eq!(format!("{:?}", one), format!("{}(1.{:0>weight$})", stringify!($name), 0, weight=precision())); + + let neg = -$name::one(); + assert_eq!(format!("{:?}", neg), format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight=precision())); + + let frac = $name::saturating_from_rational(1, 2); + assert_eq!(format!("{:?}", frac), format!("{}(0.{:0. - -use codec::{Decode, Encode}; -use primitive_types::U256; -use crate::{ - traits::{Bounded, Saturating, UniqueSaturatedInto, SaturatedConversion}, - PerThing, Perquintill, -}; -use sp_std::{ - convert::{Into, TryFrom, TryInto}, - fmt, ops, - num::NonZeroI128, -}; - -#[cfg(feature = "std")] -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; - -/// A signed fixed-point number. -/// Can hold any value in the range [-170_141_183_460_469_231_731, 170_141_183_460_469_231_731] -/// with fixed-point accuracy of 10 ** 18. -#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Fixed128(i128); - -const DIV: i128 = 1_000_000_000_000_000_000; - -impl Fixed128 { - /// Create self from a natural number. - /// - /// Note that this might be lossy. - pub fn from_natural(int: i128) -> Self { - Self(int.saturating_mul(DIV)) - } - - /// Accuracy of `Fixed128`. - pub const fn accuracy() -> i128 { - DIV - } - - /// Raw constructor. Equal to `parts / DIV`. - pub const fn from_parts(parts: i128) -> Self { - Self(parts) - } - - /// Creates self from a rational number. Equal to `n/d`. - /// - /// Note that this might be lossy. Only use this if you are sure that `n * DIV` can fit into an - /// i128. - pub fn from_rational>(n: N, d: NonZeroI128) -> Self { - let n = n.unique_saturated_into(); - Self(n.saturating_mul(DIV.into()) / d.get()) - } - - /// Consume self and return the inner raw `i128` value. - /// - /// Note this is a low level function, as the returned value is represented with accuracy. - pub fn deconstruct(self) -> i128 { - self.0 - } - - /// Takes the reciprocal(inverse) of Fixed128, 1/x - pub fn recip(&self) -> Option { - Self::from_natural(1i128).checked_div(self) - } - - /// Checked add. Same semantic to `num_traits::CheckedAdd`. - pub fn checked_add(&self, rhs: &Self) -> Option { - self.0.checked_add(rhs.0).map(Self) - } - - /// Checked sub. Same semantic to `num_traits::CheckedSub`. - pub fn checked_sub(&self, rhs: &Self) -> Option { - self.0.checked_sub(rhs.0).map(Self) - } - - /// Checked mul. Same semantic to `num_traits::CheckedMul`. - pub fn checked_mul(&self, rhs: &Self) -> Option { - let signum = self.0.signum() * rhs.0.signum(); - let mut lhs = self.0; - if lhs.is_negative() { - lhs = lhs.saturating_mul(-1); - } - let mut rhs: i128 = rhs.0.saturated_into(); - if rhs.is_negative() { - rhs = rhs.saturating_mul(-1); - } - - U256::from(lhs) - .checked_mul(U256::from(rhs)) - .and_then(|n| n.checked_div(U256::from(DIV))) - .and_then(|n| TryInto::::try_into(n).ok()) - .map(|n| Self(n * signum)) - } - - /// Checked div. Same semantic to `num_traits::CheckedDiv`. - pub fn checked_div(&self, rhs: &Self) -> Option { - if rhs.0.signum() == 0 { - return None; - } - if self.0 == 0 { - return Some(*self); - } - - let signum = self.0.signum() / rhs.0.signum(); - let mut lhs: i128 = self.0; - if lhs.is_negative() { - lhs = lhs.saturating_mul(-1); - } - let mut rhs: i128 = rhs.0.saturated_into(); - if rhs.is_negative() { - rhs = rhs.saturating_mul(-1); - } - - U256::from(lhs) - .checked_mul(U256::from(DIV)) - .and_then(|n| n.checked_div(U256::from(rhs))) - .and_then(|n| TryInto::::try_into(n).ok()) - .map(|n| Self(n * signum)) - } - - /// Checked mul for int type `N`. - pub fn checked_mul_int(&self, other: &N) -> Option - where - N: Copy + TryFrom + TryInto, - { - N::try_into(*other).ok().and_then(|rhs| { - let mut lhs = self.0; - if lhs.is_negative() { - lhs = lhs.saturating_mul(-1); - } - let mut rhs: i128 = rhs.saturated_into(); - let signum = self.0.signum() * rhs.signum(); - if rhs.is_negative() { - rhs = rhs.saturating_mul(-1); - } - - U256::from(lhs) - .checked_mul(U256::from(rhs)) - .and_then(|n| n.checked_div(U256::from(DIV))) - .and_then(|n| TryInto::::try_into(n).ok()) - .and_then(|n| TryInto::::try_into(n * signum).ok()) - }) - } - - /// Checked mul for int type `N`. - pub fn saturating_mul_int(&self, other: &N) -> N - where - N: Copy + TryFrom + TryInto + Bounded, - { - self.checked_mul_int(other).unwrap_or_else(|| { - N::try_into(*other) - .map(|n| n.signum()) - .map(|n| n * self.0.signum()) - .map(|signum| { - if signum.is_negative() { - Bounded::min_value() - } else { - Bounded::max_value() - } - }) - .unwrap_or(Bounded::max_value()) - }) - } - - /// Checked div for int type `N`. - pub fn checked_div_int(&self, other: &N) -> Option - where - N: Copy + TryFrom + TryInto, - { - N::try_into(*other) - .ok() - .and_then(|n| self.0.checked_div(n)) - .and_then(|n| n.checked_div(DIV)) - .and_then(|n| TryInto::::try_into(n).ok()) - } - - pub fn zero() -> Self { - Self(0) - } - - pub fn is_zero(&self) -> bool { - self.0 == 0 - } - - /// Saturating absolute value. Returning MAX if `parts` == i128::MIN instead of overflowing. - pub fn saturating_abs(&self) -> Self { - if self.0 == i128::min_value() { - return Fixed128::max_value(); - } - - if self.0.is_negative() { - Fixed128::from_parts(self.0 * -1) - } else { - *self - } - } - - pub fn is_positive(&self) -> bool { - self.0.is_positive() - } - - pub fn is_negative(&self) -> bool { - self.0.is_negative() - } - - /// Performs a saturated multiply and accumulate by unsigned number. - /// - /// Returns a saturated `int + (self * int)`. - pub fn saturated_multiply_accumulate(self, int: N) -> N - where - N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + - ops::Rem + ops::Div + ops::Mul + - ops::Add, - { - let div = DIV as u128; - let positive = self.0 > 0; - // safe to convert as absolute value. - let parts = self.0.checked_abs().map(|v| v as u128).unwrap_or(i128::max_value() as u128 + 1); - - - // will always fit. - let natural_parts = parts / div; - // might saturate. - let natural_parts: N = natural_parts.saturated_into(); - // fractional parts can always fit into u64. - let perquintill_parts = (parts % div) as u64; - - let n = int.clone().saturating_mul(natural_parts); - let p = Perquintill::from_parts(perquintill_parts) * int.clone(); - - // everything that needs to be either added or subtracted from the original weight. - let excess = n.saturating_add(p); - - if positive { - int.saturating_add(excess) - } else { - int.saturating_sub(excess) - } - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe addition. -impl ops::Add for Fixed128 { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self(self.0 + rhs.0) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe subtraction. -impl ops::Sub for Fixed128 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) - } -} - -impl Saturating for Fixed128 { - fn saturating_add(self, rhs: Self) -> Self { - Self(self.0.saturating_add(rhs.0)) - } - - fn saturating_sub(self, rhs: Self) -> Self { - Self(self.0.saturating_sub(rhs.0)) - } - - fn saturating_mul(self, rhs: Self) -> Self { - self.checked_mul(&rhs).unwrap_or_else(|| { - if (self.0.signum() * rhs.0.signum()).is_negative() { - Bounded::min_value() - } else { - Bounded::max_value() - } - }) - } - - fn saturating_pow(self, exp: usize) -> Self { - if exp == 0 { - return Self::from_natural(1); - } - - let exp = exp as u64; - let msb_pos = 64 - exp.leading_zeros(); - - let mut result = Self::from_natural(1); - let mut pow_val = self; - for i in 0..msb_pos { - if ((1 << i) & exp) > 0 { - result = result.saturating_mul(pow_val); - } - pow_val = pow_val.saturating_mul(pow_val); - } - result - } -} - -impl Bounded for Fixed128 { - fn min_value() -> Self { - Self(Bounded::min_value()) - } - - fn max_value() -> Self { - Self(Bounded::max_value()) - } -} - -impl fmt::Debug for Fixed128 { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let integral = { - let int = self.0 / DIV; - let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" }; - format!("{}{}", signum_for_zero, int) - }; - let fractional = format!("{:0>18}", (self.0 % DIV).abs()); - write!(f, "Fixed128({}.{})", integral, fractional) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { - Ok(()) - } -} - -impl From

for Fixed128 { - fn from(val: P) -> Self { - let accuracy = P::ACCURACY.saturated_into().max(1) as i128; - let value = val.deconstruct().saturated_into() as i128; - Fixed128::from_rational(value, NonZeroI128::new(accuracy).unwrap()) - } -} - -#[cfg(feature = "std")] -impl Fixed128 { - fn i128_str(&self) -> String { - format!("{}", &self.0) - } - - fn try_from_i128_str(s: &str) -> Result { - let parts: i128 = s.parse().map_err(|_| "invalid string input")?; - Ok(Self::from_parts(parts)) - } -} - -// Manual impl `Serialize` as serde_json does not support i128. -// TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed. -#[cfg(feature = "std")] -impl Serialize for Fixed128 { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&self.i128_str()) - } -} - -// Manual impl `Serialize` as serde_json does not support i128. -// TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed. -#[cfg(feature = "std")] -impl<'de> Deserialize<'de> for Fixed128 { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - Fixed128::try_from_i128_str(&s).map_err(|err_str| de::Error::custom(err_str)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{Perbill, Percent, Permill, Perquintill}; - - fn max() -> Fixed128 { - Fixed128::max_value() - } - - fn min() -> Fixed128 { - Fixed128::min_value() - } - - #[test] - fn fixed128_semantics() { - let a = Fixed128::from_rational(5, NonZeroI128::new(2).unwrap()); - let b = Fixed128::from_rational(10, NonZeroI128::new(4).unwrap()); - assert_eq!(a.0, 5 * DIV / 2); - assert_eq!(a, b); - - let a = Fixed128::from_rational(-5, NonZeroI128::new(1).unwrap()); - assert_eq!(a, Fixed128::from_natural(-5)); - - let a = Fixed128::from_rational(5, NonZeroI128::new(-1).unwrap()); - assert_eq!(a, Fixed128::from_natural(-5)); - - // biggest value that can be created. - assert_ne!(max(), Fixed128::from_natural(170_141_183_460_469_231_731)); - assert_eq!(max(), Fixed128::from_natural(170_141_183_460_469_231_732)); - - // the smallest value that can be created. - assert_ne!(min(), Fixed128::from_natural(-170_141_183_460_469_231_731)); - assert_eq!(min(), Fixed128::from_natural(-170_141_183_460_469_231_732)); - } - - #[test] - fn fixed128_operation() { - let a = Fixed128::from_natural(2); - let b = Fixed128::from_natural(1); - assert_eq!(a.checked_add(&b), Some(Fixed128::from_natural(1 + 2))); - assert_eq!(a.checked_sub(&b), Some(Fixed128::from_natural(2 - 1))); - assert_eq!(a.checked_mul(&b), Some(Fixed128::from_natural(1 * 2))); - assert_eq!( - a.checked_div(&b), - Some(Fixed128::from_rational(2, NonZeroI128::new(1).unwrap())) - ); - - let a = Fixed128::from_rational(5, NonZeroI128::new(2).unwrap()); - let b = Fixed128::from_rational(3, NonZeroI128::new(2).unwrap()); - assert_eq!( - a.checked_add(&b), - Some(Fixed128::from_rational(8, NonZeroI128::new(2).unwrap())) - ); - assert_eq!( - a.checked_sub(&b), - Some(Fixed128::from_rational(2, NonZeroI128::new(2).unwrap())) - ); - assert_eq!( - a.checked_mul(&b), - Some(Fixed128::from_rational(15, NonZeroI128::new(4).unwrap())) - ); - assert_eq!( - a.checked_div(&b), - Some(Fixed128::from_rational(10, NonZeroI128::new(6).unwrap())) - ); - - let a = Fixed128::from_natural(120); - assert_eq!(a.checked_div_int(&2i32), Some(60)); - - let a = Fixed128::from_rational(20, NonZeroI128::new(1).unwrap()); - assert_eq!(a.checked_div_int(&2i32), Some(10)); - - let a = Fixed128::from_natural(120); - assert_eq!(a.checked_mul_int(&2i32), Some(240)); - - let a = Fixed128::from_rational(1, NonZeroI128::new(2).unwrap()); - assert_eq!(a.checked_mul_int(&20i32), Some(10)); - - let a = Fixed128::from_rational(-1, NonZeroI128::new(2).unwrap()); - assert_eq!(a.checked_mul_int(&20i32), Some(-10)); - } - - #[test] - fn saturating_mul_should_work() { - let a = Fixed128::from_natural(-1); - assert_eq!(min().saturating_mul(a), max()); - - assert_eq!(Fixed128::from_natural(125).saturating_mul(a).deconstruct(), -125 * DIV); - - let a = Fixed128::from_rational(1, NonZeroI128::new(5).unwrap()); - assert_eq!(Fixed128::from_natural(125).saturating_mul(a).deconstruct(), 25 * DIV); - } - - #[test] - fn saturating_mul_int_works() { - let a = Fixed128::from_rational(10, NonZeroI128::new(1).unwrap()); - assert_eq!(a.saturating_mul_int(&i32::max_value()), i32::max_value()); - - let a = Fixed128::from_rational(-10, NonZeroI128::new(1).unwrap()); - assert_eq!(a.saturating_mul_int(&i32::max_value()), i32::min_value()); - - let a = Fixed128::from_rational(3, NonZeroI128::new(1).unwrap()); - assert_eq!(a.saturating_mul_int(&100i8), i8::max_value()); - - let a = Fixed128::from_rational(10, NonZeroI128::new(1).unwrap()); - assert_eq!(a.saturating_mul_int(&123i128), 1230); - - let a = Fixed128::from_rational(-10, NonZeroI128::new(1).unwrap()); - assert_eq!(a.saturating_mul_int(&123i128), -1230); - - assert_eq!(max().saturating_mul_int(&2i128), 340_282_366_920_938_463_463); - - assert_eq!(max().saturating_mul_int(&i128::min_value()), i128::min_value()); - - assert_eq!(min().saturating_mul_int(&i128::max_value()), i128::min_value()); - - assert_eq!(min().saturating_mul_int(&i128::min_value()), i128::max_value()); - } - - #[test] - fn zero_works() { - assert_eq!(Fixed128::zero(), Fixed128::from_natural(0)); - } - - #[test] - fn is_zero_works() { - assert!(Fixed128::zero().is_zero()); - assert!(!Fixed128::from_natural(1).is_zero()); - } - - #[test] - fn checked_div_with_zero_should_be_none() { - let a = Fixed128::from_natural(1); - let b = Fixed128::from_natural(0); - assert_eq!(a.checked_div(&b), None); - assert_eq!(b.checked_div(&a), Some(b)); - } - - #[test] - fn checked_div_int_with_zero_should_be_none() { - let a = Fixed128::from_natural(1); - assert_eq!(a.checked_div_int(&0i32), None); - let a = Fixed128::from_natural(0); - assert_eq!(a.checked_div_int(&1i32), Some(0)); - } - - #[test] - fn checked_div_with_zero_dividend_should_be_zero() { - let a = Fixed128::zero(); - let b = Fixed128::from_parts(1); - - assert_eq!(a.checked_div(&b), Some(Fixed128::zero())); - } - - #[test] - fn under_flow_should_be_none() { - let b = Fixed128::from_natural(1); - assert_eq!(min().checked_sub(&b), None); - } - - #[test] - fn over_flow_should_be_none() { - let a = Fixed128::from_parts(i128::max_value() - 1); - let b = Fixed128::from_parts(2); - assert_eq!(a.checked_add(&b), None); - - let a = Fixed128::max_value(); - let b = Fixed128::from_rational(2, NonZeroI128::new(1).unwrap()); - assert_eq!(a.checked_mul(&b), None); - - let a = Fixed128::from_natural(255); - let b = 2u8; - assert_eq!(a.checked_mul_int(&b), None); - - let a = Fixed128::from_natural(256); - let b = 1u8; - assert_eq!(a.checked_div_int(&b), None); - - let a = Fixed128::from_natural(256); - let b = -1i8; - assert_eq!(a.checked_div_int(&b), None); - } - - #[test] - fn checked_div_int_should_work() { - // 256 / 10 = 25 (25.6 as int = 25) - let a = Fixed128::from_natural(256); - let result = a.checked_div_int(&10i128).unwrap(); - assert_eq!(result, 25); - - // 256 / 100 = 2 (2.56 as int = 2) - let a = Fixed128::from_natural(256); - let result = a.checked_div_int(&100i128).unwrap(); - assert_eq!(result, 2); - - // 256 / 1000 = 0 (0.256 as int = 0) - let a = Fixed128::from_natural(256); - let result = a.checked_div_int(&1000i128).unwrap(); - assert_eq!(result, 0); - - // 256 / -1 = -256 - let a = Fixed128::from_natural(256); - let result = a.checked_div_int(&-1i128).unwrap(); - assert_eq!(result, -256); - - // -256 / -1 = 256 - let a = Fixed128::from_natural(-256); - let result = a.checked_div_int(&-1i128).unwrap(); - assert_eq!(result, 256); - - // 10 / -5 = -2 - let a = Fixed128::from_rational(20, NonZeroI128::new(2).unwrap()); - let result = a.checked_div_int(&-5i128).unwrap(); - assert_eq!(result, -2); - - // -170_141_183_460_469_231_731 / -2 = 85_070_591_730_234_615_865 - let result = min().checked_div_int(&-2i128).unwrap(); - assert_eq!(result, 85_070_591_730_234_615_865); - - // 85_070_591_730_234_615_865 * -2 = -170_141_183_460_469_231_730 - let result = Fixed128::from_natural(result).checked_mul_int(&-2i128).unwrap(); - assert_eq!(result, -170_141_183_460_469_231_730); - } - - #[test] - fn perthing_into_fixed_i128() { - let ten_percent_percent: Fixed128 = Percent::from_percent(10).into(); - assert_eq!(ten_percent_percent.deconstruct(), DIV / 10); - - let ten_percent_permill: Fixed128 = Permill::from_percent(10).into(); - assert_eq!(ten_percent_permill.deconstruct(), DIV / 10); - - let ten_percent_perbill: Fixed128 = Perbill::from_percent(10).into(); - assert_eq!(ten_percent_perbill.deconstruct(), DIV / 10); - - let ten_percent_perquintill: Fixed128 = Perquintill::from_percent(10).into(); - assert_eq!(ten_percent_perquintill.deconstruct(), DIV / 10); - } - - #[test] - fn recip_should_work() { - let a = Fixed128::from_natural(2); - assert_eq!( - a.recip(), - Some(Fixed128::from_rational(1, NonZeroI128::new(2).unwrap())) - ); - - let a = Fixed128::from_natural(2); - assert_eq!(a.recip().unwrap().checked_mul_int(&4i32), Some(2i32)); - - let a = Fixed128::from_rational(100, NonZeroI128::new(121).unwrap()); - assert_eq!( - a.recip(), - Some(Fixed128::from_rational(121, NonZeroI128::new(100).unwrap())) - ); - - let a = Fixed128::from_rational(1, NonZeroI128::new(2).unwrap()); - assert_eq!(a.recip().unwrap().checked_mul(&a), Some(Fixed128::from_natural(1))); - - let a = Fixed128::from_natural(0); - assert_eq!(a.recip(), None); - - let a = Fixed128::from_rational(-1, NonZeroI128::new(2).unwrap()); - assert_eq!(a.recip(), Some(Fixed128::from_natural(-2))); - } - - #[test] - fn serialize_deserialize_should_work() { - let two_point_five = Fixed128::from_rational(5, NonZeroI128::new(2).unwrap()); - let serialized = serde_json::to_string(&two_point_five).unwrap(); - assert_eq!(serialized, "\"2500000000000000000\""); - let deserialized: Fixed128 = serde_json::from_str(&serialized).unwrap(); - assert_eq!(deserialized, two_point_five); - - let minus_two_point_five = Fixed128::from_rational(-5, NonZeroI128::new(2).unwrap()); - let serialized = serde_json::to_string(&minus_two_point_five).unwrap(); - assert_eq!(serialized, "\"-2500000000000000000\""); - let deserialized: Fixed128 = serde_json::from_str(&serialized).unwrap(); - assert_eq!(deserialized, minus_two_point_five); - } - - #[test] - fn saturating_abs_should_work() { - // normal - assert_eq!(Fixed128::from_parts(1).saturating_abs(), Fixed128::from_parts(1)); - assert_eq!(Fixed128::from_parts(-1).saturating_abs(), Fixed128::from_parts(1)); - - // saturating - assert_eq!(Fixed128::min_value().saturating_abs(), Fixed128::max_value()); - } - - #[test] - fn is_positive_negative_should_work() { - let positive = Fixed128::from_parts(1); - assert!(positive.is_positive()); - assert!(!positive.is_negative()); - - let negative = Fixed128::from_parts(-1); - assert!(!negative.is_positive()); - assert!(negative.is_negative()); - - let zero = Fixed128::zero(); - assert!(!zero.is_positive()); - assert!(!zero.is_negative()); - } - - #[test] - fn fmt_should_work() { - let positive = Fixed128::from_parts(1000000000000000001); - assert_eq!(format!("{:?}", positive), "Fixed128(1.000000000000000001)"); - let negative = Fixed128::from_parts(-1000000000000000001); - assert_eq!(format!("{:?}", negative), "Fixed128(-1.000000000000000001)"); - - let positive_fractional = Fixed128::from_parts(1); - assert_eq!(format!("{:?}", positive_fractional), "Fixed128(0.000000000000000001)"); - let negative_fractional = Fixed128::from_parts(-1); - assert_eq!(format!("{:?}", negative_fractional), "Fixed128(-0.000000000000000001)"); - - let zero = Fixed128::zero(); - assert_eq!(format!("{:?}", zero), "Fixed128(0.000000000000000000)"); - } - - #[test] - fn saturating_pow_should_work() { - assert_eq!(Fixed128::from_natural(2).saturating_pow(0), Fixed128::from_natural(1)); - assert_eq!(Fixed128::from_natural(2).saturating_pow(1), Fixed128::from_natural(2)); - assert_eq!(Fixed128::from_natural(2).saturating_pow(2), Fixed128::from_natural(4)); - assert_eq!(Fixed128::from_natural(2).saturating_pow(3), Fixed128::from_natural(8)); - assert_eq!(Fixed128::from_natural(2).saturating_pow(50), Fixed128::from_natural(1125899906842624)); - - assert_eq!(Fixed128::from_natural(1).saturating_pow(1000), Fixed128::from_natural(1)); - assert_eq!(Fixed128::from_natural(-1).saturating_pow(1000), Fixed128::from_natural(1)); - assert_eq!(Fixed128::from_natural(-1).saturating_pow(1001), Fixed128::from_natural(-1)); - assert_eq!(Fixed128::from_natural(1).saturating_pow(usize::max_value()), Fixed128::from_natural(1)); - assert_eq!(Fixed128::from_natural(-1).saturating_pow(usize::max_value()), Fixed128::from_natural(-1)); - assert_eq!(Fixed128::from_natural(-1).saturating_pow(usize::max_value() - 1), Fixed128::from_natural(1)); - - assert_eq!(Fixed128::from_natural(114209).saturating_pow(4), Fixed128::from_natural(170137997018538053761)); - assert_eq!(Fixed128::from_natural(114209).saturating_pow(5), Fixed128::max_value()); - - assert_eq!(Fixed128::from_natural(1).saturating_pow(usize::max_value()), Fixed128::from_natural(1)); - assert_eq!(Fixed128::from_natural(0).saturating_pow(usize::max_value()), Fixed128::from_natural(0)); - assert_eq!(Fixed128::from_natural(2).saturating_pow(usize::max_value()), Fixed128::max_value()); - } -} diff --git a/primitives/arithmetic/src/fixed64.rs b/primitives/arithmetic/src/fixed64.rs deleted file mode 100644 index 819982aa502c5caa1f169d48af19fd5908734bf8..0000000000000000000000000000000000000000 --- a/primitives/arithmetic/src/fixed64.rs +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright 2019-2020 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 sp_std::{ - ops, prelude::*, - convert::{TryFrom, TryInto}, -}; -use codec::{Encode, Decode}; -use crate::{ - Perbill, - traits::{ - SaturatedConversion, CheckedSub, CheckedAdd, CheckedDiv, Bounded, UniqueSaturatedInto, Saturating - } -}; - -/// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036] -/// with fixed point accuracy of one billion. -#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Fixed64(i64); - -/// The accuracy of the `Fixed64` type. -const DIV: i64 = 1_000_000_000; - -impl Fixed64 { - /// creates self from a natural number. - /// - /// Note that this might be lossy. - pub fn from_natural(int: i64) -> Self { - Self(int.saturating_mul(DIV)) - } - - /// Return the accuracy of the type. Given that this function returns the value `X`, it means - /// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`. - pub fn accuracy() -> i64 { - DIV - } - - /// Consume self and return the inner value. - pub fn into_inner(self) -> i64 { self.0 } - - /// Raw constructor. Equal to `parts / 1_000_000_000`. - pub fn from_parts(parts: i64) -> Self { - Self(parts) - } - - /// creates self from a rational number. Equal to `n/d`. - /// - /// Note that this might be lossy. - pub fn from_rational(n: i64, d: u64) -> Self { - Self( - (i128::from(n).saturating_mul(i128::from(DIV)) / i128::from(d).max(1)) - .try_into() - .unwrap_or_else(|_| Bounded::max_value()) - ) - } - - /// Performs a saturated multiply and accumulate by unsigned number. - /// - /// Returns a saturated `int + (self * int)`. - pub fn saturated_multiply_accumulate(self, int: N) -> N - where - N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + - ops::Rem + ops::Div + ops::Mul + - ops::Add, - { - let div = DIV as u64; - let positive = self.0 > 0; - // safe to convert as absolute value. - let parts = self.0.checked_abs().map(|v| v as u64).unwrap_or(i64::max_value() as u64 + 1); - - - // will always fit. - let natural_parts = parts / div; - // might saturate. - let natural_parts: N = natural_parts.saturated_into(); - // fractional parts can always fit into u32. - let perbill_parts = (parts % div) as u32; - - let n = int.clone().saturating_mul(natural_parts); - let p = Perbill::from_parts(perbill_parts) * int.clone(); - - // everything that needs to be either added or subtracted from the original weight. - let excess = n.saturating_add(p); - - if positive { - int.saturating_add(excess) - } else { - int.saturating_sub(excess) - } - } - - pub fn is_negative(&self) -> bool { - self.0.is_negative() - } -} - -impl Saturating for Fixed64 { - fn saturating_add(self, rhs: Self) -> Self { - Self(self.0.saturating_add(rhs.0)) - } - - fn saturating_mul(self, rhs: Self) -> Self { - let a = self.0 as i128; - let b = rhs.0 as i128; - let res = a * b / DIV as i128; - Self(res.saturated_into()) - } - - fn saturating_sub(self, rhs: Self) -> Self { - Self(self.0.saturating_sub(rhs.0)) - } - - fn saturating_pow(self, exp: usize) -> Self { - if exp == 0 { - return Self::from_natural(1); - } - - let exp = exp as u64; - let msb_pos = 64 - exp.leading_zeros(); - - let mut result = Self::from_natural(1); - let mut pow_val = self; - for i in 0..msb_pos { - if ((1 << i) & exp) > 0 { - result = result.saturating_mul(pow_val); - } - pow_val = pow_val.saturating_mul(pow_val); - } - result - } -} - -/// Use `Saturating` trait for safe addition. -impl ops::Add for Fixed64 { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self(self.0 + rhs.0) - } -} - -/// Use `Saturating` trait for safe subtraction. -impl ops::Sub for Fixed64 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) - } -} - -/// Use `CheckedDiv` trait for safe division. -impl ops::Div for Fixed64 { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - if rhs.0 == 0 { - panic!("attempt to divide by zero"); - } - let (n, d) = if rhs.0 < 0 { - (-self.0, rhs.0.abs() as u64) - } else { - (self.0, rhs.0 as u64) - }; - Fixed64::from_rational(n, d) - } -} - -impl CheckedSub for Fixed64 { - fn checked_sub(&self, rhs: &Self) -> Option { - self.0.checked_sub(rhs.0).map(Self) - } -} - -impl CheckedAdd for Fixed64 { - fn checked_add(&self, rhs: &Self) -> Option { - self.0.checked_add(rhs.0).map(Self) - } -} - -impl CheckedDiv for Fixed64 { - fn checked_div(&self, rhs: &Self) -> Option { - if rhs.0 == 0 { - None - } else { - Some(*self / *rhs) - } - } -} - -impl sp_std::fmt::Debug for Fixed64 { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - let integral = { - let int = self.0 / DIV; - let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" }; - format!("{}{}", signum_for_zero, int) - }; - let fractional = format!("{:0>9}", (self.0 % DIV).abs()); - write!(f, "Fixed64({}.{})", integral, fractional) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn max() -> Fixed64 { - Fixed64::from_parts(i64::max_value()) - } - - #[test] - fn fixed64_semantics() { - assert_eq!(Fixed64::from_rational(5, 2).0, 5 * 1_000_000_000 / 2); - assert_eq!(Fixed64::from_rational(5, 2), Fixed64::from_rational(10, 4)); - assert_eq!(Fixed64::from_rational(5, 0), Fixed64::from_rational(5, 1)); - - // biggest value that can be created. - assert_ne!(max(), Fixed64::from_natural(9_223_372_036)); - assert_eq!(max(), Fixed64::from_natural(9_223_372_037)); - } - - #[test] - fn fixed_64_growth_decrease_curve() { - let test_set = vec![0u32, 1, 10, 1000, 1_000_000_000]; - - // negative (1/2) - let mut fm = Fixed64::from_rational(-1, 2); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i) as i32, i as i32 - i as i32 / 2); - }); - - // unit (1) multiplier - fm = Fixed64::from_parts(0); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i); - }); - - // i.5 multiplier - fm = Fixed64::from_rational(1, 2); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i * 3 / 2); - }); - - // dual multiplier - fm = Fixed64::from_rational(1, 1); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i * 2); - }); - } - - macro_rules! saturating_mul_acc_test { - ($num_type:tt) => { - assert_eq!( - Fixed64::from_rational(100, 1).saturated_multiply_accumulate(10 as $num_type), - 1010, - ); - assert_eq!( - Fixed64::from_rational(100, 2).saturated_multiply_accumulate(10 as $num_type), - 510, - ); - assert_eq!( - Fixed64::from_rational(100, 3).saturated_multiply_accumulate(0 as $num_type), - 0, - ); - assert_eq!( - Fixed64::from_rational(5, 1).saturated_multiply_accumulate($num_type::max_value()), - $num_type::max_value() - ); - assert_eq!( - max().saturated_multiply_accumulate($num_type::max_value()), - $num_type::max_value() - ); - } - } - - #[test] - fn fixed64_multiply_accumulate_works() { - saturating_mul_acc_test!(u32); - saturating_mul_acc_test!(u64); - saturating_mul_acc_test!(u128); - } - - #[test] - fn div_works() { - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_rational(10, 1); - assert_eq!(a / b, Fixed64::from_rational(12, 100)); - - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_rational(1, 100); - assert_eq!(a / b, Fixed64::from_rational(120, 1)); - - let a = Fixed64::from_rational(12, 100); - let b = Fixed64::from_rational(10, 1); - assert_eq!(a / b, Fixed64::from_rational(12, 1000)); - - let a = Fixed64::from_rational(12, 100); - let b = Fixed64::from_rational(1, 100); - assert_eq!(a / b, Fixed64::from_rational(12, 1)); - - let a = Fixed64::from_rational(-12, 10); - let b = Fixed64::from_rational(10, 1); - assert_eq!(a / b, Fixed64::from_rational(-12, 100)); - - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_rational(-10, 1); - assert_eq!(a / b, Fixed64::from_rational(-12, 100)); - - let a = Fixed64::from_rational(-12, 10); - let b = Fixed64::from_rational(-10, 1); - assert_eq!(a / b, Fixed64::from_rational(12, 100)); - } - - #[test] - #[should_panic(expected = "attempt to divide by zero")] - fn div_zero() { - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_natural(0); - let _ = a / b; - } - - #[test] - fn checked_div_zero() { - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_natural(0); - assert_eq!(a.checked_div(&b), None); - } - - #[test] - fn checked_div_non_zero() { - let a = Fixed64::from_rational(12, 10); - let b = Fixed64::from_rational(1, 100); - assert_eq!(a.checked_div(&b), Some(Fixed64::from_rational(120, 1))); - } - - #[test] - fn saturating_mul_should_work() { - assert_eq!(Fixed64::from_natural(100).saturating_mul(Fixed64::from_natural(100)), Fixed64::from_natural(10000)); - } - - #[test] - fn saturating_pow_should_work() { - assert_eq!(Fixed64::from_natural(2).saturating_pow(0), Fixed64::from_natural(1)); - assert_eq!(Fixed64::from_natural(2).saturating_pow(1), Fixed64::from_natural(2)); - assert_eq!(Fixed64::from_natural(2).saturating_pow(2), Fixed64::from_natural(4)); - assert_eq!(Fixed64::from_natural(2).saturating_pow(3), Fixed64::from_natural(8)); - assert_eq!(Fixed64::from_natural(2).saturating_pow(20), Fixed64::from_natural(1048576)); - - assert_eq!(Fixed64::from_natural(1).saturating_pow(1000), Fixed64::from_natural(1)); - assert_eq!(Fixed64::from_natural(-1).saturating_pow(1000), Fixed64::from_natural(1)); - assert_eq!(Fixed64::from_natural(-1).saturating_pow(1001), Fixed64::from_natural(-1)); - assert_eq!(Fixed64::from_natural(1).saturating_pow(usize::max_value()), Fixed64::from_natural(1)); - assert_eq!(Fixed64::from_natural(-1).saturating_pow(usize::max_value()), Fixed64::from_natural(-1)); - assert_eq!(Fixed64::from_natural(-1).saturating_pow(usize::max_value() - 1), Fixed64::from_natural(1)); - - assert_eq!(Fixed64::from_natural(309).saturating_pow(4), Fixed64::from_natural(9_116_621_361)); - assert_eq!(Fixed64::from_natural(309).saturating_pow(5), Fixed64::from_parts(i64::max_value())); - - assert_eq!(Fixed64::from_natural(1).saturating_pow(usize::max_value()), Fixed64::from_natural(1)); - assert_eq!(Fixed64::from_natural(0).saturating_pow(usize::max_value()), Fixed64::from_natural(0)); - assert_eq!(Fixed64::from_natural(2).saturating_pow(usize::max_value()), Fixed64::from_parts(i64::max_value())); - } -} diff --git a/primitives/arithmetic/src/helpers_128bit.rs b/primitives/arithmetic/src/helpers_128bit.rs index bf8315b9b6648138454a5210eac300959fb77eec..1e332f54d3bd8a85038c8c5e728f2a1cb30c3f28 100644 --- a/primitives/arithmetic/src/helpers_128bit.rs +++ b/primitives/arithmetic/src/helpers_128bit.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Some helper functions to work with 128bit numbers. Note that the functionality provided here is //! only sensible to use with 128bit numbers because for smaller sizes, you can always rely on diff --git a/primitives/arithmetic/src/lib.rs b/primitives/arithmetic/src/lib.rs index fb70b13a15312b4cee434c6dc9a58ef234bad444..c4f95af6463ac319bc1758fcb5e51b7a94a66fcf 100644 --- a/primitives/arithmetic/src/lib.rs +++ b/primitives/arithmetic/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Minimal fixed point arithmetic primitives and types for runtime. @@ -36,12 +37,10 @@ pub mod biguint; pub mod helpers_128bit; pub mod traits; mod per_things; -mod fixed64; -mod fixed128; +mod fixed; mod rational128; -pub use fixed64::Fixed64; -pub use fixed128::Fixed128; +pub use fixed::{FixedPointNumber, Fixed64, Fixed128, FixedPointOperand}; pub use per_things::{PerThing, Percent, PerU16, Permill, Perbill, Perquintill}; pub use rational128::Rational128; diff --git a/primitives/arithmetic/src/per_things.rs b/primitives/arithmetic/src/per_things.rs index 56fc562cd1a926cd3d33b8ccee48dabe6c13bb24..cf5aa6e4cb7aad51b0207691550eef7930b4fe83 100644 --- a/primitives/arithmetic/src/per_things.rs +++ b/primitives/arithmetic/src/per_things.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; @@ -382,7 +383,6 @@ macro_rules! implement_per_thing { impl $name { /// From an explicitly defined number of parts per maximum of the type. /// - /// This can be called at compile time. // needed only for peru16. Since peru16 is the only type in which $max == // $type::max_value(), rustc is being a smart-a** here by warning that the comparison // is not needed. @@ -398,9 +398,9 @@ macro_rules! implement_per_thing { Self(([x, 100][(x > 100) as usize] as $upper_type * $max as $upper_type / 100) as $type) } - /// See [`PerThing::one`]. - pub fn one() -> Self { - ::one() + /// See [`PerThing::one`] + pub const fn one() -> Self { + Self::from_parts($max) } /// See [`PerThing::is_one`]. @@ -409,8 +409,8 @@ macro_rules! implement_per_thing { } /// See [`PerThing::zero`]. - pub fn zero() -> Self { - ::zero() + pub const fn zero() -> Self { + Self::from_parts(0) } /// See [`PerThing::is_zero`]. @@ -419,8 +419,8 @@ macro_rules! implement_per_thing { } /// See [`PerThing::deconstruct`]. - pub fn deconstruct(self) -> $type { - PerThing::deconstruct(self) + pub const fn deconstruct(self) -> $type { + self.0 } /// See [`PerThing::square`]. @@ -1129,6 +1129,18 @@ macro_rules! implement_per_thing { 1, ); } + + #[test] + #[allow(unused)] + fn const_fns_work() { + const C1: $name = $name::from_percent(50); + const C2: $name = $name::one(); + const C3: $name = $name::zero(); + const C4: $name = $name::from_parts(1); + + // deconstruct is also const, hence it can be called in const rhs. + const C5: bool = C1.deconstruct() == 0; + } } }; } diff --git a/primitives/arithmetic/src/rational128.rs b/primitives/arithmetic/src/rational128.rs index 248df70794c635efc726255e5130ed8dc70ac037..709af1d3b97c3898c815e903c9e57ff2f7705c2c 100644 --- a/primitives/arithmetic/src/rational128.rs +++ b/primitives/arithmetic/src/rational128.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_std::{cmp::Ordering, prelude::*}; use crate::helpers_128bit; @@ -359,6 +360,15 @@ mod tests { multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), 250000000, ); + + assert_eq!( + multiply_by_rational( + 29459999999999999988000u128, + 1000000000000000000u128, + 10000000000000000000u128 + ).unwrap(), + 2945999999999999998800u128 + ); } #[test] diff --git a/primitives/arithmetic/src/traits.rs b/primitives/arithmetic/src/traits.rs index 4201a41364bea35752286b6d9c1de277ee6a6121..7985f09a20f07beccf72bcbdff74b63237430bab 100644 --- a/primitives/arithmetic/src/traits.rs +++ b/primitives/arithmetic/src/traits.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitive traits for the runtime arithmetic. @@ -20,8 +21,8 @@ use sp_std::{self, convert::{TryFrom, TryInto}}; use codec::HasCompact; pub use integer_sqrt::IntegerSquareRoot; pub use num_traits::{ - Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, - CheckedShl, CheckedShr, checked_pow + Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedNeg, + CheckedShl, CheckedShr, checked_pow, Signed }; use sp_std::ops::{ Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml index 32f67d5e6e0261a2310b70c0fea8d4f9d21a1dec..24fcb91396c77d3c5aaf31f0aaa8d461cafbd17b 100644 --- a/primitives/authority-discovery/Cargo.toml +++ b/primitives/authority-discovery/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-authority-discovery" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] description = "Authority discovery primitives" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,11 +12,11 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", default-features = false, version = "1.3.0" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } -sp-api = { version = "2.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../api" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../runtime" } [features] default = ["std"] diff --git a/primitives/authority-discovery/src/lib.rs b/primitives/authority-discovery/src/lib.rs index 68680ad75946545f93d8d0c5ef5c3004a3623efc..8903a7f3837553806912770243bf6b18e3a3aadf 100644 --- a/primitives/authority-discovery/src/lib.rs +++ b/primitives/authority-discovery/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime Api to help discover authorities. @@ -22,24 +23,11 @@ use sp_std::vec::Vec; mod app { use sp_application_crypto::{ - CryptoTypePublicPair, key_types::AUTHORITY_DISCOVERY, - Public as _, app_crypto, - sr25519}; + sr25519, + }; app_crypto!(sr25519, AUTHORITY_DISCOVERY); - - impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } - } - - impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(sr25519::CRYPTO_ID, key.to_raw_vec()) - } - } } sp_application_crypto::with_pair! { diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml index 7bc01953ef8dd1c59d5ed9c0e8222d97259b177e..5ae5561a599e674985652bed5dd421b23df4d920 100644 --- a/primitives/authorship/Cargo.toml +++ b/primitives/authorship/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-authorship" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] description = "Authorship primitives" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,9 +12,9 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../inherents" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../inherents" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } [features] diff --git a/primitives/authorship/src/lib.rs b/primitives/authorship/src/lib.rs index 53dac56dc473c20d3f18e717a396ac13b80eb7b3..a760c546a25d7f2947b374b25965fc5192e53a2e 100644 --- a/primitives/authorship/src/lib.rs +++ b/primitives/authorship/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Authorship Primitives diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml index 70bb5e12d37a202330d6d98af82f092f4e578671..767dfeb87e9a71527f4a5758b6e96cac754d71e1 100644 --- a/primitives/block-builder/Cargo.toml +++ b/primitives/block-builder/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-block-builder" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "The block builder runtime api." @@ -12,11 +12,11 @@ description = "The block builder runtime api." targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../runtime" } -sp-api = { version = "2.0.0-dev", default-features = false, path = "../api" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../runtime" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../api" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../inherents" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../inherents" } [features] default = [ "std" ] diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 732c937c1a0858514c3841d3dad5419b5749b519..6367a18afa6151aea69c80c7c65b455d33c1933e 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The block builder runtime api. diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml index d5cf80b775196a0892af2a33325fd1653d799388..d76d9c72091c05a2e4d0a1fb366adc7921ad3ab3 100644 --- a/primitives/blockchain/Cargo.toml +++ b/primitives/blockchain/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-blockchain" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate blockchain traits and primitives." @@ -19,7 +19,7 @@ lru = "0.4.0" parking_lot = "0.10.0" derive_more = "0.99.2" codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-consensus = { version = "0.8.0-dev", path = "../consensus/common" } -sp-runtime = { version = "2.0.0-dev", path = "../runtime" } -sp-block-builder = { version = "2.0.0-dev", path = "../block-builder" } -sp-state-machine = { version = "0.8.0-dev", path = "../state-machine" } +sp-consensus = { version = "0.8.0-rc2", path = "../consensus/common" } +sp-runtime = { version = "2.0.0-rc2", path = "../runtime" } +sp-block-builder = { version = "2.0.0-rc2", path = "../block-builder" } +sp-state-machine = { version = "0.8.0-rc2", path = "../state-machine" } diff --git a/primitives/blockchain/src/backend.rs b/primitives/blockchain/src/backend.rs index 45d627a1c27224a6c0349b9b5f2c11353b5d3a0b..1328dfb5752fc0544e33c6b9934965dd3158dded 100644 --- a/primitives/blockchain/src/backend.rs +++ b/primitives/blockchain/src/backend.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate blockchain trait diff --git a/primitives/blockchain/src/error.rs b/primitives/blockchain/src/error.rs index e479b8abe918ee881dbb4fa79cdf824cfe6fb14e..17c276d8709cbee4cacda8fb3066205cb6626344 100644 --- a/primitives/blockchain/src/error.rs +++ b/primitives/blockchain/src/error.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate client possible errors. diff --git a/primitives/blockchain/src/header_metadata.rs b/primitives/blockchain/src/header_metadata.rs index b7df03187db37b0a56114ad09e650c2d8098871a..a4df04b507fd1853a2e43cb8504ab30bf0f3a308 100644 --- a/primitives/blockchain/src/header_metadata.rs +++ b/primitives/blockchain/src/header_metadata.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Implements tree backend, cached header metadata and algorithms //! to compute routes efficiently over the tree of headers. diff --git a/primitives/blockchain/src/lib.rs b/primitives/blockchain/src/lib.rs index 8f83c7aec5d9d13cc18e929a48bd224c43a2ce46..27b9c3585e9caa673460f000ae3c8adb88fb94c0 100644 --- a/primitives/blockchain/src/lib.rs +++ b/primitives/blockchain/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate blockchain traits and primitives. diff --git a/primitives/chain-spec/Cargo.toml b/primitives/chain-spec/Cargo.toml index 585decc68d02b86cfe9a7631b796bc82a16cf9f2..9b2658abe5f18f038cae18818a2ae5ab6d9b3888 100644 --- a/primitives/chain-spec/Cargo.toml +++ b/primitives/chain-spec/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-chain-spec" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate chain configurations types." diff --git a/primitives/chain-spec/src/lib.rs b/primitives/chain-spec/src/lib.rs index 13ebc09b6c0f0646b92d21056bbc1ef217f0ca3d..869fae8236b7674ba0eb8d02b86cb382686dd840 100644 --- a/primitives/chain-spec/src/lib.rs +++ b/primitives/chain-spec/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Types and traits related to chain specifications. diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml index 574b80bd3d3902b959c55429d44e2fc2f21d96f3..b270bdb476c51f4c2ad3c0b5a1164045dcf62a4e 100644 --- a/primitives/consensus/aura/Cargo.toml +++ b/primitives/consensus/aura/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-consensus-aura" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Primitives for Aura consensus" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,13 +12,13 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../application-crypto" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../std" } -sp-api = { version = "2.0.0-dev", default-features = false, path = "../../api" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../runtime" } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../inherents" } -sp-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../timestamp" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../std" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../../api" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../runtime" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../inherents" } +sp-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../timestamp" } [features] default = ["std"] diff --git a/primitives/consensus/aura/src/inherents.rs b/primitives/consensus/aura/src/inherents.rs index 77ec03c6f43425bbaa1c4983c95f9585590b75b1..a18bd3370306196ddafc15e339457e4c5d1918ec 100644 --- a/primitives/consensus/aura/src/inherents.rs +++ b/primitives/consensus/aura/src/inherents.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. /// Contains the inherents for the AURA module diff --git a/primitives/consensus/aura/src/lib.rs b/primitives/consensus/aura/src/lib.rs index 2dda5b28bf825e7716578298ac9340013f1dd087..cf0bcf2218a06440ec815b84a16650a8f9eef0a1 100644 --- a/primitives/consensus/aura/src/lib.rs +++ b/primitives/consensus/aura/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitives for Aura. diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml index ca097d6a32d870e141e0fffcb789420bcdf8030d..6cda2695d96e7b70cd95bd17882e61f41c41ed38 100644 --- a/primitives/consensus/babe/Cargo.toml +++ b/primitives/consensus/babe/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-consensus-babe" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Primitives for BABE consensus" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,16 +12,16 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../../application-crypto" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../../application-crypto" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } merlin = { version = "2.0", default-features = false } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../std" } -sp-api = { version = "2.0.0-dev", default-features = false, path = "../../api" } -sp-consensus = { version = "0.8.0-dev", optional = true, path = "../common" } -sp-consensus-vrf = { version = "0.8.0-dev", path = "../vrf", default-features = false } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../inherents" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../runtime" } -sp-timestamp = { version = "2.0.0-dev", default-features = false, path = "../../timestamp" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../std" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../../api" } +sp-consensus = { version = "0.8.0-rc2", optional = true, path = "../common" } +sp-consensus-vrf = { version = "0.8.0-rc2", path = "../vrf", default-features = false } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../inherents" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../runtime" } +sp-timestamp = { version = "2.0.0-rc2", default-features = false, path = "../../timestamp" } [features] default = ["std"] diff --git a/primitives/consensus/babe/src/digests.rs b/primitives/consensus/babe/src/digests.rs index 24be9b1b1455927ec1558d721bb539dd995a9a5c..4b625abe9f263be5e503002e4e2d80c25bdd1e4a 100644 --- a/primitives/consensus/babe/src/digests.rs +++ b/primitives/consensus/babe/src/digests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Private implementation details of BABE digests. diff --git a/primitives/consensus/babe/src/inherents.rs b/primitives/consensus/babe/src/inherents.rs index 7c0744ac6e13ac21f4fc1fc01afd071d93e745ec..5384183f9e67835902387a2f92e401a2bf9546b4 100644 --- a/primitives/consensus/babe/src/inherents.rs +++ b/primitives/consensus/babe/src/inherents.rs @@ -1,18 +1,20 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . //! Inherents for BABE use sp_inherents::{Error, InherentData, InherentIdentifier}; diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs index 5f26349ef98eb784104ce59d40d8349c1cafa3d0..9848715a47f6fc3d3b6a1618715ad7faa0e6d7a7 100644 --- a/primitives/consensus/babe/src/lib.rs +++ b/primitives/consensus/babe/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitives for BABE. #![deny(warnings)] diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml index 7101dde2fc3aa3e49ffd9533078ec98527c00391..f91ed927b945cdf2f16675a29967fb78173bddfc 100644 --- a/primitives/consensus/common/Cargo.toml +++ b/primitives/consensus/common/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-consensus" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Common utilities for building and using consensus engines in substrate." @@ -15,23 +15,24 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] derive_more = "0.99.2" -libp2p = { version = "0.18.1", default-features = false } +libp2p = { version = "0.19.1", default-features = false } log = "0.4.8" -sp-core = { path= "../../core", version = "2.0.0-dev"} -sp-inherents = { version = "2.0.0-dev", path = "../../inherents" } -sp-state-machine = { version = "0.8.0-dev", path = "../../../primitives/state-machine" } +sp-core = { path= "../../core", version = "2.0.0-rc2"} +sp-inherents = { version = "2.0.0-rc2", path = "../../inherents" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../../primitives/state-machine" } futures = { version = "0.3.1", features = ["thread-pool"] } futures-timer = "3.0.1" -sp-std = { version = "2.0.0-dev", path = "../../std" } -sp-version = { version = "2.0.0-dev", path = "../../version" } -sp-runtime = { version = "2.0.0-dev", path = "../../runtime" } -sp-utils = { version = "2.0.0-dev", path = "../../utils" } +sp-std = { version = "2.0.0-rc2", path = "../../std" } +sp-version = { version = "2.0.0-rc2", path = "../../version" } +sp-runtime = { version = "2.0.0-rc2", path = "../../runtime" } +sp-utils = { version = "2.0.0-rc2", path = "../../utils" } codec = { package = "parity-scale-codec", version = "1.3.0", features = ["derive"] } parking_lot = "0.10.0" serde = { version = "1.0", features = ["derive"] } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../../utils/prometheus", version = "0.8.0-rc2"} [dev-dependencies] -sp-test-primitives = { version = "2.0.0-dev", path = "../../test-primitives" } +sp-test-primitives = { version = "2.0.0-rc2", path = "../../test-primitives" } [features] default = [] diff --git a/primitives/consensus/common/src/block_import.rs b/primitives/consensus/common/src/block_import.rs index eb90ac9f1d4df6ceb0ecba42bca4b7911cce7de5..5e593da1163d77a65be2ca7bfaa9cd9f4114d71b 100644 --- a/primitives/consensus/common/src/block_import.rs +++ b/primitives/consensus/common/src/block_import.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Block import helpers. diff --git a/primitives/consensus/common/src/error.rs b/primitives/consensus/common/src/error.rs index d7e396223a2c53611856642631f363025107f486..0da749589013d8ce2a8328ac6c1f647b83ba2005 100644 --- a/primitives/consensus/common/src/error.rs +++ b/primitives/consensus/common/src/error.rs @@ -1,22 +1,23 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Error types in Consensus use sp_version::RuntimeVersion; -use sp_core::ed25519::{Public, Signature}; +use sp_core::ed25519::Public; use std::error; /// Result type alias. @@ -48,7 +49,7 @@ pub enum Error { CannotPropose, /// Error checking signature #[display(fmt="Message signature {:?} by {:?} is invalid.", _0, _1)] - InvalidSignature(Signature, Public), + InvalidSignature(Vec, Vec), /// Invalid authorities set received from the runtime. #[display(fmt="Current state of blockchain has invalid authorities set")] InvalidAuthoritiesSet, @@ -79,6 +80,9 @@ pub enum Error { #[display(fmt="Chain lookup failed: {}", _0)] #[from(ignore)] ChainLookup(String), + /// Signing failed + #[display(fmt="Failed to sign using key: {:?}. Reason: {}", _0, _1)] + CannotSign(Vec, String) } impl error::Error for Error { diff --git a/primitives/consensus/common/src/evaluation.rs b/primitives/consensus/common/src/evaluation.rs index 5542042fedb1c186dae948b7da1b91e7c57fd9e2..76fcd5310b06af6daf0704b964059a3d0e95ad36 100644 --- a/primitives/consensus/common/src/evaluation.rs +++ b/primitives/consensus/common/src/evaluation.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Block evaluation and evaluation errors. diff --git a/primitives/consensus/common/src/import_queue.rs b/primitives/consensus/common/src/import_queue.rs index 2da0bcac0c17b8b6661bd5fcedf0f7ef7e1a691c..1a034e11d6644bc4de75980ee191627a71cb322c 100644 --- a/primitives/consensus/common/src/import_queue.rs +++ b/primitives/consensus/common/src/import_queue.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Import Queue primitive: something which can verify and import blocks. //! @@ -26,13 +27,17 @@ //! queues to be instantiated simply. use std::collections::HashMap; + use sp_runtime::{Justification, traits::{Block as BlockT, Header as _, NumberFor}}; -use crate::error::Error as ConsensusError; -use crate::block_import::{ - BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult, - BlockCheckParams, FinalityProofImport, -}; +use crate::{ + error::Error as ConsensusError, + block_import::{ + BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult, + BlockCheckParams, FinalityProofImport, + }, + metrics::Metrics, +}; pub use basic_queue::BasicQueue; mod basic_queue; @@ -185,6 +190,17 @@ pub fn import_single_block, Transaction>( block_origin: BlockOrigin, block: IncomingBlock, verifier: &mut V, +) -> Result>, BlockImportError> { + import_single_block_metered(import_handle, block_origin, block, verifier, None) +} + +/// Single block import function with metering. +pub(crate) fn import_single_block_metered, Transaction>( + import_handle: &mut dyn BlockImport, + block_origin: BlockOrigin, + block: IncomingBlock, + verifier: &mut V, + metrics: Option, ) -> Result>, BlockImportError> { let peer = block.origin; @@ -206,8 +222,8 @@ pub fn import_single_block, Transaction>( let hash = header.hash(); let parent_hash = header.parent_hash().clone(); - let import_error = |e| { - match e { + let import_handler = |import| { + match import { Ok(ImportResult::AlreadyInChain) => { trace!(target: "sync", "Block already in chain {}: {:?}", number, hash); Ok(BlockImportResult::ImportedKnown(number)) @@ -231,7 +247,8 @@ pub fn import_single_block, Transaction>( } } }; - match import_error(import_handle.check_block(BlockCheckParams { + + match import_handler(import_handle.check_block(BlockCheckParams { hash, number, parent_hash, @@ -242,6 +259,7 @@ pub fn import_single_block, Transaction>( r => return Ok(r), // Any other successful result means that the block is already imported. } + let started = std::time::Instant::now(); let (mut import_block, maybe_keys) = verifier.verify(block_origin, header, justification, block.body) .map_err(|msg| { if let Some(ref peer) = peer { @@ -249,14 +267,21 @@ pub fn import_single_block, Transaction>( } else { trace!(target: "sync", "Verifying {}({}) failed: {}", number, hash, msg); } + if let Some(metrics) = metrics.as_ref() { + metrics.report_verification(false, started.elapsed()); + } BlockImportError::VerificationFailed(peer.clone(), msg) })?; + if let Some(metrics) = metrics.as_ref() { + metrics.report_verification(true, started.elapsed()); + } + let mut cache = HashMap::new(); if let Some(keys) = maybe_keys { cache.extend(keys.into_iter()); } import_block.allow_missing_state = block.allow_missing_state; - import_error(import_handle.import_block(import_block.convert_transaction(), cache)) + import_handler(import_handle.import_block(import_block.convert_transaction(), cache)) } diff --git a/primitives/consensus/common/src/import_queue/basic_queue.rs b/primitives/consensus/common/src/import_queue/basic_queue.rs index f2b830e890e4040bff14f294e9c450078a4f9ddd..33c3da910d23b7019a0367c779a24b76fe9f2a11 100644 --- a/primitives/consensus/common/src/import_queue/basic_queue.rs +++ b/primitives/consensus/common/src/import_queue/basic_queue.rs @@ -1,31 +1,36 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::{mem, pin::Pin, time::Duration, marker::PhantomData}; use futures::{prelude::*, task::Context, task::Poll}; use futures_timer::Delay; use sp_runtime::{Justification, traits::{Block as BlockT, Header as HeaderT, NumberFor}}; use sp_utils::mpsc::{TracingUnboundedSender, tracing_unbounded}; - -use crate::block_import::BlockOrigin; -use crate::import_queue::{ - BlockImportResult, BlockImportError, Verifier, BoxBlockImport, BoxFinalityProofImport, - BoxJustificationImport, ImportQueue, Link, Origin, - IncomingBlock, import_single_block, - buffered_link::{self, BufferedLinkSender, BufferedLinkReceiver} +use prometheus_endpoint::Registry; + +use crate::{ + block_import::BlockOrigin, + import_queue::{ + BlockImportResult, BlockImportError, Verifier, BoxBlockImport, BoxFinalityProofImport, + BoxJustificationImport, ImportQueue, Link, Origin, + IncomingBlock, import_single_block_metered, + buffered_link::{self, BufferedLinkSender, BufferedLinkReceiver}, + }, + metrics::Metrics, }; /// Interface to a basic block import queue that is importing blocks sequentially in a separate @@ -57,14 +62,21 @@ impl BasicQueue { justification_import: Option>, finality_proof_import: Option>, spawner: &impl sp_core::traits::SpawnBlocking, + prometheus_registry: Option<&Registry>, ) -> Self { let (result_sender, result_port) = buffered_link::buffered_link(); + let metrics = prometheus_registry.and_then(|r| + Metrics::register(r) + .map_err(|err| { log::warn!("Failed to register Prometheus metrics: {}", err); }) + .ok() + ); let (future, worker_sender) = BlockImportWorker::new( result_sender, verifier, block_import, justification_import, finality_proof_import, + metrics, ); spawner.spawn_blocking("basic-block-import-worker", future.boxed()); @@ -132,6 +144,7 @@ struct BlockImportWorker { justification_import: Option>, finality_proof_import: Option>, delay_between_blocks: Duration, + metrics: Option, _phantom: PhantomData, } @@ -142,6 +155,7 @@ impl BlockImportWorker { block_import: BoxBlockImport, justification_import: Option>, finality_proof_import: Option>, + metrics: Option, ) -> (impl Future + Send, TracingUnboundedSender>) { let (sender, mut port) = tracing_unbounded("mpsc_block_import_worker"); @@ -150,6 +164,7 @@ impl BlockImportWorker { justification_import, finality_proof_import, delay_between_blocks: Duration::new(0, 0), + metrics, _phantom: PhantomData, }; @@ -210,7 +225,7 @@ impl BlockImportWorker { // a `Future` into `importing`. let (bi, verif) = block_import_verifier.take() .expect("block_import_verifier is always Some; qed"); - importing = Some(worker.import_a_batch_of_blocks(bi, verif, origin, blocks)); + importing = Some(worker.import_batch(bi, verif, origin, blocks)); }, ToWorkerMsg::ImportFinalityProof(who, hash, number, proof) => { let (_, verif) = block_import_verifier.as_mut() @@ -232,16 +247,17 @@ impl BlockImportWorker { /// /// For lifetime reasons, the `BlockImport` implementation must be passed by value, and is /// yielded back in the output once the import is finished. - fn import_a_batch_of_blocks>( + fn import_batch>( &mut self, block_import: BoxBlockImport, verifier: V, origin: BlockOrigin, - blocks: Vec> + blocks: Vec>, ) -> impl Future, V)> { let mut result_sender = self.result_sender.clone(); + let metrics = self.metrics.clone(); - import_many_blocks(block_import, origin, blocks, verifier, self.delay_between_blocks) + import_many_blocks(block_import, origin, blocks, verifier, self.delay_between_blocks, metrics) .then(move |(imported, count, results, block_import, verifier)| { result_sender.blocks_processed(imported, count, results); future::ready((block_import, verifier)) @@ -312,6 +328,7 @@ fn import_many_blocks, Transaction>( blocks: Vec>, verifier: V, delay_between_blocks: Duration, + metrics: Option, ) -> impl Future< Output = ( usize, @@ -361,9 +378,9 @@ fn import_many_blocks, Transaction>( None => { // No block left to import, success! let import_handle = import_handle.take() - .expect("Future polled again after it has finished"); + .expect("Future polled again after it has finished (import handle is None)"); let verifier = verifier.take() - .expect("Future polled again after it has finished"); + .expect("Future polled again after it has finished (verifier handle is None)"); let results = mem::replace(&mut results, Vec::new()); return Poll::Ready((imported, count, results, import_handle, verifier)); }, @@ -373,9 +390,9 @@ fn import_many_blocks, Transaction>( // therefore `import_handle` and `verifier` are always `Some` here. It is illegal to poll // a `Future` again after it has ended. let import_handle = import_handle.as_mut() - .expect("Future polled again after it has finished"); + .expect("Future polled again after it has finished (import handle is None)"); let verifier = verifier.as_mut() - .expect("Future polled again after it has finished"); + .expect("Future polled again after it has finished (verifier handle is None)"); let block_number = block.header.as_ref().map(|h| h.number().clone()); let block_hash = block.hash; @@ -383,14 +400,19 @@ fn import_many_blocks, Transaction>( Err(BlockImportError::Cancelled) } else { // The actual import. - import_single_block( + import_single_block_metered( &mut **import_handle, blocks_origin.clone(), block, verifier, + metrics.clone(), ) }; + if let Some(metrics) = metrics.as_ref() { + metrics.report_import::(&import_result); + } + if import_result.is_ok() { trace!(target: "sync", "Block imported successfully {:?} ({})", block_number, block_hash); imported += 1; diff --git a/primitives/consensus/common/src/import_queue/buffered_link.rs b/primitives/consensus/common/src/import_queue/buffered_link.rs index ea77fc97f0e8a28e889ea8c13c1644a2f968a734..d85121a710ecbee67716fa1462c2b5dfc96035d1 100644 --- a/primitives/consensus/common/src/import_queue/buffered_link.rs +++ b/primitives/consensus/common/src/import_queue/buffered_link.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides the `buffered_link` utility. //! diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs index 9f338ad1d4e75741bb02bca67005c1d316909565..da23172783cdcba7d973a5c6f4c1dd96b6b86963 100644 --- a/primitives/consensus/common/src/lib.rs +++ b/primitives/consensus/common/src/lib.rs @@ -44,6 +44,7 @@ pub mod block_import; mod select_chain; pub mod import_queue; pub mod evaluation; +mod metrics; // block size limit. const MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024 + 512; @@ -71,7 +72,9 @@ pub enum BlockStatus { Unknown, } -/// Environment producer for a Consensus instance. Creates proposer instance and communication streams. +/// Environment for a Consensus instance. +/// +/// Creates proposer instance. pub trait Environment { /// The proposer type this creates. type Proposer: Proposer + Send + 'static; @@ -154,7 +157,7 @@ pub trait Proposer { /// /// Returns a future that resolves to a [`Proposal`] or to [`Error`]. fn propose( - &mut self, + self, inherent_data: InherentData, inherent_digests: DigestFor, max_duration: Duration, diff --git a/primitives/consensus/common/src/metrics.rs b/primitives/consensus/common/src/metrics.rs new file mode 100644 index 0000000000000000000000000000000000000000..90df85a2948ef39cfb391a9f09a168b0e8effbcd --- /dev/null +++ b/primitives/consensus/common/src/metrics.rs @@ -0,0 +1,80 @@ +// Copyright 2020 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 . + +//! Metering tools for consensus + +use prometheus_endpoint::{register, U64, Registry, PrometheusError, Opts, CounterVec, HistogramVec, HistogramOpts}; + +use sp_runtime::traits::{Block as BlockT, NumberFor}; + +use crate::import_queue::{BlockImportResult, BlockImportError}; + +/// Generic Prometheus metrics for common consensus functionality. +#[derive(Clone)] +pub(crate) struct Metrics { + pub import_queue_processed: CounterVec, + pub block_verification_time: HistogramVec, +} + +impl Metrics { + pub(crate) fn register(registry: &Registry) -> Result { + Ok(Self { + import_queue_processed: register( + CounterVec::new( + Opts::new("import_queue_processed_total", "Blocks processed by import queue"), + &["result"] // 'success or failure + )?, + registry, + )?, + block_verification_time: register( + HistogramVec::new( + HistogramOpts::new( + "block_verification_time", + "Histogram of time taken to import blocks", + ), + &["result"], + )?, + registry, + )?, + }) + } + + pub fn report_import( + &self, + result: &Result>, BlockImportError>, + ) { + let label = match result { + Ok(_) => "success", + Err(BlockImportError::IncompleteHeader(_)) => "incomplete_header", + Err(BlockImportError::VerificationFailed(_,_)) => "verification_failed", + Err(BlockImportError::BadBlock(_)) => "bad_block", + Err(BlockImportError::MissingState) => "missing_state", + Err(BlockImportError::UnknownParent) => "unknown_parent", + Err(BlockImportError::Cancelled) => "cancelled", + Err(BlockImportError::Other(_)) => "failed", + }; + + self.import_queue_processed.with_label_values( + &[label] + ).inc(); + } + + pub fn report_verification(&self, success: bool, time: std::time::Duration) { + self.block_verification_time.with_label_values( + &[if success { "success" } else { "verification_failed" }] + ).observe(time.as_secs_f64()); + } +} diff --git a/primitives/consensus/common/src/offline_tracker.rs b/primitives/consensus/common/src/offline_tracker.rs index b4959503b1d394403de4434865dd10d3f43c61ea..9269640ffc8e46a1c0c21fe5318bbb4bf36bdb1d 100644 --- a/primitives/consensus/common/src/offline_tracker.rs +++ b/primitives/consensus/common/src/offline_tracker.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tracks offline validators. diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml index a7bcb6a000fed5d30b74e027cc32ef56a3f82d2b..d696b0a975c1a1bdf3ae344af58f22a4e13f9d68 100644 --- a/primitives/consensus/pow/Cargo.toml +++ b/primitives/consensus/pow/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-consensus-pow" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Primitives for Aura consensus" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,10 +12,10 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-api = { version = "2.0.0-dev", default-features = false, path = "../../api" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../std" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../runtime" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../core" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../../api" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../std" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../runtime" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../core" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } [features] diff --git a/primitives/consensus/pow/src/lib.rs b/primitives/consensus/pow/src/lib.rs index fa8f75d1be64c3e014cfa43f5cb15801dd84a851..79c9b6f16c3bd9e3cb91dec5a9e2fa40f9d3c43c 100644 --- a/primitives/consensus/pow/src/lib.rs +++ b/primitives/consensus/pow/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitives for Substrate Proof-of-Work (PoW) consensus. diff --git a/primitives/consensus/vrf/Cargo.toml b/primitives/consensus/vrf/Cargo.toml index 92d8a77cb4edfe847d05393e65e320646a231ae8..3e0f3c8c3f5c2a253b157ee454b53317bc4addc1 100644 --- a/primitives/consensus/vrf/Cargo.toml +++ b/primitives/consensus/vrf/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-consensus-vrf" -version = "0.8.0-dev" +version = "0.8.0-rc2" authors = ["Parity Technologies "] description = "Primitives for VRF based consensus" edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" repository = "https://github.com/paritytech/substrate/" homepage = "https://substrate.dev" @@ -14,9 +14,9 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { version = "1.0.0", package = "parity-scale-codec", default-features = false } schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } -sp-std = { version = "2.0.0-dev", path = "../../std", default-features = false } -sp-core = { version = "2.0.0-dev", path = "../../core", default-features = false } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../../runtime" } +sp-std = { version = "2.0.0-rc2", path = "../../std", default-features = false } +sp-core = { version = "2.0.0-rc2", path = "../../core", default-features = false } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../runtime" } [features] default = ["std"] diff --git a/primitives/consensus/vrf/src/lib.rs b/primitives/consensus/vrf/src/lib.rs index 4ec6e376d6829f15937e38d569c9edf1779b0927..430e11974bcd44cc6a3919ef1d8ad84af1357ddb 100644 --- a/primitives/consensus/vrf/src/lib.rs +++ b/primitives/consensus/vrf/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitives for VRF-based consensus engines. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/primitives/consensus/vrf/src/schnorrkel.rs b/primitives/consensus/vrf/src/schnorrkel.rs index c1c2a7c21ab9e37b30df128e79065111b566ddca..65e68375865d05bb6e19929985abad3908218c4c 100644 --- a/primitives/consensus/vrf/src/schnorrkel.rs +++ b/primitives/consensus/vrf/src/schnorrkel.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Schnorrkel-based VRF. diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 2ab23d23c4a0e691770941cb74bef3ac3d6a405b..1c06163843634dbb98a9443229af50df3e366b0a 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-core" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Shareable Substrate types." @@ -13,7 +13,8 @@ documentation = "https://docs.rs/sp-core" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } +derive_more = "0.99.2" +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } log = { version = "0.4.8", default-features = false } serde = { version = "1.0.101", optional = true, features = ["derive"] } @@ -32,9 +33,9 @@ num-traits = { version = "0.2.8", default-features = false } zeroize = { version = "1.0.0", default-features = false } lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.10.0", optional = true } -sp-debug-derive = { version = "2.0.0-dev", path = "../debug-derive" } -sp-externalities = { version = "0.8.0-dev", optional = true, path = "../externalities" } -sp-storage = { version = "2.0.0-dev", default-features = false, path = "../storage" } +sp-debug-derive = { version = "2.0.0-rc2", path = "../debug-derive" } +sp-externalities = { version = "0.8.0-rc2", optional = true, path = "../externalities" } +sp-storage = { version = "2.0.0-rc2", default-features = false, path = "../storage" } parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] } futures = { version = "0.3.1", optional = true } @@ -49,10 +50,10 @@ twox-hash = { version = "1.5.0", default-features = false, optional = true } libsecp256k1 = { version = "0.3.2", default-features = false, features = ["hmac"], optional = true } merlin = { version = "2.0", default-features = false, optional = true } -sp-runtime-interface = { version = "2.0.0-dev", default-features = false, path = "../runtime-interface" } +sp-runtime-interface = { version = "2.0.0-rc2", default-features = false, path = "../runtime-interface" } [dev-dependencies] -sp-serializer = { version = "2.0.0-dev", path = "../serializer" } +sp-serializer = { version = "2.0.0-rc2", path = "../serializer" } pretty_assertions = "0.6.1" hex-literal = "0.2.1" rand = "0.7.2" diff --git a/primitives/core/benches/bench.rs b/primitives/core/benches/bench.rs index 7db9d72e6b5b0d6afa04c28f07c91c6491a4c541..335920c4d204c52b2f4ca1d9ddd946bdcbfde11e 100644 --- a/primitives/core/benches/bench.rs +++ b/primitives/core/benches/bench.rs @@ -13,6 +13,7 @@ // limitations under the License. + #[macro_use] extern crate criterion; diff --git a/primitives/core/src/changes_trie.rs b/primitives/core/src/changes_trie.rs index cb21ffe13df969141cb056056694914e4006ca9e..1d88242e43d69729d2c3e37697f63fc81d75f364 100644 --- a/primitives/core/src/changes_trie.rs +++ b/primitives/core/src/changes_trie.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate changes trie configuration. diff --git a/primitives/core/src/crypto.rs b/primitives/core/src/crypto.rs index 44d43c3a44230fcf339b5f180c25140df185c52e..73134dcbfa9da956abaf2d3509762cd60641257c 100644 --- a/primitives/core/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Cryptographic utilities. @@ -559,6 +560,8 @@ pub trait Public: /// Return a slice filled with raw data. fn as_slice(&self) -> &[u8] { self.as_ref() } + /// Return `CryptoTypePublicPair` from public key. + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair; } /// An opaque 32-byte cryptographic identifier. @@ -706,6 +709,11 @@ mod dummy { #[cfg(feature = "std")] fn to_raw_vec(&self) -> Vec { vec![] } fn as_slice(&self) -> &[u8] { b"" } + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair( + CryptoTypeId(*b"dumm"), Public::to_raw_vec(self) + ) + } } impl Pair for Dummy { @@ -1006,6 +1014,8 @@ pub mod key_types { pub const AUTHORITY_DISCOVERY: KeyTypeId = KeyTypeId(*b"audi"); /// Key type for staking, built-in. Identified as `stak`. pub const STAKING: KeyTypeId = KeyTypeId(*b"stak"); + /// Key type for equivocation reporting, built-in. Identified as `fish`. + pub const REPORTING: KeyTypeId = KeyTypeId(*b"fish"); /// A key type ID useful for tests. pub const DUMMY: KeyTypeId = KeyTypeId(*b"dumy"); } @@ -1059,6 +1069,11 @@ mod tests { fn to_raw_vec(&self) -> Vec { vec![] } + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair( + CryptoTypeId(*b"dumm"), self.to_raw_vec(), + ) + } } impl Pair for TestPair { type Public = TestPublic; diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs index 8a45157844f3af20ce5ded4ce3dc28f6008a5983..29fa9a9c5c5d723f9696f699bdcd0b28c473c1dc 100644 --- a/primitives/core/src/ecdsa.rs +++ b/primitives/core/src/ecdsa.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Simple ECDSA API. @@ -36,7 +37,8 @@ use crate::{hashing::blake2_256, crypto::{Pair as TraitPair, DeriveJunction, Sec use crate::crypto::Ss58Codec; #[cfg(feature = "std")] use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; -use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive, CryptoTypeId}; +use crate::crypto::{Public as TraitPublic, CryptoTypePublicPair, UncheckedFrom, CryptoType, Derive, CryptoTypeId}; +use sp_runtime_interface::pass_by::PassByInner; #[cfg(feature = "full_crypto")] use secp256k1::{PublicKey, SecretKey}; @@ -50,7 +52,7 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds"); type Seed = [u8; 32]; /// The ECDSA compressed public key. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, PassByInner)] pub struct Public([u8; 33]); impl PartialOrd for Public { @@ -118,6 +120,22 @@ impl TraitPublic for Public { r.copy_from_slice(data); Self(r) } + + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) + } +} + +impl From for CryptoTypePublicPair { + fn from(key: Public) -> Self { + (&key).into() + } +} + +impl From<&Public> for CryptoTypePublicPair { + fn from(key: &Public) -> Self { + CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) + } } impl Derive for Public {} @@ -173,12 +191,17 @@ impl std::fmt::Display for Public { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for Public { +impl sp_std::fmt::Debug for Public { + #[cfg(feature = "std")] fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let s = self.to_ss58check(); write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.as_ref()), &s[0..8]) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } } #[cfg(feature = "std")] @@ -204,7 +227,7 @@ impl sp_std::hash::Hash for Public { } /// A signature (a 512-bit value, plus 8 bits for recovery ID). -#[derive(Encode, Decode)] +#[derive(Encode, Decode, PassByInner)] pub struct Signature([u8; 65]); impl sp_std::convert::TryFrom<&[u8]> for Signature { @@ -284,11 +307,16 @@ impl AsMut<[u8]> for Signature { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for Signature { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl sp_std::fmt::Debug for Signature { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } } #[cfg(feature = "full_crypto")] diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs index abeac05388d2773e7ba80f60d6b4e9193ebe2fcd..f6e7227013728c86dd9ad5ce9d6febd6ab79b006 100644 --- a/primitives/core/src/ed25519.rs +++ b/primitives/core/src/ed25519.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Simple Ed25519 API. @@ -377,20 +378,24 @@ impl TraitPublic for Public { r.copy_from_slice(data); Public(r) } + + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) + } } impl Derive for Public {} impl From for CryptoTypePublicPair { - fn from(key: Public) -> Self { - (&key).into() - } + fn from(key: Public) -> Self { + (&key).into() + } } impl From<&Public> for CryptoTypePublicPair { - fn from(key: &Public) -> Self { - CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) - } + fn from(key: &Public) -> Self { + CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec()) + } } /// Derive a single hard junction. diff --git a/primitives/core/src/hash.rs b/primitives/core/src/hash.rs index 424fefbe6a47028f773699a0f27a1a78a7f66ae4..20a6788c3207029eacba04c0e8faae79ee1ef3fd 100644 --- a/primitives/core/src/hash.rs +++ b/primitives/core/src/hash.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A fixed hash type. diff --git a/primitives/core/src/hasher.rs b/primitives/core/src/hasher.rs index 28da432da7142b1a8ada83946088a03eb90d54ee..8ccaa4d90a78d7e697750f18f0b35fbcb8351396 100644 --- a/primitives/core/src/hasher.rs +++ b/primitives/core/src/hasher.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate Blake2b Hasher implementation @@ -35,3 +36,23 @@ pub mod blake2 { } } } + +pub mod keccak { + use hash_db::Hasher; + use hash256_std_hasher::Hash256StdHasher; + use crate::hash::H256; + + /// Concrete implementation of Hasher using Keccak 256-bit hashes + #[derive(Debug)] + pub struct KeccakHasher; + + impl Hasher for KeccakHasher { + type Out = H256; + type StdHasher = Hash256StdHasher; + const LENGTH: usize = 32; + + fn hash(x: &[u8]) -> Self::Out { + crate::hashing::keccak_256(x).into() + } + } +} diff --git a/primitives/core/src/hashing.rs b/primitives/core/src/hashing.rs index d958da6c321380301d087cd40951bc3c50c12b2f..f61700a5a43cdcff29946cfffaa39131187236a9 100644 --- a/primitives/core/src/hashing.rs +++ b/primitives/core/src/hashing.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Hashing functions. diff --git a/primitives/core/src/hexdisplay.rs b/primitives/core/src/hexdisplay.rs index 14fedc205c49ebd87b2af807975f3c6d7ddf0c72..f4c8fea8f22230fa36b276898205cd9813f3bdeb 100644 --- a/primitives/core/src/hexdisplay.rs +++ b/primitives/core/src/hexdisplay.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Wrapper type for byte collections that outputs hex. diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 9da56018e95d7abeececd5122f371a1766d05bb3..56dbbc7b7898de5b442516b82c31026c835c3068 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Shareable Substrate types. @@ -82,6 +83,8 @@ pub use crypto::{DeriveJunction, Pair, Public}; pub use hash_db::Hasher; #[cfg(feature = "std")] pub use self::hasher::blake2::Blake2Hasher; +#[cfg(feature = "std")] +pub use self::hasher::keccak::KeccakHasher; pub use sp_storage as storage; diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs index e792d71afca3b41bf8f312d34dba2859ae324986..b2ff3552135ce935a2e8d3a79c7533baa5afa117 100644 --- a/primitives/core/src/offchain/mod.rs +++ b/primitives/core/src/offchain/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Offchain workers types @@ -36,6 +37,9 @@ pub trait OffchainStorage: Clone + Send + Sync { /// Persist a value in storage under given key and prefix. fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]); + /// Clear a storage entry under given key and prefix. + fn remove(&mut self, prefix: &[u8], key: &[u8]); + /// Retrieve a value from storage under given key and prefix. fn get(&self, prefix: &[u8], key: &[u8]) -> Option>; @@ -218,7 +222,7 @@ pub struct Duration(u64); impl Duration { /// Create new duration representing given number of milliseconds. - pub fn from_millis(millis: u64) -> Self { + pub const fn from_millis(millis: u64) -> Self { Duration(millis) } @@ -345,9 +349,15 @@ pub trait Externalities: Send { /// Sets a value in the local storage. /// /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. + /// offchain worker tasks running on the same machine. It _is_ persisted between runs. fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]); + /// Removes a value in the local storage. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It _is_ persisted between runs. + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]); + /// Sets a value in the local storage if it matches current value. /// /// Since multiple offchain workers may be running concurrently, to prevent @@ -356,7 +366,7 @@ pub trait Externalities: Send { /// Returns `true` if the value has been set, `false` otherwise. /// /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. + /// offchain worker tasks running on the same machine. It _is_ persisted between runs. fn local_storage_compare_and_set( &mut self, kind: StorageKind, @@ -369,7 +379,7 @@ pub trait Externalities: Send { /// /// If the value does not exist in the storage `None` will be returned. /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. + /// offchain worker tasks running on the same machine. It _is_ persisted between runs. fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option>; /// Initiates a http request given HTTP verb and the URL. @@ -512,6 +522,10 @@ impl Externalities for Box { (&mut **self).local_storage_set(kind, key, value) } + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + (&mut **self).local_storage_clear(kind, key) + } + fn local_storage_compare_and_set( &mut self, kind: StorageKind, @@ -617,6 +631,11 @@ impl Externalities for LimitedExternalities { self.externalities.local_storage_set(kind, key, value) } + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + self.check(Capability::OffchainWorkerDbWrite, "local_storage_clear"); + self.externalities.local_storage_clear(kind, key) + } + fn local_storage_compare_and_set( &mut self, kind: StorageKind, diff --git a/primitives/core/src/offchain/storage.rs b/primitives/core/src/offchain/storage.rs index 830c25392b7426e1f48257487fbbe09fdf8fdd99..52a7bbe857d9d6379f14c84609f7bec11993fbd2 100644 --- a/primitives/core/src/offchain/storage.rs +++ b/primitives/core/src/offchain/storage.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! In-memory implementation of offchain workers database. @@ -50,6 +51,11 @@ impl OffchainStorage for InMemOffchainStorage { self.storage.insert(key, value.to_vec()); } + fn remove(&mut self, prefix: &[u8], key: &[u8]) { + let key: Vec = prefix.iter().chain(key).cloned().collect(); + self.storage.remove(&key); + } + fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { let key: Vec = prefix.iter().chain(key).cloned().collect(); self.storage.get(&key).cloned() diff --git a/primitives/core/src/offchain/testing.rs b/primitives/core/src/offchain/testing.rs index b889374a47c2fd26baee2f0fdcec28a6a73cc786..76cf8915f205430264b48d0e0f0ac9064c1994bb 100644 --- a/primitives/core/src/offchain/testing.rs +++ b/primitives/core/src/offchain/testing.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Utilities for offchain calls testing. //! @@ -72,10 +73,10 @@ pub struct OffchainState { pub persistent_storage: InMemOffchainStorage, /// Local storage pub local_storage: InMemOffchainStorage, - /// Current timestamp (unix millis) - pub timestamp: u64, /// A supposedly random seed. pub seed: [u8; 32], + /// A timestamp simulating the current time. + pub timestamp: Timestamp, } impl OffchainState { @@ -159,11 +160,11 @@ impl offchain::Externalities for TestOffchainExt { } fn timestamp(&mut self) -> Timestamp { - Timestamp::from_unix_millis(self.0.read().timestamp) + self.0.read().timestamp } - fn sleep_until(&mut self, _deadline: Timestamp) { - unimplemented!("not needed in tests so far") + fn sleep_until(&mut self, deadline: Timestamp) { + self.0.write().timestamp = deadline; } fn random_seed(&mut self) -> [u8; 32] { @@ -178,6 +179,14 @@ impl offchain::Externalities for TestOffchainExt { }.set(b"", key, value); } + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + let mut state = self.0.write(); + match kind { + StorageKind::LOCAL => &mut state.local_storage, + StorageKind::PERSISTENT => &mut state.persistent_storage, + }.remove(b"", key); + } + fn local_storage_compare_and_set( &mut self, kind: StorageKind, diff --git a/primitives/core/src/sandbox.rs b/primitives/core/src/sandbox.rs index 73fbcfb572ee355f645dc716f197ef8f29a7292d..4cb5bd41d5826bd3f7d8a581f424d368a11cf070 100644 --- a/primitives/core/src/sandbox.rs +++ b/primitives/core/src/sandbox.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Definition of a sandbox environment. diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs index cadfb25776b83552ee2ef8794660dd3a4ef34f73..9e9aaf53bbf1fda34f81450af3a5617184f78d82 100644 --- a/primitives/core/src/sr25519.rs +++ b/primitives/core/src/sr25519.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Simple sr25519 (Schnorr-Ristretto) API. @@ -391,6 +392,10 @@ impl TraitPublic for Public { r.copy_from_slice(data); Public(r) } + + fn to_public_crypto_pair(&self) -> CryptoTypePublicPair { + CryptoTypePublicPair(CRYPTO_ID, self.to_raw_vec()) + } } impl From for CryptoTypePublicPair { diff --git a/primitives/core/src/tasks.rs b/primitives/core/src/tasks.rs index 199a185e5371a0efdd272e824d934d07f994d1e3..9a181255ec4e0ee6a6f8b34f682ecb7aefc45ef8 100644 --- a/primitives/core/src/tasks.rs +++ b/primitives/core/src/tasks.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Module for low-level asynchronous processing. diff --git a/primitives/core/src/testing.rs b/primitives/core/src/testing.rs index f818865d2197e434573146174f190ed7284d4617..e14eb6a7f37c6f6da25c94f5b750fd55c34d17e5 100644 --- a/primitives/core/src/testing.rs +++ b/primitives/core/src/testing.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Types that should only be used for testing! @@ -20,7 +21,7 @@ use crate::crypto::KeyTypeId; #[cfg(feature = "std")] use crate::{ crypto::{Pair, Public, CryptoTypePublicPair}, - ed25519, sr25519, + ed25519, sr25519, ecdsa, traits::BareCryptoStoreError }; #[cfg(feature = "std")] @@ -29,6 +30,8 @@ use std::collections::HashSet; pub const ED25519: KeyTypeId = KeyTypeId(*b"ed25"); /// Key type for generic Sr 25519 key. pub const SR25519: KeyTypeId = KeyTypeId(*b"sr25"); +/// Key type for generic Sr 25519 key. +pub const ECDSA: KeyTypeId = KeyTypeId(*b"ecds"); /// A keystore implementation usable in tests. #[cfg(feature = "std")] @@ -61,6 +64,14 @@ impl KeyStore { ) } + fn ecdsa_key_pair(&self, id: KeyTypeId, pub_key: &ecdsa::Public) -> Option { + self.keys.get(&id) + .and_then(|inner| + inner.get(pub_key.as_slice()) + .map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid")) + ) + } + } #[cfg(feature = "std")] @@ -73,6 +84,7 @@ impl crate::traits::BareCryptoStore for KeyStore { .fold(Vec::new(), |mut v, k| { v.push(CryptoTypePublicPair(sr25519::CRYPTO_ID, k.clone())); v.push(CryptoTypePublicPair(ed25519::CRYPTO_ID, k.clone())); + v.push(CryptoTypePublicPair(ecdsa::CRYPTO_ID, k.clone())); v })) }) @@ -141,6 +153,37 @@ impl crate::traits::BareCryptoStore for KeyStore { } } + fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec { + self.keys.get(&id) + .map(|keys| + keys.values() + .map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid")) + .map(|p| p.public()) + .collect() + ) + .unwrap_or_default() + } + + fn ecdsa_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> Result { + match seed { + Some(seed) => { + let pair = ecdsa::Pair::from_string(seed, None) + .map_err(|_| BareCryptoStoreError::ValidationError("Generates an `ecdsa` pair.".to_owned()))?; + self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into()); + Ok(pair.public()) + }, + None => { + let (pair, phrase, _) = ecdsa::Pair::generate_with_phrase(None); + self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), phrase); + Ok(pair.public()) + } + } + } + fn insert_unknown(&mut self, id: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> { self.keys.entry(id).or_default().insert(public.to_owned(), suri.to_string()); Ok(()) @@ -186,6 +229,12 @@ impl crate::traits::BareCryptoStore for KeyStore { .ok_or(BareCryptoStoreError::PairNotFound("sr25519".to_owned()))?; return Ok(key_pair.sign(msg).encode()); } + ecdsa::CRYPTO_ID => { + let key_pair: ecdsa::Pair = self + .ecdsa_key_pair(id, &ecdsa::Public::from_slice(key.1.as_slice())) + .ok_or(BareCryptoStoreError::PairNotFound("ecdsa".to_owned()))?; + return Ok(key_pair.sign(msg).encode()); + } _ => Err(BareCryptoStoreError::KeyNotSupported(id)) } } diff --git a/primitives/core/src/traits.rs b/primitives/core/src/traits.rs index 133a4a4e1958a7e696578a615da5f17634c2b307..880b34a1ed191f30c18748f1b77451234fc7386d 100644 --- a/primitives/core/src/traits.rs +++ b/primitives/core/src/traits.rs @@ -1,24 +1,25 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Shareable Substrate traits. use crate::{ crypto::{KeyTypeId, CryptoTypePublicPair}, - ed25519, sr25519, + ed25519, sr25519, ecdsa, }; use std::{ @@ -31,17 +32,22 @@ use std::{ pub use sp_externalities::{Externalities, ExternalitiesExt}; /// BareCryptoStore error -#[derive(Debug)] +#[derive(Debug, derive_more::Display)] pub enum BareCryptoStoreError { /// Public key type is not supported + #[display(fmt="Key not supported: {:?}", _0)] KeyNotSupported(KeyTypeId), /// Pair not found for public key and KeyTypeId + #[display(fmt="Pair was not found: {}", _0)] PairNotFound(String), /// Validation error + #[display(fmt="Validation error: {}", _0)] ValidationError(String), /// Keystore unavailable + #[display(fmt="Keystore unavailable")] Unavailable, /// Programming errors + #[display(fmt="An unknown keystore error occurred: {}", _0)] Other(String) } @@ -71,6 +77,18 @@ pub trait BareCryptoStore: Send + Sync { id: KeyTypeId, seed: Option<&str>, ) -> Result; + /// Returns all ecdsa public keys for the given key type. + fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec; + /// Generate a new ecdsa key pair for the given key type and an optional seed. + /// + /// If the given seed is `Some(_)`, the key pair will only be stored in memory. + /// + /// Returns the public key of the generated key pair. + fn ecdsa_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> Result; /// Insert a new key. This doesn't require any known of the crypto; but a public key must be /// manually provided. diff --git a/primitives/core/src/u32_trait.rs b/primitives/core/src/u32_trait.rs index 975b4aa90990e7ea4c80cd31e5b4a438fdd2d628..6f73e1f6ba7190e9274dfb6958002917faab92d3 100644 --- a/primitives/core/src/u32_trait.rs +++ b/primitives/core/src/u32_trait.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! An u32 trait with "values" as impl'd types. diff --git a/primitives/core/src/uint.rs b/primitives/core/src/uint.rs index e666137c08161d897707def5fadde55a9d2f1abe..ef1adc4a0e0ee7fa2ac30d0f3f5a3bc70ece1c82 100644 --- a/primitives/core/src/uint.rs +++ b/primitives/core/src/uint.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! An unsigned fixed-size integer. diff --git a/primitives/database/Cargo.toml b/primitives/database/Cargo.toml index 2ab86de61d65f12c597ce9db46e23f06b0b71ed2..1899ec850d3123d466b60c21d5fcd7db6c889da0 100644 --- a/primitives/database/Cargo.toml +++ b/primitives/database/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-database" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate database trait." @@ -11,4 +11,4 @@ documentation = "https://docs.rs/sp-database" [dependencies] parking_lot = "0.10.0" -kvdb = "0.5.0" +kvdb = "0.6.0" diff --git a/primitives/database/src/kvdb.rs b/primitives/database/src/kvdb.rs index 85a324b5c105f757e9c264b7b9a696ac612faefb..e05320deed920688f7f1c5752eab49c5e469c2ad 100644 --- a/primitives/database/src/kvdb.rs +++ b/primitives/database/src/kvdb.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. /// A wrapper around `kvdb::Database` that implements `sp_database::Database` trait diff --git a/primitives/database/src/lib.rs b/primitives/database/src/lib.rs index bd9bd2eb54c28c9189891e06689723f86284062e..bc4c11f60a98d3a6e0a1a2b663bd6847aa82c1c4 100644 --- a/primitives/database/src/lib.rs +++ b/primitives/database/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The main database trait, allowing Substrate to store data persistently. diff --git a/primitives/database/src/mem.rs b/primitives/database/src/mem.rs index 09d6149bed174b9225d31ca53fc24a59893c8171..cbfc4f31d9ff2531238ad03b299b77c43c899796 100644 --- a/primitives/database/src/mem.rs +++ b/primitives/database/src/mem.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! In-memory implementation of `Database` diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml index a3e9d91fd2825dbe70da48ee2e4b78e6a549e267..92ba01b23c0734c56888d58cc9050bdfafbf9178 100644 --- a/primitives/debug-derive/Cargo.toml +++ b/primitives/debug-derive/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-debug-derive" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Macros to derive runtime debug implementation." diff --git a/primitives/debug-derive/src/impls.rs b/primitives/debug-derive/src/impls.rs index b0e6dfa3eec4b9790901eef8b6dce5696250b622..1757b294d9d490191b968e4d5d0a5440d198f04f 100644 --- a/primitives/debug-derive/src/impls.rs +++ b/primitives/debug-derive/src/impls.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use quote::quote; use proc_macro2::TokenStream; diff --git a/primitives/debug-derive/src/lib.rs b/primitives/debug-derive/src/lib.rs index 68bbb94e1b006bba81ccead4a7fefb72f9b2354e..db370f890810dedcc78a9bbba19f7b23fb59412f 100644 --- a/primitives/debug-derive/src/lib.rs +++ b/primitives/debug-derive/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Macros to derive runtime debug implementation. //! diff --git a/primitives/debug-derive/tests/tests.rs b/primitives/debug-derive/tests/tests.rs index 77b3d53a2d4ad0189d58e22afbaa8455d07458ec..6a03762b1c65535462d96fc58e793886f1949369 100644 --- a/primitives/debug-derive/tests/tests.rs +++ b/primitives/debug-derive/tests/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use sp_debug_derive::RuntimeDebug; diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index 9d7cd1df6b7fe5f652feec480fe25fd3346b416f..589c8e625c3d1a15b70455c46e86411937367942 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sp-externalities" -version = "0.8.0-dev" -license = "GPL-3.0" +version = "0.8.0-rc2" +license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" @@ -13,7 +13,7 @@ documentation = "https://docs.rs/sp-externalities" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-storage = { version = "2.0.0-dev", path = "../storage" } -sp-std = { version = "2.0.0-dev", path = "../std" } +sp-storage = { version = "2.0.0-rc2", path = "../storage" } +sp-std = { version = "2.0.0-rc2", path = "../std" } environmental = { version = "1.1.1" } codec = { package = "parity-scale-codec", version = "1.3.0" } diff --git a/primitives/externalities/src/extensions.rs b/primitives/externalities/src/extensions.rs index f38f256bb9e68456d14da43c80ed24eefeeabb0f..c75877e67db96c9bd553033e1cf7c463a3f2f663 100644 --- a/primitives/externalities/src/extensions.rs +++ b/primitives/externalities/src/extensions.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Externalities extensions storage. //! diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index 2b584b512e4993b363127124f2866cfcb7b1565d..cfb1d0878a4919ca5dd048e2910d56362410d129 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate externalities abstraction //! diff --git a/primitives/externalities/src/scope_limited.rs b/primitives/externalities/src/scope_limited.rs index 263858aa5f5ced3b3c16dfbadf3a701737823d26..1f70276f02d36658edf58a4bf873c045f7891b4a 100644 --- a/primitives/externalities/src/scope_limited.rs +++ b/primitives/externalities/src/scope_limited.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Stores the externalities in an `environmental` value to make it scope limited available. diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 378f715eccae9eb356877b73212d9f83e2eec54c..83bfca378d3f803d965092350735e70a88828847 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-finality-grandpa" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Primitives for GRANDPA integration, suitable for WASM compilation." @@ -14,15 +14,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../application-crypto" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../application-crypto" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -grandpa = { package = "finality-grandpa", version = "0.12.2", default-features = false, features = ["derive-codec"] } +grandpa = { package = "finality-grandpa", version = "0.12.3", default-features = false, features = ["derive-codec"] } log = { version = "0.4.8", optional = true } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-api = { version = "2.0.0-dev", default-features = false, path = "../api" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../core" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../runtime" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../api" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../core" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../runtime" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } [features] default = ["std"] diff --git a/primitives/finality-grandpa/src/lib.rs b/primitives/finality-grandpa/src/lib.rs index a84ce57c8d1f6ec3f91e797674e8e7472f368102..2e81c8cecbb708f952ae0dff7b5bd24c1a7e3995 100644 --- a/primitives/finality-grandpa/src/lib.rs +++ b/primitives/finality-grandpa/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Primitives for GRANDPA integration, suitable for WASM compilation. @@ -352,21 +353,11 @@ where H: Encode, N: Encode, { - localized_payload_with_buffer(round, set_id, message, buf); + use sp_application_crypto::RuntimeAppPublic; - #[cfg(not(feature = "std"))] - let verify = || { - use sp_application_crypto::RuntimeAppPublic; - id.verify(&buf, signature) - }; - - #[cfg(feature = "std")] - let verify = || { - use sp_application_crypto::Pair; - AuthorityPair::verify(signature, &buf, &id) - }; + localized_payload_with_buffer(round, set_id, message, buf); - if verify() { + if id.verify(&buf, signature) { Ok(()) } else { #[cfg(feature = "std")] @@ -501,7 +492,10 @@ sp_api::decl_runtime_apis! { /// provide the equivocation proof and a key ownership proof (should be /// obtained using `generate_key_ownership_proof`). This method will /// sign the extrinsic with any reporting keys available in the keystore - /// and will push the transaction to the pool. + /// and will push the transaction to the pool. This method returns `None` + /// when creation of the extrinsic fails, either due to unavailability + /// of keys to sign, or because equivocation reporting is disabled for + /// the given runtime (i.e. this method is hardcoded to return `None`). /// Only useful in an offchain context. fn submit_report_equivocation_extrinsic( equivocation_proof: EquivocationProof>, diff --git a/primitives/finality-tracker/Cargo.toml b/primitives/finality-tracker/Cargo.toml index a111c6267526aeaabc29a019364a793356d65376..2f9e377f6b6e1fb1defc07c6ab597248d0beeb95 100644 --- a/primitives/finality-tracker/Cargo.toml +++ b/primitives/finality-tracker/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-finality-tracker" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "FRAME module that tracks the last finalized block, as perceived by block authors." @@ -13,8 +13,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../../primitives/inherents" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../primitives/std" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } [features] default = ["std"] diff --git a/primitives/finality-tracker/src/lib.rs b/primitives/finality-tracker/src/lib.rs index a7157139dc1050699682824ae2763a76b01dec7b..fea40039056068a04f2f40054b7255763be8b7a5 100644 --- a/primitives/finality-tracker/src/lib.rs +++ b/primitives/finality-tracker/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! FRAME module that tracks the last finalized block, as perceived by block authors. diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml index 084d275882a197afb829eb05cd02f956860f7390..367782ae5be44ea0e8a4858b511d2d36229685c1 100644 --- a/primitives/inherents/Cargo.toml +++ b/primitives/inherents/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-inherents" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Provides types and traits for creating and checking inherents." @@ -15,8 +15,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] parking_lot = { version = "0.10.0", optional = true } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../core" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } derive_more = { version = "0.99.2", optional = true } diff --git a/primitives/inherents/src/lib.rs b/primitives/inherents/src/lib.rs index e63382cdf2e4622b76b08c88dcae0b87c867ed97..98942969535285081b7bb42774867c566dbfd830 100644 --- a/primitives/inherents/src/lib.rs +++ b/primitives/inherents/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides types and traits for creating and checking inherents. //! diff --git a/primitives/io/Cargo.toml b/primitives/io/Cargo.toml index 93c8cc9d38b40cc4d1404f97874a9642daca628d..6189194eded34caa87892d3f781fd3fa97b05b23 100644 --- a/primitives/io/Cargo.toml +++ b/primitives/io/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-io" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "I/O for Substrate runtimes" @@ -16,14 +16,14 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../core" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../core" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } libsecp256k1 = { version = "0.3.4", optional = true } -sp-state-machine = { version = "0.8.0-dev", optional = true, path = "../../primitives/state-machine" } -sp-wasm-interface = { version = "2.0.0-dev", path = "../../primitives/wasm-interface", default-features = false } -sp-runtime-interface = { version = "2.0.0-dev", default-features = false, path = "../runtime-interface" } -sp-trie = { version = "2.0.0-dev", optional = true, path = "../../primitives/trie" } -sp-externalities = { version = "0.8.0-dev", optional = true, path = "../externalities" } +sp-state-machine = { version = "0.8.0-rc2", optional = true, path = "../../primitives/state-machine" } +sp-wasm-interface = { version = "2.0.0-rc2", path = "../../primitives/wasm-interface", default-features = false } +sp-runtime-interface = { version = "2.0.0-rc2", default-features = false, path = "../runtime-interface" } +sp-trie = { version = "2.0.0-rc2", optional = true, path = "../../primitives/trie" } +sp-externalities = { version = "0.8.0-rc2", optional = true, path = "../externalities" } log = { version = "0.4.8", optional = true } futures = { version = "0.3.1", features = ["thread-pool"], optional = true } parking_lot = { version = "0.10.0", optional = true } diff --git a/primitives/io/src/batch_verifier.rs b/primitives/io/src/batch_verifier.rs index ab2ee629d326db329a24667557a06631994ec576..6a78070b38b55bdc97c4bd3f9304b52d1797ed5f 100644 --- a/primitives/io/src/batch_verifier.rs +++ b/primitives/io/src/batch_verifier.rs @@ -1,22 +1,23 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Batch/parallel verification. -use sp_core::{ed25519, sr25519, crypto::Pair, traits::CloneableSpawn}; +use sp_core::{ed25519, sr25519, ecdsa, crypto::Pair, traits::CloneableSpawn}; use std::sync::{Arc, atomic::{AtomicBool, Ordering as AtomicOrdering}}; use futures::{future::FutureExt, task::FutureObj, channel::oneshot}; @@ -123,6 +124,29 @@ impl BatchVerifier { true } + /// Push ecdsa signature to verify. + /// + /// Returns false if some of the pushed signatures before already failed the check + /// (in this case it won't verify anything else) + pub fn push_ecdsa( + &mut self, + signature: ecdsa::Signature, + pub_key: ecdsa::Public, + message: Vec, + ) -> bool { + if self.invalid.load(AtomicOrdering::Relaxed) { return false; } + + if self.spawn_verification_task(move || ecdsa::Pair::verify(&signature, &message, &pub_key)).is_err() { + log::debug!( + target: "runtime", + "Batch-verification returns false because failed to spawn background task.", + ); + + return false; + } + true + } + fn verify_sr25519_batch(items: Vec) -> bool { let messages = items.iter().map(|item| &item.message[..]).collect(); let signatures = items.iter().map(|item| &item.signature).collect(); diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index f5d692469f0a8a6eb9a76106c9d3e5424804866c..8d81a84c4c88ad99d000ad24053a36dafc6e546f 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! I/O host interface for substrate runtime. @@ -41,7 +42,7 @@ use sp_core::{ }; use sp_core::{ - crypto::KeyTypeId, ed25519, sr25519, H256, LogLevel, + crypto::KeyTypeId, ed25519, sr25519, ecdsa, H256, LogLevel, offchain::{ Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, }, @@ -299,6 +300,16 @@ pub trait Trie { fn blake2_256_ordered_root(input: Vec>) -> H256 { Layout::::ordered_trie_root(input) } + + /// A trie root formed from the iterated items. + fn keccak_256_root(input: Vec<(Vec, Vec)>) -> H256 { + Layout::::trie_root(input) + } + + /// A trie root formed from the enumerated items. + fn keccak_256_ordered_root(input: Vec>) -> H256 { + Layout::::ordered_trie_root(input) + } } /// Interface that provides miscellaneous functions for communicating between the runtime and the node. @@ -544,6 +555,80 @@ pub trait Crypto { sr25519::Pair::verify_deprecated(sig, msg, pubkey) } + /// Returns all `ecdsa` public keys for the given key id from the keystore. + fn ecdsa_public_keys(&mut self, id: KeyTypeId) -> Vec { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .ecdsa_public_keys(id) + } + + /// Generate an `ecdsa` key for the given key type using an optional `seed` and + /// store it in the keystore. + /// + /// The `seed` needs to be a valid utf8. + /// + /// Returns the public key. + fn ecdsa_generate(&mut self, id: KeyTypeId, seed: Option>) -> ecdsa::Public { + let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!")); + self.extension::() + .expect("No `keystore` associated for the current context!") + .write() + .ecdsa_generate_new(id, seed) + .expect("`ecdsa_generate` failed") + } + + /// Sign the given `msg` with the `ecdsa` key that corresponds to the given public key and + /// key type in the keystore. + /// + /// Returns the signature. + fn ecdsa_sign( + &mut self, + id: KeyTypeId, + pub_key: &ecdsa::Public, + msg: &[u8], + ) -> Option { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .sign_with(id, &pub_key.into(), msg) + .map(|sig| ecdsa::Signature::from_slice(sig.as_slice())) + .ok() + } + + /// Verify `ecdsa` signature. + /// + /// Returns `true` when the verification is either successful or batched. + /// If no batching verification extension registered, this will return the result + /// of verification immediately. If batching verification extension is registered + /// caller should call `crypto::finish_batch_verify` to actualy check all submitted + /// signatures. + fn ecdsa_verify( + sig: &ecdsa::Signature, + msg: &[u8], + pub_key: &ecdsa::Public, + ) -> bool { + // TODO: see #5554, this is used outside of externalities context/runtime, thus this manual + // `with_externalities`. + // + // This `with_externalities(..)` block returns Some(Some(result)) if signature verification was successfully + // batched, everything else (Some(None)/None) means it was not batched and needs to be verified. + let evaluated = sp_externalities::with_externalities(|mut instance| + instance.extension::().map( + |extension| extension.push_ecdsa( + sig.clone(), + pub_key.clone(), + msg.to_vec(), + ) + ) + ); + + match evaluated { + Some(Some(val)) => val, + _ => ecdsa::Pair::verify(sig, msg, pub_key), + } + } + /// Verify and recover a SECP256k1 ECDSA signature. /// /// - `sig` is passed in RSV format. V should be either `0/1` or `27/28`. @@ -711,6 +796,16 @@ pub trait Offchain { .local_storage_set(kind, key, value) } + /// Remove a value from the local storage. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_clear(&mut self, kind: StorageKind, key: &[u8]) { + self.extension::() + .expect("local_storage_clear can be called only in the offchain worker context") + .local_storage_clear(kind, key) + } + /// Sets a value in the local storage if it matches current value. /// /// Since multiple offchain workers may be running concurrently, to prevent diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml index 23e243239a553322b75878422f3c8e22d8e9ce29..ead618e3fc96e83d121d02b6de0350427ec328fe 100644 --- a/primitives/keyring/Cargo.toml +++ b/primitives/keyring/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-keyring" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Keyring support code for the runtime. A set of test accounts." @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "2.0.0-dev", path = "../core" } -sp-runtime = { version = "2.0.0-dev", path = "../runtime" } +sp-core = { version = "2.0.0-rc2", path = "../core" } +sp-runtime = { version = "2.0.0-rc2", path = "../runtime" } lazy_static = "1.4.0" strum = { version = "0.16.0", features = ["derive"] } diff --git a/primitives/keyring/src/ed25519.rs b/primitives/keyring/src/ed25519.rs index 197b9ded8794b2cc93418af09572c2d0dae9e24f..17882027387c538e4ab4b9a96312ba32488984d5 100644 --- a/primitives/keyring/src/ed25519.rs +++ b/primitives/keyring/src/ed25519.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Support code for the runtime. A set of test accounts. diff --git a/primitives/keyring/src/lib.rs b/primitives/keyring/src/lib.rs index 18f8cdf2c4ab9c8ce8e97e9f1dfe6a315460a7dc..55ed14d294f1dc7cb82d8e516d14bbca4c08f03b 100644 --- a/primitives/keyring/src/lib.rs +++ b/primitives/keyring/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Support code for the runtime. A set of test accounts. diff --git a/primitives/keyring/src/sr25519.rs b/primitives/keyring/src/sr25519.rs index 476997f2db79b00b79b3214bd8f20f6d49898ffb..80397f0de9fc12d42eae2776b484651954270a90 100644 --- a/primitives/keyring/src/sr25519.rs +++ b/primitives/keyring/src/sr25519.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Support code for the runtime. A set of test accounts. diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml index ebd0fa12d41dc73c7969d8f398885fddb022a541..2f7246121afd8926e01c9f5618fce3716c4d27e8 100644 --- a/primitives/offchain/Cargo.toml +++ b/primitives/offchain/Cargo.toml @@ -1,8 +1,8 @@ [package] description = "Substrate offchain workers primitives" name = "sp-offchain" -version = "2.0.0-dev" -license = "GPL-3.0" +version = "2.0.0-rc2" +license = "Apache-2.0" authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" @@ -12,12 +12,12 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-core = { version = "2.0.0-dev", default-features = false, path = "../core" } -sp-api = { version = "2.0.0-dev", default-features = false, path = "../api" } -sp-runtime = { version = "2.0.0-dev", default-features = false, path = "../runtime" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../core" } +sp-api = { version = "2.0.0-rc2", default-features = false, path = "../api" } +sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../runtime" } [dev-dependencies] -sp-state-machine = { version = "0.8.0-dev", default-features = false, path = "../state-machine" } +sp-state-machine = { version = "0.8.0-rc2", default-features = false, path = "../state-machine" } [features] default = ["std"] diff --git a/primitives/offchain/src/lib.rs b/primitives/offchain/src/lib.rs index 8f043d712a8404ebecfec138210fd72490303fea..fa5ab808df8a107f7033ccb73aa0a92b832e15fb 100644 --- a/primitives/offchain/src/lib.rs +++ b/primitives/offchain/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2018-2020 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 . +// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! The Offchain Worker runtime api primitives. diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml index b5adb9cb5483fd32b13840a23377aa52a1ad7bce..75042799b1b5238b18e52c2475df487e7a1743a7 100644 --- a/primitives/panic-handler/Cargo.toml +++ b/primitives/panic-handler/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-panic-handler" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Custom panic hook with bug report link" diff --git a/primitives/panic-handler/src/lib.rs b/primitives/panic-handler/src/lib.rs index c0f70d9d145c893dc38700e362c224a132cff808..7b6787683e6f6f54d491ec1a5c9fe7b9147df6c0 100644 --- a/primitives/panic-handler/src/lib.rs +++ b/primitives/panic-handler/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Custom panic hook with bug report link //! diff --git a/primitives/phragmen/Cargo.toml b/primitives/phragmen/Cargo.toml index 29fc0ed41e40878bfd6981efb0ae551d7a28ab05..d2b8e56dc0dbb6ad991d384c5344559b4b63567b 100644 --- a/primitives/phragmen/Cargo.toml +++ b/primitives/phragmen/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-phragmen" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Phragmen primitives" @@ -14,15 +14,15 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } -sp-phragmen-compact = { version = "2.0.0-dev", path = "./compact" } -sp-arithmetic = { version = "2.0.0-dev", default-features = false, path = "../arithmetic" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } +sp-phragmen-compact = { version = "2.0.0-rc2", path = "./compact" } +sp-arithmetic = { version = "2.0.0-rc2", default-features = false, path = "../arithmetic" } [dev-dependencies] -substrate-test-utils = { version = "2.0.0-dev", path = "../../test-utils" } +substrate-test-utils = { version = "2.0.0-rc2", path = "../../test-utils" } rand = "0.7.3" -sp-phragmen = { version = "2.0.0-dev", path = "." } -sp-runtime = { version = "2.0.0-dev", path = "../../primitives/runtime" } +sp-phragmen = { version = "2.0.0-rc2", path = "." } +sp-runtime = { version = "2.0.0-rc2", path = "../../primitives/runtime" } [features] default = ["std"] diff --git a/primitives/phragmen/benches/phragmen.rs b/primitives/phragmen/benches/phragmen.rs index e274586f601d5588ddeeedf2e88c8149c473bd7c..c01d9f400d69d2162bf92c1b416a0d0cd4d6f463 100644 --- a/primitives/phragmen/benches/phragmen.rs +++ b/primitives/phragmen/benches/phragmen.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. + //! Benchmarks of the phragmen election algorithm. //! Note that execution times will not be accurate in an absolute scale, since //! - Everything is executed in the context of `TestExternalities` diff --git a/primitives/phragmen/compact/Cargo.toml b/primitives/phragmen/compact/Cargo.toml index 386116f2683ae9998e5b02e70477065f903cfd59..8fb9789d99c54b003571fa19a681343e8217a463 100644 --- a/primitives/phragmen/compact/Cargo.toml +++ b/primitives/phragmen/compact/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-phragmen-compact" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Phragmen Compact Solution" diff --git a/primitives/phragmen/compact/src/assignment.rs b/primitives/phragmen/compact/src/assignment.rs index 4630a494fc77562dfd4aab6bbc8bf83ca75bd961..a48cbd937913b78bf470ed69616323c60ee7e248 100644 --- a/primitives/phragmen/compact/src/assignment.rs +++ b/primitives/phragmen/compact/src/assignment.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Code generation for the ratio assignment type. diff --git a/primitives/phragmen/compact/src/lib.rs b/primitives/phragmen/compact/src/lib.rs index 9406f944c396ebd170f9e393d7383de878ac69aa..735e0abaa66cd38d3a0060def5ddfc8b339e1a92 100644 --- a/primitives/phragmen/compact/src/lib.rs +++ b/primitives/phragmen/compact/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Proc macro for phragmen compact assignment. @@ -157,6 +158,23 @@ fn struct_def( ) }).collect::(); + + let len_impl = (1..=count).map(|c| { + let field_name = field_name_for(c); + quote!( + all_len = all_len.saturating_add(self.#field_name.len()); + ) + }).collect::(); + + let edge_count_impl = (1..count).map(|c| { + let field_name = field_name_for(c); + quote!( + all_edges = all_edges.saturating_add( + self.#field_name.len().saturating_mul(#c as usize) + ); + ) + }).collect::(); + Ok(quote! ( /// A struct to encode a Phragmen assignment in a compact way. #[derive( @@ -180,6 +198,28 @@ fn struct_def( { const LIMIT: usize = #count; } + + impl<#voter_type, #target_type, #weight_type> #ident<#voter_type, #target_type, #weight_type> { + /// Get the length of all the assignments that this type is encoding. This is basically + /// the same as the number of assignments, or the number of voters in total. + pub fn len(&self) -> usize { + let mut all_len = 0usize; + #len_impl + all_len + } + + /// Get the total count of edges. + pub fn edge_count(&self) -> usize { + let mut all_edges = 0usize; + #edge_count_impl + all_edges + } + + /// Get the average edge count. + pub fn average_edge_count(&self) -> usize { + self.edge_count().checked_div(self.len()).unwrap_or(0) + } + } )) } diff --git a/primitives/phragmen/compact/src/staked.rs b/primitives/phragmen/compact/src/staked.rs index 81ccb5c55927c5633a07feccad842c4c3119a4e6..cb1675219580a478f6bbdbb500d5f9cb6e990853 100644 --- a/primitives/phragmen/compact/src/staked.rs +++ b/primitives/phragmen/compact/src/staked.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Code generation for the staked assignment type. diff --git a/primitives/phragmen/fuzzer/Cargo.lock b/primitives/phragmen/fuzzer/Cargo.lock index 3ef2a2732424a3ddd412192dc01ac0647c36ffe1..a57bfa39206fc2c70eea5512a1acfa099d77e973 100644 --- a/primitives/phragmen/fuzzer/Cargo.lock +++ b/primitives/phragmen/fuzzer/Cargo.lock @@ -540,7 +540,7 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "198831fe8722331a395bc199a5d08efbc197497ef354cb4c77b969c02ffc0fc4" dependencies = [ @@ -1247,7 +1247,7 @@ dependencies = [ [[package]] name = "sp-phragmen-compact" -version = "2.0.0-dev" +version = "2.0.0-rc2" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/primitives/phragmen/fuzzer/Cargo.toml b/primitives/phragmen/fuzzer/Cargo.toml index 7f7aef1961d518864759cd7b1a4b745ed9d9c378..2846841e1c11b0fe965150274adc047501ccd650 100644 --- a/primitives/phragmen/fuzzer/Cargo.toml +++ b/primitives/phragmen/fuzzer/Cargo.toml @@ -3,7 +3,7 @@ name = "sp-phragmen-fuzzer" version = "2.0.0-alpha.5" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Fuzzer for phragmén implementation." @@ -14,9 +14,9 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-phragmen = { version = "2.0.0-dev", path = ".." } -sp-std = { version = "2.0.0-dev", path = "../../std" } -sp-runtime = { version = "2.0.0-dev", path = "../../runtime" } +sp-phragmen = { version = "2.0.0-rc2", path = ".." } +sp-std = { version = "2.0.0-rc2", path = "../../std" } +sp-runtime = { version = "2.0.0-rc2", path = "../../runtime" } honggfuzz = "0.5" rand = { version = "0.7.3", features = ["std", "small_rng"] } diff --git a/primitives/phragmen/fuzzer/src/common.rs b/primitives/phragmen/fuzzer/src/common.rs index 3429dcb20adde2e260d66cf9be76df9f0420ec39..f1aab214de6ba96a4de688109ebda1360137071a 100644 --- a/primitives/phragmen/fuzzer/src/common.rs +++ b/primitives/phragmen/fuzzer/src/common.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Common fuzzing utils. diff --git a/primitives/phragmen/fuzzer/src/equalize.rs b/primitives/phragmen/fuzzer/src/equalize.rs index cb4f98c4eb15284be7de03bbbefa90b5d027e82c..8ca417f269886e0ba8f9510d35dbb29c4ffbc421 100644 --- a/primitives/phragmen/fuzzer/src/equalize.rs +++ b/primitives/phragmen/fuzzer/src/equalize.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Fuzzing fro the equalize algorithm //! diff --git a/primitives/phragmen/fuzzer/src/reduce.rs b/primitives/phragmen/fuzzer/src/reduce.rs index f0a16466636e3fe6e271ea039113c59d46345b4d..7ac15dd5443b2d12ca5586277ba7d9f6fcab661d 100644 --- a/primitives/phragmen/fuzzer/src/reduce.rs +++ b/primitives/phragmen/fuzzer/src/reduce.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Fuzzing for the reduce algorithm. //! diff --git a/primitives/phragmen/src/helpers.rs b/primitives/phragmen/src/helpers.rs index 6b1497e3ad752e5c428ad3b0544913af95cd4d53..2674bc445de375bd771d619103c18bf86ae1b4e6 100644 --- a/primitives/phragmen/src/helpers.rs +++ b/primitives/phragmen/src/helpers.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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. +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Helper methods for phragmen. diff --git a/primitives/phragmen/src/lib.rs b/primitives/phragmen/src/lib.rs index 9aaa96150ff7471a56cfaed0137c1ad1df2483d0..03bbb279d8f987d92a37bd130c5c6113faa039df 100644 --- a/primitives/phragmen/src/lib.rs +++ b/primitives/phragmen/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Rust implementation of the Phragmén election algorithm. This is used in several pallets to //! optimally distribute the weight of a set of voters among an elected set of candidates. In the diff --git a/primitives/phragmen/src/mock.rs b/primitives/phragmen/src/mock.rs index cf9c90334bc588bb21855e1ed346ec99a3d1fe95..fb801125158bc1dc0f6a19d965cc91eb20b0f561 100644 --- a/primitives/phragmen/src/mock.rs +++ b/primitives/phragmen/src/mock.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Mock file for phragmen. diff --git a/primitives/phragmen/src/node.rs b/primitives/phragmen/src/node.rs index 432c537052ebb5c3e9c5921233554f545cc50ffa..d18c0e9016b64450606a2c2320d317770c5586f9 100644 --- a/primitives/phragmen/src/node.rs +++ b/primitives/phragmen/src/node.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! (very) Basic implementation of a graph node used in the reduce algorithm. diff --git a/primitives/phragmen/src/reduce.rs b/primitives/phragmen/src/reduce.rs index 7153a9383c341437b7537bea892542344319b330..2878aa78c45d92c8cfce53117727021e94f2e91e 100644 --- a/primitives/phragmen/src/reduce.rs +++ b/primitives/phragmen/src/reduce.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Rust implementation of the Phragmén reduce algorithm. This can be used by any off chain //! application to reduce cycles from the edge assignment, which will result in smaller size. diff --git a/primitives/phragmen/src/tests.rs b/primitives/phragmen/src/tests.rs index 720a0a3f7524a754d4bd7f4112ff3978b4d436ae..0219c35a8b976f4d98508764ba53de1ed0d1ce62 100644 --- a/primitives/phragmen/src/tests.rs +++ b/primitives/phragmen/src/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for phragmen. @@ -671,6 +672,8 @@ mod compact { compact, Decode::decode(&mut &encoded[..]).unwrap(), ); + assert_eq!(compact.len(), 4); + assert_eq!(compact.edge_count(), 2 + 4); } fn basic_ratio_test_with() where @@ -746,6 +749,13 @@ mod compact { target_index, ).unwrap(); + // basically number of assignments that it is encoding. + assert_eq!(compacted.len(), assignments.len()); + assert_eq!( + compacted.edge_count(), + assignments.iter().fold(0, |a, b| a + b.distribution.len()), + ); + assert_eq!( compacted, TestCompact { @@ -843,6 +853,11 @@ mod compact { voter_index, target_index, ).unwrap(); + assert_eq!(compacted.len(), assignments.len()); + assert_eq!( + compacted.edge_count(), + assignments.iter().fold(0, |a, b| a + b.distribution.len()), + ); assert_eq!( compacted, diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml index 740b429c0c8fb6a30b845da7ae4a7321af8dfe89..a625d4ad716de42b3c9f38a3c5176ec54c27d7ed 100644 --- a/primitives/rpc/Cargo.toml +++ b/primitives/rpc/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-rpc" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate RPC primitives and utilities." @@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", features = ["derive"] } -sp-core = { version = "2.0.0-dev", path = "../core" } +sp-core = { version = "2.0.0-rc2", path = "../core" } [dev-dependencies] serde_json = "1.0.41" diff --git a/primitives/rpc/src/lib.rs b/primitives/rpc/src/lib.rs index 7c22daf5cd94fce09ba1d967de8b99469299d2cf..c479f0df8b60e9acb8755526d6e7a01737920eff 100644 --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate RPC primitives and utilities. diff --git a/primitives/rpc/src/list.rs b/primitives/rpc/src/list.rs index 469eae3d1479aab9412addd006badf70eee44907..a80d5a22272c84e4b220a1110138a7405295bc7a 100644 --- a/primitives/rpc/src/list.rs +++ b/primitives/rpc/src/list.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! RPC a lenient list or value type. diff --git a/primitives/rpc/src/number.rs b/primitives/rpc/src/number.rs index 1d41dd234f7043c80ae2c257e563c41586c0df51..63aa643fb6fca6e323842afe94ade5d3cffc9881 100644 --- a/primitives/rpc/src/number.rs +++ b/primitives/rpc/src/number.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Chain RPC Block number type. diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml index 1d0ae8f95120d1d6157ebf1c3a553a1eefe75b60..a0ff6330146a8b89475cdebb89ba7197c0d76df6 100644 --- a/primitives/runtime-interface/Cargo.toml +++ b/primitives/runtime-interface/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-runtime-interface" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Substrate runtime interface" @@ -13,20 +13,20 @@ documentation = "https://docs.rs/sp-runtime-interface/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-wasm-interface = { version = "2.0.0-dev", path = "../wasm-interface", default-features = false } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } -sp-tracing = { version = "2.0.0-dev", default-features = false, path = "../tracing" } -sp-runtime-interface-proc-macro = { version = "2.0.0-dev", path = "proc-macro" } -sp-externalities = { version = "0.8.0-dev", optional = true, path = "../externalities" } +sp-wasm-interface = { version = "2.0.0-rc2", path = "../wasm-interface", default-features = false } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } +sp-tracing = { version = "2.0.0-rc2", default-features = false, path = "../tracing" } +sp-runtime-interface-proc-macro = { version = "2.0.0-rc2", path = "proc-macro" } +sp-externalities = { version = "0.8.0-rc2", optional = true, path = "../externalities" } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } static_assertions = "1.0.0" primitive-types = { version = "0.7.0", default-features = false } [dev-dependencies] -sp-runtime-interface-test-wasm = { version = "2.0.0-dev", path = "test-wasm" } -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } -sp-core = { version = "2.0.0-dev", path = "../core" } -sp-io = { version = "2.0.0-dev", path = "../io" } +sp-runtime-interface-test-wasm = { version = "2.0.0-rc2", path = "test-wasm" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } +sp-core = { version = "2.0.0-rc2", path = "../core" } +sp-io = { version = "2.0.0-rc2", path = "../io" } rustversion = "1.0.0" trybuild = "1.0.23" diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml index 28fe00cc390dde62b1cef847e9019ec6917a4479..89d8ddf56b10f07f7e6251d4c7775d2e0846ba31 100644 --- a/primitives/runtime-interface/proc-macro/Cargo.toml +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-runtime-interface-proc-macro" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "This crate provides procedural macros for usage within the context of the Substrate runtime interface." diff --git a/primitives/runtime-interface/proc-macro/src/lib.rs b/primitives/runtime-interface/proc-macro/src/lib.rs index 2ed8b1a2281b727ca7e9333272111d81dfb8591f..2f5b9de1c14e7da9dd07113cfe71facb6d97f776 100644 --- a/primitives/runtime-interface/proc-macro/src/lib.rs +++ b/primitives/runtime-interface/proc-macro/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! This crate provides procedural macros for usage within the context of the Substrate runtime //! interface. diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs b/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs index 5e30870a82d2e7831a43a454451fbe68e5926dc4..5e51440938456b41628ca89a6736970e6e51b65d 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Derive macro implementation of `PassBy` with the associated type set to `Codec`. //! diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs index 5d5b3ae43bdf5f0014c4355914b544c7d3529727..35ed9c0cb802f6ce105c8f18caf23957c4e9d3cb 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Derive macro implementation of `PassBy` with the associated type set to `Enum`. //! diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs b/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs index 2e1caaa96c61fa4c2f501a7c8efcc9fe924e877e..cf3bb965d0743b04be7367416b43773fc0c2beee 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Derive macro implementation of `PassBy` with the associated type set to `Inner` and of the //! helper trait `PassByInner`. diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs b/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs index 1466af598ea7cafac655f0efd0034b1d9e7b017a..ff5ea4849af77cb650d5f2ec0535441a7ead395a 100644 --- a/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs +++ b/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! All the `PassBy*` derive implementations. diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs index 8e83556f045085a887cbc4a68838a8988f23045f..6760e9656113a9e8b3cfd0e7246a514ce915a477 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generates the bare function interface for a given trait definition. //! diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs index 46de98c3c3f706ea30f3ca4f95ed5f7ab53d9f32..721eed649c25d5d0244615194f185b672c2bd1e3 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generates the extern host functions and the implementation for these host functions. //! diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs index 1c88198d6ea44fa04a5bc11878f8fa8d0b075833..c9b6edf68fd5a48ec9f56200b3b2154c267baebe 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use crate::utils::generate_runtime_interface_include; diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs index 542c4ca4b8c37b3519a4bb103897c80d83145b4d..70015d02426d4de85be697f303873ed756dbb246 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Checks the trait declaration, makes the trait declaration module local, removes all method //! default implementations and implements the trait for `&mut dyn Externalities`. diff --git a/primitives/runtime-interface/src/host.rs b/primitives/runtime-interface/src/host.rs index cf03e6623af591ac39966e0808913223c42dd7bd..4a01291e68455dc74a16040c31992dd818d64764 100644 --- a/primitives/runtime-interface/src/host.rs +++ b/primitives/runtime-interface/src/host.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Traits required by the runtime interface from the host side. diff --git a/primitives/runtime-interface/src/impls.rs b/primitives/runtime-interface/src/impls.rs index 084b5e11eb3b128c61aae7eefe7bc9baabe71413..217316c3dd79c9f5060d07f2d636b6f11b013492 100644 --- a/primitives/runtime-interface/src/impls.rs +++ b/primitives/runtime-interface/src/impls.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides implementations for the runtime interface traits. diff --git a/primitives/runtime-interface/src/lib.rs b/primitives/runtime-interface/src/lib.rs index 4f748825e5bc1d889bf2eaa024516d0ce722a632..562f94b278efcc60fd21b754dfcf4e1e65f88ab3 100644 --- a/primitives/runtime-interface/src/lib.rs +++ b/primitives/runtime-interface/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Substrate runtime interface //! diff --git a/primitives/runtime-interface/src/pass_by.rs b/primitives/runtime-interface/src/pass_by.rs index d6767b5ebbe93dfb131c13564b4f900d6bdca0bd..5ccb3a5e96ee1168ea2cdb73a2d92b6bc3bb376a 100644 --- a/primitives/runtime-interface/src/pass_by.rs +++ b/primitives/runtime-interface/src/pass_by.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides the [`PassBy`](PassBy) trait to simplify the implementation of the //! runtime interface traits for custom types. diff --git a/primitives/runtime-interface/src/util.rs b/primitives/runtime-interface/src/util.rs index fa7016a2b01a6632632e7b11ea618763e04b0381..604e37e8be3976c369bae2f82173f3fb484f914c 100644 --- a/primitives/runtime-interface/src/util.rs +++ b/primitives/runtime-interface/src/util.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Various utilities that help interfacing with wasm runtime code. diff --git a/primitives/runtime-interface/src/wasm.rs b/primitives/runtime-interface/src/wasm.rs index a0801c2bfb5a9aca7c937ef276306428f44630e0..5511f60e30d214e9473088ce58c4573dc83264f9 100644 --- a/primitives/runtime-interface/src/wasm.rs +++ b/primitives/runtime-interface/src/wasm.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Traits required by the runtime interface from the wasm side. diff --git a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml index f992cad69b0f8df53a9cace9db3be21044637907..43a1f8baa93b3165a00f339eb7e72b4a1c85f471 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml +++ b/primitives/runtime-interface/test-wasm-deprecated/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-runtime-interface-test-wasm-deprecated" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = false @@ -13,10 +13,10 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "2.0.0-dev", default-features = false, path = "../" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../io" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../core" } +sp-runtime-interface = { version = "2.0.0-rc2", default-features = false, path = "../" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../io" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../core" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } diff --git a/primitives/runtime-interface/test-wasm-deprecated/build.rs b/primitives/runtime-interface/test-wasm-deprecated/build.rs index 647b4768141d2203155bf5325f9ff87f7d9c2446..a4f323566006cf7c003cec2e413e1d23ecffead1 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/build.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/build.rs @@ -1,25 +1,26 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs b/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs index 29d28c75faafb9b4864479568c819e9bc3178477..ad005bfb5f8b980425e7b07d45d900c5241ad93d 100644 --- a/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs +++ b/primitives/runtime-interface/test-wasm-deprecated/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the runtime interface traits and proc macros. diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml index f9e64a5027a68a7befd47b4cd58523411187266f..3f99e157ec70b48064c25e07daca30d463986213 100644 --- a/primitives/runtime-interface/test-wasm/Cargo.toml +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "sp-runtime-interface-test-wasm" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" build = "build.rs" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" publish = false @@ -13,10 +13,10 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "2.0.0-dev", default-features = false, path = "../" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../../std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../../io" } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../../core" } +sp-runtime-interface = { version = "2.0.0-rc2", default-features = false, path = "../" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../io" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../core" } [build-dependencies] wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } diff --git a/primitives/runtime-interface/test-wasm/build.rs b/primitives/runtime-interface/test-wasm/build.rs index 647b4768141d2203155bf5325f9ff87f7d9c2446..a4f323566006cf7c003cec2e413e1d23ecffead1 100644 --- a/primitives/runtime-interface/test-wasm/build.rs +++ b/primitives/runtime-interface/test-wasm/build.rs @@ -1,25 +1,26 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates_or_path("1.0.9", "../../../utils/wasm-builder") + .with_wasm_builder_from_crates_or_path("1.0.11", "../../../utils/wasm-builder") .export_heap_base() .import_memory() .build() diff --git a/primitives/runtime-interface/test-wasm/src/lib.rs b/primitives/runtime-interface/test-wasm/src/lib.rs index 700c77854a8b3e003c56c1b25d2c0ba904550fd1..90112046fcda4c11e2109c9715ae23469824d129 100644 --- a/primitives/runtime-interface/test-wasm/src/lib.rs +++ b/primitives/runtime-interface/test-wasm/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the runtime interface traits and proc macros. diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml index 03f0122b2200b2e8684d06599b60a1a9a599320f..b281278b5cde41a6d2410e63aef4032dce66a168 100644 --- a/primitives/runtime-interface/test/Cargo.toml +++ b/primitives/runtime-interface/test/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-runtime-interface-test" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" publish = false homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" @@ -12,12 +12,12 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -sp-runtime-interface = { version = "2.0.0-dev", path = "../" } -sc-executor = { version = "0.8.0-dev", path = "../../../client/executor" } -sp-runtime-interface-test-wasm = { version = "2.0.0-dev", path = "../test-wasm" } -sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0-dev", path = "../test-wasm-deprecated" } -sp-state-machine = { version = "0.8.0-dev", path = "../../../primitives/state-machine" } -sp-runtime = { version = "2.0.0-dev", path = "../../runtime" } -sp-core = { version = "2.0.0-dev", path = "../../core" } -sp-io = { version = "2.0.0-dev", path = "../../io" } +sp-runtime-interface = { version = "2.0.0-rc2", path = "../" } +sc-executor = { version = "0.8.0-rc2", path = "../../../client/executor" } +sp-runtime-interface-test-wasm = { version = "2.0.0-rc2", path = "../test-wasm" } +sp-runtime-interface-test-wasm-deprecated = { version = "2.0.0-rc2", path = "../test-wasm-deprecated" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../../primitives/state-machine" } +sp-runtime = { version = "2.0.0-rc2", path = "../../runtime" } +sp-core = { version = "2.0.0-rc2", path = "../../core" } +sp-io = { version = "2.0.0-rc2", path = "../../io" } tracing = "0.1.13" diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index e7ef1934e25d8b644fe201b9ead6b4a6fb13918c..06bc4e8ed8d46951f8e84c0291849062902f933e 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Integration tests for runtime interface primitives #![cfg(test)] @@ -31,7 +32,10 @@ use std::{collections::HashSet, sync::{Arc, Mutex}}; type TestExternalities = sp_state_machine::TestExternalities; -fn call_wasm_method(binary: &[u8], method: &str) -> TestExternalities { +fn call_wasm_method_with_result( + binary: &[u8], + method: &str, +) -> Result { let mut ext = TestExternalities::default(); let mut ext_ext = ext.ext(); let mut host_functions = HF::host_functions(); @@ -50,9 +54,13 @@ fn call_wasm_method(binary: &[u8], method: &str) -> TestExte &[], &mut ext_ext, sp_core::traits::MissingHostFunctions::Disallow, - ).expect(&format!("Executes `{}`", method)); + ).map_err(|e| format!("Failed to execute `{}`: {}", method, e))?; - ext + Ok(ext) +} + +fn call_wasm_method(binary: &[u8], method: &str) -> TestExternalities { + call_wasm_method_with_result::(binary, method).unwrap() } #[test] @@ -94,20 +102,15 @@ fn test_return_input_public_key() { } #[test] -#[should_panic( - expected = "Instantiation: Export ext_test_api_return_input_version_1 not found" -)] fn host_function_not_found() { - call_wasm_method::<()>(&WASM_BINARY[..], "test_return_data"); + let err = call_wasm_method_with_result::<()>(&WASM_BINARY[..], "test_return_data").unwrap_err(); + + assert!(err.contains("Instantiation: Export ")); + assert!(err.contains(" not found")); } #[test] -#[should_panic( - expected = - "Executes `test_invalid_utf8_data_should_return_an_error`: \ - \"Trap: Trap { kind: Host(FunctionExecution(\\\"ext_test_api_invalid_utf8_data_version_1\\\", \ - \\\"Invalid utf8 data provided\\\")) }\"" -)] +#[should_panic(expected = "Invalid utf8 data provided")] fn test_invalid_utf8_data_should_return_an_error() { call_wasm_method::(&WASM_BINARY[..], "test_invalid_utf8_data_should_return_an_error"); } diff --git a/primitives/runtime-interface/tests/ui.rs b/primitives/runtime-interface/tests/ui.rs index 910771f9389691d61b1c84069fdf6090e242f80b..2f7fd6d06bcd34c3724d6fa39422d4f7890392cc 100644 --- a/primitives/runtime-interface/tests/ui.rs +++ b/primitives/runtime-interface/tests/ui.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::env; diff --git a/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr b/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr index 6502a36fc18b7f387b1112b559c455e515411db9..c7ed1af3b1a037bfc657692b60bc166be8452850 100644 --- a/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr +++ b/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr @@ -3,3 +3,5 @@ error: `PassByEnum` only supports enums as input type. | 3 | #[derive(PassByEnum)] | ^^^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr b/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr index 1f03436d4e007fc9fe6cc85a4d2f2b6dd37de4fa..f6c85ed2bba3e24b44cf93ac30c1e7b8d54ba8bd 100644 --- a/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr +++ b/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr @@ -3,3 +3,5 @@ error: `PassByEnum` only supports unit variants. | 3 | #[derive(PassByEnum)] | ^^^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr b/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr index 7f576a69f0e5039a0e058aa385fe5da2879d7710..9afbce76f0c233c3156f0024a8485b32a29aa50c 100644 --- a/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr +++ b/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr @@ -3,3 +3,5 @@ error: Only newtype/one field structs are supported by `PassByInner`! | 3 | #[derive(PassByInner)] | ^^^^^^^^^^^ + | + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index dcb0e2260090ca0a812d8e11bab5a707666c974c..ae30372b65926e5a9d080e23ec8c74ef26258df7 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "sp-runtime" -version = "2.0.0-dev" +version = "2.0.0-rc2" authors = ["Parity Technologies "] edition = "2018" -license = "GPL-3.0" +license = "Apache-2.0" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/substrate/" description = "Runtime Modules shared primitive types." @@ -16,23 +16,23 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } -sp-core = { version = "2.0.0-dev", default-features = false, path = "../core" } -sp-application-crypto = { version = "2.0.0-dev", default-features = false, path = "../application-crypto" } -sp-arithmetic = { version = "2.0.0-dev", default-features = false, path = "../arithmetic" } -sp-std = { version = "2.0.0-dev", default-features = false, path = "../std" } -sp-io = { version = "2.0.0-dev", default-features = false, path = "../io" } +sp-core = { version = "2.0.0-rc2", default-features = false, path = "../core" } +sp-application-crypto = { version = "2.0.0-rc2", default-features = false, path = "../application-crypto" } +sp-arithmetic = { version = "2.0.0-rc2", default-features = false, path = "../arithmetic" } +sp-std = { version = "2.0.0-rc2", default-features = false, path = "../std" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../io" } log = { version = "0.4.8", optional = true } paste = "0.1.6" rand = { version = "0.7.2", optional = true } impl-trait-for-tuples = "0.1.3" -sp-inherents = { version = "2.0.0-dev", default-features = false, path = "../inherents" } +sp-inherents = { version = "2.0.0-rc2", default-features = false, path = "../inherents" } parity-util-mem = { version = "0.6.1", default-features = false, features = ["primitive-types"] } hash256-std-hasher = { version = "0.15.2", default-features = false } [dev-dependencies] serde_json = "1.0.41" rand = "0.7.2" -sp-state-machine = { version = "0.8.0-dev", path = "../../primitives/state-machine" } +sp-state-machine = { version = "0.8.0-rc2", path = "../../primitives/state-machine" } [features] bench = [] diff --git a/primitives/runtime/src/curve.rs b/primitives/runtime/src/curve.rs index b00cbed6525a16cf6f1db35eed8f5b6e225437f3..be47b566e93c0c27e91826abb4f2af1a5af604bc 100644 --- a/primitives/runtime/src/curve.rs +++ b/primitives/runtime/src/curve.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Provides some utilities to define a piecewise linear function. diff --git a/primitives/runtime/src/generic/block.rs b/primitives/runtime/src/generic/block.rs index fb07d6c215d81f3a241926da6252c12686fc2f28..4a758b7416dec568876a769ff4dbcf1f69b00385 100644 --- a/primitives/runtime/src/generic/block.rs +++ b/primitives/runtime/src/generic/block.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of a block and associated items. diff --git a/primitives/runtime/src/generic/checked_extrinsic.rs b/primitives/runtime/src/generic/checked_extrinsic.rs index a329f334c0d7707edc8a4e07ada8eac443accce2..f355308a59f9704d7f7343dcd904d8458ad63184 100644 --- a/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/primitives/runtime/src/generic/checked_extrinsic.rs @@ -1,24 +1,26 @@ -// Copyright 2017-2020 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. +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of an extrinsic that has passed the verification //! stage. use crate::traits::{ - self, Member, MaybeDisplay, SignedExtension, Dispatchable, DispatchInfoOf, ValidateUnsigned, + self, Member, MaybeDisplay, SignedExtension, Dispatchable, DispatchInfoOf, PostDispatchInfoOf, + ValidateUnsigned, }; use crate::transaction_validity::{TransactionValidity, TransactionSource}; @@ -66,7 +68,7 @@ where self, info: &DispatchInfoOf, len: usize, - ) -> crate::ApplyExtrinsicResult { + ) -> crate::ApplyExtrinsicResultWithInfo> { let (maybe_who, pre) = if let Some((id, extra)) = self.signed { let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?; (Some(id), pre) @@ -80,8 +82,7 @@ where Ok(info) => info, Err(err) => err.post_info, }; - let res = res.map(|_| ()).map_err(|e| e.error); - Extra::post_dispatch(pre, info, &post_info, len, &res)?; + Extra::post_dispatch(pre, info, &post_info, len, &res.map(|_| ()).map_err(|e| e.error))?; Ok(res) } } diff --git a/primitives/runtime/src/generic/digest.rs b/primitives/runtime/src/generic/digest.rs index 44c1559aaa088dfbb9d51a116f88311df8bd1611..ec0963e5ba002c15490ef63034d7c8aa43a3d596 100644 --- a/primitives/runtime/src/generic/digest.rs +++ b/primitives/runtime/src/generic/digest.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of a digest. diff --git a/primitives/runtime/src/generic/era.rs b/primitives/runtime/src/generic/era.rs index 37b4b495fef540eb3b942098e3f54f11dfd41d1e..9bfab517a92caab182dba4d6a652757eb47158d4 100644 --- a/primitives/runtime/src/generic/era.rs +++ b/primitives/runtime/src/generic/era.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of an unchecked (pre-verification) extrinsic. diff --git a/primitives/runtime/src/generic/header.rs b/primitives/runtime/src/generic/header.rs index 5efb36603d572fd7be350f7b046e8b5969408cc6..24cceef2cdc331ca81831457e8cd757e85c616d7 100644 --- a/primitives/runtime/src/generic/header.rs +++ b/primitives/runtime/src/generic/header.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of a block header. diff --git a/primitives/runtime/src/generic/mod.rs b/primitives/runtime/src/generic/mod.rs index 5e9928ba1909ab2aa114babaadcc1cc774131e60..2a25c063ead7345c9428a920de39780ab5eedb35 100644 --- a/primitives/runtime/src/generic/mod.rs +++ b/primitives/runtime/src/generic/mod.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // tag::description[] //! Generic implementations of Extrinsic/Header/Block. diff --git a/primitives/runtime/src/generic/tests.rs b/primitives/runtime/src/generic/tests.rs index de2f4a19d99cf7b366af00ef24ea322a6fc0ce68..56138094fa0246e5f25b173a7cf11a596e2e96be 100644 --- a/primitives/runtime/src/generic/tests.rs +++ b/primitives/runtime/src/generic/tests.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Tests for the generic implementations of Extrinsic/Header/Block. diff --git a/primitives/runtime/src/generic/unchecked_extrinsic.rs b/primitives/runtime/src/generic/unchecked_extrinsic.rs index 4eb96ff960bcc72d65fd12d0567bd7206945d131..41ff2609fc8ccc1939dca2a23445052927a61a3a 100644 --- a/primitives/runtime/src/generic/unchecked_extrinsic.rs +++ b/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Generic implementation of an unchecked (pre-verification) extrinsic. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index a5b3e71edcde3d9f1d258730f58ba3749daf2f46..52ae46c6624287ae2133531c78d67fc3ffa92b1f 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -1,18 +1,19 @@ -// Copyright 2017-2020 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 . +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Runtime Modules shared primitive types. @@ -62,7 +63,7 @@ pub use crate::runtime_string::*; pub use generic::{DigestItem, Digest}; /// Re-export this since it's part of the API of this crate. -pub use sp_core::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, AccountId32}}; +pub use sp_core::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, CryptoTypeId, AccountId32}}; pub use sp_application_crypto::{RuntimeAppPublic, BoundToRuntimeAppPublic}; /// Re-export `RuntimeDebug`, to avoid dependency clutter. @@ -71,7 +72,7 @@ pub use sp_core::RuntimeDebug; /// Re-export top-level arithmetic stuff. pub use sp_arithmetic::{ Perquintill, Perbill, Permill, Percent, PerU16, Rational128, Fixed64, Fixed128, - PerThing, traits::SaturatedConversion, + PerThing, traits::SaturatedConversion, FixedPointNumber, FixedPointOperand, }; /// Re-export 128 bit helpers. pub use sp_arithmetic::helpers_128bit; @@ -373,16 +374,16 @@ impl From for DispatchOutcome { } } -/// This is the legacy return type of `Dispatchable`. It is still exposed for compatibilty -/// reasons. The new return type is `DispatchResultWithInfo`. -/// FRAME runtimes should use frame_support::dispatch::DispatchResult +/// This is the legacy return type of `Dispatchable`. It is still exposed for compatibility reasons. +/// The new return type is `DispatchResultWithInfo`. FRAME runtimes should use +/// `frame_support::dispatch::DispatchResult`. pub type DispatchResult = sp_std::result::Result<(), DispatchError>; /// Return type of a `Dispatchable` which contains the `DispatchResult` and additional information /// about the `Dispatchable` that is only known post dispatch. pub type DispatchResultWithInfo = sp_std::result::Result>; -/// Reason why a dispatch call failed +/// Reason why a dispatch call failed. #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize))] pub enum DispatchError { @@ -392,11 +393,11 @@ pub enum DispatchError { CannotLookup, /// A bad origin. BadOrigin, - /// A custom error in a module + /// A custom error in a module. Module { - /// Module index, matching the metadata module index + /// Module index, matching the metadata module index. index: u8, - /// Module specific error value + /// Module specific error value. error: u8, /// Optional error message. #[codec(skip)] @@ -404,15 +405,15 @@ pub enum DispatchError { }, } -/// Result of a `Dispatchable` which contains the `DispatchResult` and additional information -/// about the `Dispatchable` that is only known post dispatch. +/// Result of a `Dispatchable` which contains the `DispatchResult` and additional information about +/// the `Dispatchable` that is only known post dispatch. #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)] pub struct DispatchErrorWithPostInfo where Info: Eq + PartialEq + Clone + Copy + Encode + Decode + traits::Printable { - /// Addditional information about the `Dispatchable` which is only known post dispatch. + /// Additional information about the `Dispatchable` which is only known post dispatch. pub post_info: Info, - /// The actual `DispatchResult` indicating whether the dispatch was succesfull. + /// The actual `DispatchResult` indicating whether the dispatch was successful. pub error: DispatchError, } @@ -535,6 +536,10 @@ pub type DispatchOutcome = Result<(), DispatchError>; /// - The extrinsic supplied a bad signature. This transaction won't become valid ever. pub type ApplyExtrinsicResult = Result; +/// Same as `ApplyExtrinsicResult` but augmented with `PostDispatchInfo` on success. +pub type ApplyExtrinsicResultWithInfo = + Result, transaction_validity::TransactionValidityError>; + /// Verify a signature on an encoded value in a lazy manner. This can be /// an optimization if the signature scheme has an "unsigned" escape hash. pub fn verify_encoded_lazy( diff --git a/primitives/runtime/src/offchain/http.rs b/primitives/runtime/src/offchain/http.rs index bbc929526b75998c181346a87eeaa3e532dc441c..12a0fcf1e5b45cb5c7cb258950ef561c11a6797a 100644 --- a/primitives/runtime/src/offchain/http.rs +++ b/primitives/runtime/src/offchain/http.rs @@ -1,18 +1,19 @@ -// Copyright 2019-2020 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 . +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A high-level helpers for making HTTP requests from Offchain Workers. //! diff --git a/primitives/runtime/src/offchain/mod.rs b/primitives/runtime/src/offchain/mod.rs index 9f0f949eaeb8df483df75b680fc1b872ae91ea4f..fe5844ce3004b62286968cf829e4b71793515446 100644 --- a/primitives/runtime/src/offchain/mod.rs +++ b/primitives/runtime/src/offchain/mod.rs @@ -1,22 +1,24 @@ -// Copyright 2019-2020 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. +// Copyright (C) 2019-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 -// 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 . +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A collection of higher lever helpers for offchain calls. pub mod http; pub mod storage; +pub mod storage_lock; pub use sp_core::offchain::*; diff --git a/primitives/runtime/src/offchain/storage.rs b/primitives/runtime/src/offchain/storage.rs index 681bc14451e116e52c71f1f239d7ff539ded9c8e..2f62d400c0b950b326f70edae145de259eb16e7d 100644 --- a/primitives/runtime/src/offchain/storage.rs +++ b/primitives/runtime/src/offchain/storage.rs @@ -1,18 +1,19 @@ -// Copyright 2020 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 . +// Copyright (C) 2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! A set of storage helpers for offchain workers. @@ -49,6 +50,11 @@ impl<'a> StorageValueRef<'a> { }) } + /// Remove the associated value from the storage. + pub fn clear(&mut self) { + sp_io::offchain::local_storage_clear(self.kind, self.key) + } + /// Retrieve & decode the value from storage. /// /// Note that if you want to do some checks based on the value @@ -66,7 +72,8 @@ impl<'a> StorageValueRef<'a> { /// Function `f` should return a new value that we should attempt to write to storage. /// This function returns: /// 1. `Ok(Ok(T))` in case the value has been successfully set. - /// 2. `Ok(Err(T))` in case the value was returned, but it couldn't have been set. + /// 2. `Ok(Err(T))` in case the value was calculated by the passed closure `f`, + /// but it could not be stored. /// 3. `Err(_)` in case `f` returns an error. pub fn mutate(&self, f: F) -> Result, E> where T: codec::Codec, diff --git a/primitives/runtime/src/offchain/storage_lock.rs b/primitives/runtime/src/offchain/storage_lock.rs new file mode 100644 index 0000000000000000000000000000000000000000..f8defa422459f4c4068f105d5d28d28a9a8ea4de --- /dev/null +++ b/primitives/runtime/src/offchain/storage_lock.rs @@ -0,0 +1,515 @@ +// Copyright 2019-2020 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 . + +//! # Off-chain Storage Lock +//! +//! A storage-based lock with a defined expiry time. +//! +//! The lock is using Local Storage and allows synchronizing access to critical +//! section of your code for concurrently running Off-chain Workers. Usage of +//! `PERSISTENT` variant of the storage persists the lock value across a full node +//! restart or re-orgs. +//! +//! A use case for the lock is to make sure that a particular section of the +//! code is only run by one Off-chain Worker at a time. This may include +//! performing a side-effect (i.e. an HTTP call) or alteration of single or +//! multiple Local Storage entries. +//! +//! One use case would be collective updates of multiple data items or append / +//! remove of i.e. sets, vectors which are stored in the off-chain storage DB. +//! +//! ## Example: +//! +//! ```rust +//! # use codec::{Decode, Encode, Codec}; +//! // in your off-chain worker code +//! use sp_runtime::offchain::{ +//! storage::StorageValueRef, +//! storage_lock::{StorageLock, Time}, +//! }; +//! +//! fn append_to_in_storage_vec<'a, T>(key: &'a [u8], _: T) where T: Codec { +//! // `access::lock` defines the storage entry which is used for +//! // persisting the lock in the underlying database. +//! // The entry name _must_ be unique and can be interpreted as a +//! // unique mutex instance reference tag. +//! let mut lock = StorageLock::