Build a Deterministic Runtime¶
Introduction¶
By default, the Rust compiler produces optimized Wasm binaries. These binaries are suitable for working in an isolated environment, such as local development. However, the Wasm binaries the compiler builds by default aren't guaranteed to be deterministically reproducible. Each time the compiler generates the Wasm runtime, it might produce a slightly different Wasm byte code. This is problematic in a blockchain network where all nodes must use exactly the same raw chain specification file.
Working with builds that aren't guaranteed to be deterministically reproducible can cause other problems, too. For example, for automating the build processes for a blockchain, it is ideal that the same code always produces the same result (in terms of bytecode). Compiling the Wasm runtime with every push would produce inconsistent and unpredictable results without a deterministic build, making it difficult to integrate with any automation and likely to break a CI/CD pipeline continuously. Deterministic builds—code that always compiles to exactly the same bytecode—ensure that the Wasm runtime can be inspected, audited, and independently verified.
Prerequisites¶
Before you begin, ensure you have Docker installed.
Tooling for Wasm Runtime¶
To compile the Wasm runtime deterministically, the same tooling that produces the runtime for Polkadot, Kusama, and other Polkadot SDK-based chains can be used. This tooling, referred to collectively as the Substrate Runtime Toolbox or srtool
, ensures that the same source code consistently compiles to an identical Wasm blob.
The core component of srtool
is a Docker container executed as part of a Docker image. The name of the srtool
Docker image specifies the version of the Rust compiler used to compile the code included in the image. For example, the image paritytech/srtool:1.62.0
indicates that the code in the image was compiled with version 1.62.0
of the rustc
compiler.
Working with the Docker Container¶
The srtool-cli
package is a command-line utility written in Rust that installs an executable program called srtool
. This program simplifies the interactions with the srtool
Docker container.
Over time, the tooling around the srtool
Docker image has expanded to include the following tools and helper programs:
srtool-cli
- provides a command-line interface to pull the srtool Docker image, get information about the image and tooling used to interact with it, and build the runtime using thesrtool
Docker containersubwasm
- provides command-line options for working with the metadata and Wasm runtime built using srtool. Thesubwasm
program is also used internally to perform tasks in thesrtool
imagesrtool-actions
- provides GitHub actions to integrate builds produced using thesrtool
image with your GitHub CI/CD pipelinessrtool-app
- provides a simple graphical user interface for building the runtime using thesrtool
Docker image
Prepare the Environment¶
It is recommended to install the srtool-cli
program to work with the Docker image using a simple command-line interface.
To prepare the environment:
-
Verify that Docker is installed by running the following command:
If Docker is installed, the command will display version information:
docker --version Docker version 20.10.17, build 100c701 -
Install the
srtool
command-line interface by running the following command: -
View usage information for the
srtool
command-line interface by running the following command: -
Download the latest
srtool
Docker image by running the following command:
Start a Deterministic Build¶
After preparing the environment, the Wasm runtime can be compiled using the srtool
Docker image.
To build the runtime, you need to open your Polkadot SDK-based project in a terminal shell and run the following command:
- The name specified for the
--package
should be the name defined in theCargo.toml
file for the runtime -
The path specified for the
--runtime-dir
should be the path to theCargo.toml
file for the runtime. For example: -
If the
Cargo.toml
file for the runtime is located in aruntime
subdirectory, for example,runtime/kusama
, the--runtime-dir
parameter can be omitted
Use srtool in GitHub Actions¶
To add a GitHub workflow for building the runtime:
- Create a
.github/workflows
directory in the chain's directory - In the
.github/workflows
directory, click Add file, then select Create new file -
Copy the sample GitHub action from
basic.yml
example in thesrtools-actions
repository and paste it into the file you created in the previous stepbasic.yml
name: Srtool build on: push jobs: srtool: runs-on: ubuntu-latest strategy: matrix: chain: ["asset-hub-kusama", "asset-hub-westend"] steps: - uses: actions/checkout@v3 - name: Srtool build id: srtool_build uses: chevdor/srtool-actions@v0.8.0 with: chain: ${{ matrix.chain }} runtime_dir: polkadot-parachains/${{ matrix.chain }}-runtime - name: Summary run: | echo '${{ steps.srtool_build.outputs.json }}' | jq . > ${{ matrix.chain }}-srtool-digest.json cat ${{ matrix.chain }}-srtool-digest.json echo "Runtime location: ${{ steps.srtool_build.outputs.wasm }}"
-
Modify the settings in the sample action
For example, modify the following settings:
- The name of the chain
- The name of the runtime package
- The location of the runtime
-
Type a name for the action file and commit
Use the srtool Image via Docker Hub¶
If utilizing srtool-cli
or srtool-app
isn't an option, the paritytech/srtool
container image can be used directly via Docker Hub.
To pull the image from Docker Hub:
- Sign in to Docker Hub
- Type
paritytech/srtool
in the search field and press enter - Click paritytech/srtool, then click Tags
- Copy the command for the image you want to pull
- Open a terminal shell on your local computer
-
Paste the command you copied from the Docker Hub. For example, you might run a command similar to the following, which downloads and unpacks the image:
Naming Convention for Images¶
Keep in mind that there is no latest
tag for the srtool
image. Ensure that the image selected is compatible with the locally available version of the Rust compiler.
The naming convention for paritytech/srtool
Docker images specifies the version of the Rust compiler used to compile the code included in the image. Some images specify both a compiler version and the version of the build script used. For example, an image named paritytech/srtool:1.62.0-0.9.19
was compiled with version 1.62.0
of the rustc
compiler and version 0.9.19
of the build script. Images that only specify the compiler version always contain the software's latest version.
| Created: November 8, 2024