Skip to content

Commit

Permalink
CW-53: Added a runtime metadata check (#1762)
Browse files Browse the repository at this point in the history
# Description

This PR adds a runtime metadata check, which consists of two phases:
1. Build `subxt` using large self-hosted runner (1 minute)
2. Run `subxt codegen` on runtime built from main (used in e2e tests -
short session) (1 minute)
This check fails if someone forgets to regenerate the `aleph-runtime`
static metadata file.

There's no if condition when this check is supposed to run as if
practically it does not make sense to check, e.g., if runtime code
changed or aleph pallet code changed in git, as then we'd need to check
every `aleph-runtime` dependency, etc. This check is lightweight (2-3
minutes, and runs in parallel with the longest check excluded packages).

Also, this PR consists of changes to the `Aleph::NextAuthorities` hash.
This hash is what `subtext` thinks the hash of `NextAuthorities`
metadata is. Normally, this hash does not include any of what is stored
as a storage value, but only data such as pallet name, storage function
name, storage value type (`Option<T>` or `T`), etc. Also, maybe a bit
surprisingly, it includes _default_ value of given type into that
`subxt` hash. Now, `NextAuthorities` storage value type is
`Vec<AccountId>`, and normally default is `vec![]`. However, we do have
a default initializer `DefaultNextAuthorities` which, turns out, is used
by `subxt codegen` when generating hash for `NextAuthorities`. When
`DefaultNextAuthorities`, static runtime metadata generated by `subxt`
is always the same in CI. `DefaultNextAuthorities` is not required in
pallet aleph, as initialization of `NextAuthorities` is done in
`on_genesis_session`.

## Type of change

Please delete options that are not relevant.

- New feature (non-breaking change which adds functionality)

# Testing
* [Runtime changed but no metadata regenerated -
fail](https://github.com/Cardinal-Cryptography/aleph-node/actions/runs/9516243551/job/26232450103)
- OK
* [Runtime changed and metadata regenerated -
pass](https://github.com/Cardinal-Cryptography/aleph-node/actions/runs/9577643942/job/26406625666?pr=1762)
- OK
  • Loading branch information
Marcin-Radecki authored Jun 19, 2024
1 parent d004433 commit 2b195a0
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .github/scripts/run_consensus.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function generate_chainspec() {

echo "Generate chainspec and keystores for accounts: ${account_ids_comma_separated[@]}"
docker run --rm -v $(pwd)/docker/data:/data --entrypoint "/bin/sh" -e RUST_LOG=debug "${CHAIN_BOOTSTRAPPER_IMAGE}" \
-c "chain-bootstrapper bootstrap-chain --base-path /data --account-ids ${account_ids_comma_separated} --authorities-account-ids ${validator_ids_comma_separated} > /data/chainspec.json"
-c "chain-bootstrapper bootstrap-chain --base-path /data --account-ids ${account_ids_comma_separated} --authorities-account-ids ${validator_ids_comma_separated} --raw > /data/chainspec.json"
}

function generate_bootnode_peer_id() {
Expand Down
109 changes: 109 additions & 0 deletions .github/workflows/_check-runtime-metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
# This workflow builds subxt-cli, starts local one-node consensus chain and
# uses subxt codegen to compare live chain data with what is versioned in git
name: Check runtime metadata
on:
workflow_call:
inputs:
ref:
description: "git ref: hash, branch, tag or 'mainnet' or 'testnet'"
type: string
required: true
artifact-aleph-node-image:
description: 'Name of aleph-node image stored in GH Artifacts'
type: string
required: true
artifact-chain-bootstrapper-image:
description: 'chain-bootstrapper image name in GH artifacts'
type: string
required: true
jobs:
build-subxt:
name: Build subxt
runs-on: [self-hosted, Linux, X64, large]
env:
RUST_BACKTRACE: full
RUSTC_WRAPPER: sccache
steps:
- name: Checkout aleph-node source code
uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
fetch-depth: 0

- name: Call action get-ref-properties
id: get-ref-properties
uses: Cardinal-Cryptography/github-actions/get-ref-properties@v7

- name: Install Rust toolchain
uses: Cardinal-Cryptography/github-actions/install-rust-toolchain@v7
with:
targets: wasm32-unknown-unknown

- name: Build subxt-cli
shell: bash
run: |
# same version as in aleph-client's Cargo.toml
cargo install subxt-cli --version 0.30.1
- name: Get subxt-cli path
id: get-subxt-path
shell: bash
run: |
subxt_path=$(which subxt)
echo "path=${subxt_path}" >> $GITHUB_OUTPUT
- name: Upload subxt binary to GH artifacts
uses: actions/upload-artifact@v4
with:
name: subxt-binary
path: ${{ steps.get-subxt-path.outputs.path }}
if-no-files-found: error
retention-days: 7

check-metadata:
name: Check runtime metadata
needs: [build-subxt]
runs-on: ubuntu-20.04
steps:
- name: Checkout aleph-node source code
uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
fetch-depth: 0

- name: Download node docker image
uses: actions/download-artifact@v4
with:
name: subxt-binary

- name: Download node docker image
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact-aleph-node-image }}

- name: Load node docker image
shell: bash
run: docker load -i aleph-node.tar

- name: Download chain-bootstrapper image
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact-chain-bootstrapper-image }}

- name: Load chain-bootstrapper image
shell: bash
run: docker load -i chain-bootstrapper.tar

