Skip to content

Add stellar contract verify command#2586

Draft
fnando wants to merge 20 commits into
contract-build-verifiablefrom
contract-verify
Draft

Add stellar contract verify command#2586
fnando wants to merge 20 commits into
contract-build-verifiablefrom
contract-verify

Conversation

@fnando

@fnando fnando commented May 22, 2026

Copy link
Copy Markdown
Member

⚠️ Depends on #2585 — do not merge until #2585 lands on main. This PR's base is contract-build-verifiable, so once #2585 merges, GitHub will automatically retarget this one to main.

What

Adds a new stellar contract verify subcommand that takes a contract id (--id, fetched from the network) or a local WASM (--wasm), reads the SEP-58 build metadata embedded in it (bldimg, source identification, build flags), re-runs the recorded build inside the recorded container image, and byte-compares the result against the original to confirm the WASM is reproducible.

Notable bits:

  • Source materialization works for both git pairs (source_repo + source_rev) and tarballs (tarball_url + tarball_sha256). For WASMs that record only tarball_sha256, the user can supply a local file or URL via --tarball-url.
  • Git cloning uses gix (with rustls TLS) instead of shelling out to git, so the command has no runtime dependency on a system git binary and there's a single retrieval channel to gate on.
  • A trust prompt fires before pulling an unrecognized bldimg, and unconditionally for any tarball source (tarballs are never default-trusted). --trust skips it; the prompt overrides --quiet so it can't be silenced by accident. The default trust list is the stellar/stellar-cli image.
  • The materialized source directory is created with hardened permissions so a local attacker can't slip a file in mid-verify.
  • Integration tests cover the git source path, tarball-by-URL, tarball-by-local-file (with --tarball-sha256), and the trust-prompt flow; they live in the existing integration tier.

Why

#2585 makes it possible to produce a verifiable build; this PR is the other half — a way to check a deployed contract against its claimed source. Together they close the SEP-58 loop end-to-end in the CLI.

Known limitations

N/A

@github-project-automation github-project-automation Bot moved this to Backlog (Not Ready) in DevX May 22, 2026
@fnando fnando moved this from Backlog (Not Ready) to In Progress in DevX May 22, 2026
@fnando fnando self-assigned this May 22, 2026
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​reqwest@​0.13.37910094100100
Addedcargo/​gix@​0.83.08110093100100
Addedcargo/​tar@​0.4.4610010093100100
Updatedcargo/​tempfile@​3.21.0 ⏵ 3.27.098 -110093100100

View full report

@saimeunt

saimeunt commented Jun 5, 2026

Copy link
Copy Markdown

Hi @fnando, we just submitted a proposal for the Contract Source Verification Service RFP and it mentioned your draft PR.

It’s great that SEP-58 core verification logic is now embedded directly in stellar-cli, it provides a single source of truth for build reproducibility among verifiers. We plan to use stellar contract verify in our service to handle the actual verification, which includes fetching WASM, extracting metadata, rebuilding contract with the correct buildimg and comparing rebuilt WASM hash with on-chain hash.

While designing our tech architecture document for the RFP, we noticed retroactive verification is a mandatory requirement for the upcoming verification service, but contracts deployed before stellar contract build —-verifiable lack the proper contractmetav0 containing the SEP-58 fields expected by stellar contract verify.

At the moment, stellar contract verifywill error when SEP-58 fields are missing (as per WIP implementation). This means in its current state the core verification logic from stellar-cli can’t be leveraged to implement retroactive verification using the same ideal path as newly-deployed contracts built with with stellar contract build —-verifiable.

In your notable bits, you mention that the user can supply a local file or URL via --tarball-urlfor supplying tarball_url when it’s missing in contractmetav0, eg. when working with closed-source contracts. We think this should be extended to all SEP-58 fields to allow supporting a wider range of verifications scenario, providing an escape hatch for contracts deployed before SEP-58 is adopted.

It is the responsibility of the verifier to flag these verification results as having their build environment provided by the user submitting the verification and not recorded on-chain in WASM metadata.

Does this suggestion makes sense and do you plan to add support for user-supplied build environment + source identification parameters while finalizing this draft?

@fnando

fnando commented Jun 5, 2026

Copy link
Copy Markdown
Member Author

@saimeunt Yes, the scenario makes sense, but I don't think it should live under stellar contract verify.

The way I see it, the verification service is the one responsible for receiving and storing everything needed to build the contract (source code, OS distro, build options, etc.). For that reason I'd keep the SEP-58 path in the CLI strictly tied to the immutable, on-chain contractmetav0, so its output means one specific, auditable thing, and have the service own its build+verification pipeline for everything else.

The real distinction isn't whether the build image is custom (an on-chain metadata can reference a custom image too, and that's equally hard to trust without auditing the image). It's chain of custody: on-chain fields are immutable and tied to the deployer, while user-supplied fields have no such provenance. That's exactly the case you raised; it's the verifier's responsibility to flag those results as "build environment provided by the submitter, not recorded on-chain."

I'd put all of that under out-of-band verification: the registry works with developers to verify contracts and covers everything SEP-58 doesn't (private source, pre-SEP-58 contracts1, etc.). The registry marks the contract verified, and it's ultimately up to users to trust the registry's findings, so the more verification services a developer goes through, the higher the trust.

Footnotes

  1. pre-SEP-58 contracts with public source are, hopefully, the easiest to handle in such a pipeline, especially if they weren't built with a cargo install-generated CLI, because matching distro + stellar-cli + rust + git revision + build opts will likely reproduce the same wasm 🤞.

@leighmcculloch

Copy link
Copy Markdown
Member

A verification service doesn't need to use the cli to verify with data not in the wasm meta. It should use the docker image directly.

@saimeunt

saimeunt commented Jun 8, 2026

Copy link
Copy Markdown

@fnando @leighmcculloch Thanks for your answers, I agree stellar-cli and the stellar contract verify command is strictly a developer-facing CLI that can be used to locally verify a contract and check against what verifiers report.

Verifiers will use their own logic built on top of the stellar-cli Docker image to actually verify contracts and support more scenarios than the standard SEP-58 path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

3 participants