You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Contract builds are not reproducible across different machines and environments. Different host OS, architecture, toolchain versions, and system libraries can produce different .wasm outputs from the same source code. This makes it impossible for third parties to independently verify that a deployed contract was built from a given source.
Related: stellar/stellar-protocol#1802 explored reproducing builds without Docker, but that approach hasn't proven reliable.
What would you like to see?
Building Reproducibly
Add a --docker option to stellar contract build that runs the cargo rustc build step inside a Docker container using an official Rust image pinned to a specific digest, always targeting amd64 architecture to eliminate host architecture differences.
--docker (no value): Pulls the latest official Rust image (docker.io/library/rust:latest) as --platform linux/amd64. After pulling, the resolved @sha256:... digest is recorded in contract metadata so the exact image can be replayed later.
--docker=<image> (with value): Uses the specified Docker image, allowing users to reproduce past builds by passing the exact image with digest (e.g. docker.io/library/rust@sha256:abcdef...).
Only the cargo rustc compilation runs inside Docker. The CLI's own post-processing of the .wasm file (optimization, metadata, etc.) continues to run on the host, outside Docker.
The fully qualified Docker image name including its @sha256:... digest is recorded as a contract metadata entry, alongside the existing CLI version metadata.
Defaults are powerful and after sometime it might make sense to make this the default build option, meaning the docker build process is used automatically if a docker host is detected, and if the non-docker build process is used a warning is displayed indicating that reproducibility will be limited.
Verifying
stellar contract verify command:
Add a stellar contract verify command that automates verification of a contract build. It accepts the same wasm inputs as other contract commands:
--wasm <path> — a local .wasm file
--wasm-hash <hash> — fetch the wasm by its hash from the network
--contract-id <id> — fetch the wasm for a deployed contract from the network
The command:
Reads the Docker image and CLI version from the contract's metadata.
Errors if the CLI version in metadata does not match the currently running stellar-cli version (the user must install the matching version first).
Rebuilds the contract from source using stellar contract build --docker=<image> with the Docker image from metadata.
Compares the rebuild output to the original .wasm and reports whether they match.
Manual verification:
The same verification can also be done manually:
Install the same version of stellar-cli (recorded in contract metadata).
Run stellar contract build --docker=<image> using the same Docker image (also recorded in contract metadata).
Compare the resulting .wasm output.
flowchart TD
A[stellar contract build] --> B{--docker flag?}
B -- No --> C[cargo rustc on host]
B -- "--docker" --> D[Pull latest rust image\namd64, record resolved digest]
B -- "--docker=image" --> E[Pull specified image\namd64]
D --> F[cargo rustc inside Docker container]
E --> F
C --> G[CLI post-processes .wasm on host]
F --> G
G --> H[Embed metadata:\n- CLI version\n- Docker image + digest]
H --> I[Final .wasm output]
style D fill:#ccffcc,stroke:#00ff00
style E fill:#ccffcc,stroke:#00ff00
style F fill:#ccffcc,stroke:#00ff00
style H fill:#ccffcc,stroke:#00ff00
Loading
Legend:
Green = New/proposed components
Default = Existing/unchanged components
Why not include the CLI in the Docker image?
Bundling the CLI into a custom Docker image would create a single blessed image that SDF must maintain and host. But instead using community images (like the official rust image) and allowing any image to be specified, builds stay decentralised. No single entity controls the build environment, and users aren't locked into a specific image provider.
What alternatives are there?
Pinning a specific image version in each CLI release, but this ties CLI releases to image updates and adds maintenance burden. Pulling latest and recording the digest is simpler and always gives the newest toolchain.
Reproducing builds without Docker by pinning toolchain versions (explored in https://github.com/orgs/stellar/discussions/1802, but has not proven reliable due to host OS and system library differences).
A fully self-contained Docker image with both Rust and the CLI baked in, but this centralises control and limits flexibility.
Thanks
This idea is not unique or mine, a few people over time have mentioned ideas very much like this, and other blockchain ecosystems rely on docker to isolate and reproduce as well. Thanks to everyone who has raised this ideas at different times.
What problem does your feature solve?
Contract builds are not reproducible across different machines and environments. Different host OS, architecture, toolchain versions, and system libraries can produce different
.wasmoutputs from the same source code. This makes it impossible for third parties to independently verify that a deployed contract was built from a given source.Related: stellar/stellar-protocol#1802 explored reproducing builds without Docker, but that approach hasn't proven reliable.
What would you like to see?
Building Reproducibly
Add a
--dockeroption tostellar contract buildthat runs thecargo rustcbuild step inside a Docker container using an official Rust image pinned to a specific digest, always targetingamd64architecture to eliminate host architecture differences.--docker(no value): Pulls the latest official Rust image (docker.io/library/rust:latest) as--platform linux/amd64. After pulling, the resolved@sha256:...digest is recorded in contract metadata so the exact image can be replayed later.--docker=<image>(with value): Uses the specified Docker image, allowing users to reproduce past builds by passing the exact image with digest (e.g.docker.io/library/rust@sha256:abcdef...).cargo rustccompilation runs inside Docker. The CLI's own post-processing of the.wasmfile (optimization, metadata, etc.) continues to run on the host, outside Docker.@sha256:...digest is recorded as a contract metadata entry, alongside the existing CLI version metadata.Defaults are powerful and after sometime it might make sense to make this the default build option, meaning the docker build process is used automatically if a docker host is detected, and if the non-docker build process is used a warning is displayed indicating that reproducibility will be limited.
Verifying
stellar contract verifycommand:Add a
stellar contract verifycommand that automates verification of a contract build. It accepts the same wasm inputs as other contract commands:--wasm <path>— a local.wasmfile--wasm-hash <hash>— fetch the wasm by its hash from the network--contract-id <id>— fetch the wasm for a deployed contract from the networkThe command:
stellar-cliversion (the user must install the matching version first).stellar contract build --docker=<image>with the Docker image from metadata..wasmand reports whether they match.Manual verification:
The same verification can also be done manually:
stellar-cli(recorded in contract metadata).stellar contract build --docker=<image>using the same Docker image (also recorded in contract metadata)..wasmoutput.flowchart TD A[stellar contract build] --> B{--docker flag?} B -- No --> C[cargo rustc on host] B -- "--docker" --> D[Pull latest rust image\namd64, record resolved digest] B -- "--docker=image" --> E[Pull specified image\namd64] D --> F[cargo rustc inside Docker container] E --> F C --> G[CLI post-processes .wasm on host] F --> G G --> H[Embed metadata:\n- CLI version\n- Docker image + digest] H --> I[Final .wasm output] style D fill:#ccffcc,stroke:#00ff00 style E fill:#ccffcc,stroke:#00ff00 style F fill:#ccffcc,stroke:#00ff00 style H fill:#ccffcc,stroke:#00ff00Legend:
Why not include the CLI in the Docker image?
Bundling the CLI into a custom Docker image would create a single blessed image that SDF must maintain and host. But instead using community images (like the official
rustimage) and allowing any image to be specified, builds stay decentralised. No single entity controls the build environment, and users aren't locked into a specific image provider.What alternatives are there?
Thanks
This idea is not unique or mine, a few people over time have mentioned ideas very much like this, and other blockchain ecosystems rely on docker to isolate and reproduce as well. Thanks to everyone who has raised this ideas at different times.