- name: Run consensus party
shell: bash
run: |
./.github/scripts/run_consensus.sh -n 1
sleep 30
- name: Check metadata
shell: bash
run: |
chmod +x subxt
cd aleph-client
SUBXT_BINARY=../subxt ./check-runtime-metadata.sh
12 changes: 12 additions & 0 deletions .github/workflows/on-pull-request-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ jobs:
name: Check production node and runtime
uses: ./.github/workflows/_check-production-node-and-runtime.yml

check-runtime-metadata:
name: Check runtime metadata
needs:
- build-test-aleph-node
- build-chain-bootstrapper
uses: ./.github/workflows/_check-runtime-metadata.yml
with:
ref: ${{ github.ref }}
artifact-aleph-node-image: ${{ needs.build-test-aleph-node.outputs.artifact-name-image }}
# yamllint disable-line rule:line-length
artifact-chain-bootstrapper-image: ${{ needs.build-chain-bootstrapper.outputs.artifact-name-image }}

build-test-aleph-node:
name: Build test aleph-node
uses: ./.github/workflows/_build-aleph-node.yml
Expand Down
2 changes: 0 additions & 2 deletions aleph-client/.dockerignore

This file was deleted.

9 changes: 6 additions & 3 deletions ...nt/docker/subxt-integration-entrypoint.sh → aleph-client/check-runtime-metadata.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#!/usr/bin/env bash

subxt codegen --derive Clone --derive Debug --derive PartialEq --derive Eq \
echo "This script must be run from the aleph-client directory."
SUBXT_BINARY=${SUBXT_BINARY:-"subxt"}

"${SUBXT_BINARY}" codegen --derive Clone --derive Debug --derive PartialEq --derive Eq \
--substitute-type 'sp_core::crypto::AccountId32=::subxt::utils::Static<::subxt::ext::sp_core::crypto::AccountId32>' \
| rustfmt --edition=2021 --config-path aleph-node/rustfmt.toml > aleph_zero.rs;
| rustfmt --edition=2021 --config-path rustfmt.toml > aleph_zero.rs;

diff -y -W 200 --suppress-common-lines aleph_zero.rs aleph-node/aleph-client/src/aleph_zero.rs
diff -y -W 200 --suppress-common-lines aleph_zero.rs src/aleph_zero.rs
diff_exit_code=$?
if [[ ! $diff_exit_code -eq 0 ]]; then
echo "Current runtime metadata is different than versioned in git!"
Expand Down
18 changes: 0 additions & 18 deletions aleph-client/docker/README.md

This file was deleted.

13 changes: 0 additions & 13 deletions aleph-client/docker/subxt-integration.Dockerfile

This file was deleted.

14 changes: 7 additions & 7 deletions aleph-client/src/aleph_zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2075,9 +2075,9 @@ pub mod api {
.hash();
runtime_metadata_hash
== [
254u8, 200u8, 139u8, 229u8, 182u8, 242u8, 46u8, 196u8, 112u8, 184u8, 161u8, 232u8,
129u8, 49u8, 226u8, 113u8, 114u8, 72u8, 155u8, 188u8, 131u8, 171u8, 11u8, 1u8,
35u8, 152u8, 155u8, 138u8, 53u8, 78u8, 176u8, 47u8,
115u8, 13u8, 54u8, 26u8, 248u8, 53u8, 14u8, 227u8, 103u8, 17u8, 45u8, 180u8, 199u8,
63u8, 105u8, 193u8, 146u8, 2u8, 207u8, 204u8, 119u8, 126u8, 56u8, 214u8, 233u8,
168u8, 66u8, 4u8, 159u8, 15u8, 224u8, 180u8,
]
}
pub mod system {
Expand Down Expand Up @@ -9477,10 +9477,10 @@ pub mod api {
"NextAuthorities",
vec![],
[
207u8, 65u8, 187u8, 184u8, 128u8, 170u8, 162u8, 124u8, 3u8, 121u8,
231u8, 236u8, 27u8, 131u8, 223u8, 66u8, 81u8, 32u8, 28u8, 2u8, 228u8,
174u8, 133u8, 85u8, 129u8, 207u8, 165u8, 61u8, 0u8, 124u8, 164u8,
246u8,
228u8, 138u8, 101u8, 251u8, 183u8, 146u8, 98u8, 145u8, 172u8, 29u8,
10u8, 111u8, 91u8, 160u8, 3u8, 43u8, 189u8, 168u8, 233u8, 231u8, 105u8,
190u8, 200u8, 168u8, 61u8, 22u8, 162u8, 126u8, 213u8, 63u8, 131u8,
47u8,
],
)
}
Expand Down
9 changes: 1 addition & 8 deletions pallets/aleph/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,13 @@ pub mod pallet {
DEFAULT_FINALITY_VERSION
}

/// Default value for `NextAuthorities` storage.
#[pallet::type_value]
pub(crate) fn DefaultNextAuthorities<T: Config>() -> Vec<T::AuthorityId> {
T::NextSessionAuthorityProvider::next_authorities()
}

#[pallet::storage]
#[pallet::getter(fn authorities)]
pub(super) type Authorities<T: Config> = StorageValue<_, Vec<T::AuthorityId>, ValueQuery>;

#[pallet::storage]
#[pallet::getter(fn next_authorities)]
pub(super) type NextAuthorities<T: Config> =
StorageValue<_, Vec<T::AuthorityId>, ValueQuery, DefaultNextAuthorities<T>>;
pub(super) type NextAuthorities<T: Config> = StorageValue<_, Vec<T::AuthorityId>, ValueQuery>;

/// Set of account ids that will be used as authorities in the next session
#[pallet::storage]
Expand Down

0 comments on commit 2b195a0

Please sign in to comment.