Skip to content

build(node): add reproducible build target for morphnode - #1067

Open
FletcherMan wants to merge 6 commits into
release/0.6.3from
build/morphnode-repro
Open

FletcherMan wants to merge 6 commits into
release/0.6.3from
build/morphnode-repro

Conversation

@FletcherMan

@FletcherMan FletcherMan commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

make morphnode embeds the wall-clock build time, so the same source tree produces a different binary every time.

Adds make morphnode-repro: same binary, byte-identical across builds. It is just $(MAKE) morphnode REPRO=1, so there is only one build recipe. make morphnode is unchanged and still reports the real build time.

REPRO=1 removes five sources of variance:

Source Fix
Build timestamp BuildTime set to the constant reproducible
Go build ID (varies with build cache) -buildid=
Absolute checkout paths -trimpath
VCS stamps (vcs.modified flips on a dirty tree, and the block is omitted entirely when .git is absent) -buildvcs=false
Random Mach-O LC_UUID on macOS -extldflags=-Wl,-no_uuid, darwin only

Commit time is deliberately not used for BuildTime — a reproducible artifact has no build time, and reusing the commit time would misreport what the field means. Use Git Commit / Version to identify the source.

MakefileEc2.mk switches the mainnet node target over to morphnode-repro and prints the sha256 of the artifact before upload.

Verified on macOS/arm64, go1.24.0, including after go clean -cache: two runs of morphnode-repro give an identical sha256, two runs of morphnode do not.

Note: cross-machine reproducibility also needs a fixed toolchain, since morphnode is built with cgo.

`make morphnode` embeds the wall-clock build time, so the same source tree
produces a different binary on every build. Add `make morphnode-repro`, which
builds the same binary but byte-identically:

  - BuildTime becomes the constant "reproducible"; a reproducible artifact has
    no meaningful build time, and reusing the commit time here would misreport
    what BuildTime means
  - -buildid= drops the Go build ID, which varies with the build cache state
  - -trimpath drops absolute checkout paths
  - -no_uuid drops the random LC_UUID that Apple's linker stamps into every
    Mach-O binary (Linux's GNU build-id is already content-derived)

Without -no_uuid the binaries still differed, in 47 bytes: the UUID itself plus
the ad-hoc code signature covering it.

`make morphnode` is deliberately left untouched, so its BuildTime keeps
reporting when the binary was actually built.

Co-authored-by: Cursor <cursoragent@cursor.com>
@FletcherMan
FletcherMan requested a review from a team as a code owner September 15, 2026 01:41
@FletcherMan
FletcherMan requested a review from twcctop September 15, 2026 01:41
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 96fcd91a-83c1-432f-91b4-ed87fd5d761f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

MarvelFisher and others added 3 commits September 15, 2026 17:23
`go build` embeds vcs.revision, vcs.time and vcs.modified. They are stable for
a fixed commit, but vcs.modified flips with a dirty tree and the whole block is
silently omitted when .git is absent — so the same source can still produce
different binaries depending on how the build environment is set up. Docker
builds that exclude .git hit exactly this.

Version and GitCommit already carry the same information, so drop the stamps.

Co-authored-by: Cursor <cursoragent@cursor.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

Claude Code Review is paused for this repository. To reconnect it, an admin of this repository's GitHub organization (or the account owner, for personal repositories) who can also manage your Claude organization's Code Review settings needs to re-link GitHub in Code Review settings. This is a one-time step.

Tip: disable this comment in your organization's Code Review settings.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants