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
The mirror of #34, in the other direction, and not closed by the fix for it.
#34 was that a candidate's SOURCE operand could be pointed at the snapshot constant,
making checkCandidatesAnchoredToSource compare a value with itself. rainlanguage/rain.deploy#242 fixes that by removing DeployCandidate.sourceCreationCode and reading the source operand from vm.getCode(artifactPath) — the compiler's answer, which a consumer cannot supply.
The RECORD operand is still consumer-supplied. DeploySuite.creationCode can be
spelled type(X).creationCode instead of the generated CREATION_CODE constant,
which puts both operands back on the source side. The anchor then compares the
compiler's output against the compiler's output and is satisfied for any contract,
whatever the frozen snapshot on disk actually records.
Why rain-deploy cannot catch it
Symmetrically to #34: while the snapshot and current source agree — the normal
committed state — type(X).creationCode and the generated CREATION_CODE constant
are the same bytes. They diverge only once the snapshot goes stale, which is exactly
the moment the anchor is supposed to fire. No runtime value assertion inside rain-deploy can distinguish the two spellings.
DeploySuite.creationCode's own NatSpec already warns about this. rain.deploy
catches it for ITSELF with an AST test
(RegistryDeploySuitesTest.testCandidatesRecordTheGeneratedConstants) that inspects
how the literal is spelled — a test consumers do not inherit.
Consequence
A consumer that makes this edit has a candidate whose pins are unanchored in both
directions while every check stays green, including the one RainDeployBroadcast.run() runs before it broadcasts.
This repo is not currently in that state: its candidate records CLONE_FACTORY_CREATION_CODE_CANDIDATE, and LibCloneFactoryDeployCandidateTest.testCandidateCreationCodeMatchesSource compares
the generated constant to type(CloneFactory).creationCode directly. That test is
this repo's own and is not something rain-deploy guarantees a consumer has.
Directions (for triage, not a recommendation)
Give consumers the AST check rain.deploy uses on itself, as something inheritable
rather than a per-repo reimplementation.
Have the generator, rather than the consumer, be the only thing that can spell the
record operand.
What
The mirror of #34, in the other direction, and not closed by the fix for it.
#34 was that a candidate's SOURCE operand could be pointed at the snapshot constant,
making
checkCandidatesAnchoredToSourcecompare a value with itself.rainlanguage/rain.deploy#242 fixes that by removing
DeployCandidate.sourceCreationCodeand reading the source operand fromvm.getCode(artifactPath)— the compiler's answer, which a consumer cannot supply.The RECORD operand is still consumer-supplied.
DeploySuite.creationCodecan bespelled
type(X).creationCodeinstead of the generatedCREATION_CODEconstant,which puts both operands back on the source side. The anchor then compares the
compiler's output against the compiler's output and is satisfied for any contract,
whatever the frozen snapshot on disk actually records.
Why rain-deploy cannot catch it
Symmetrically to #34: while the snapshot and current source agree — the normal
committed state —
type(X).creationCodeand the generatedCREATION_CODEconstantare the same bytes. They diverge only once the snapshot goes stale, which is exactly
the moment the anchor is supposed to fire. No runtime value assertion inside
rain-deploycan distinguish the two spellings.DeploySuite.creationCode's own NatSpec already warns about this.rain.deploycatches it for ITSELF with an AST test
(
RegistryDeploySuitesTest.testCandidatesRecordTheGeneratedConstants) that inspectshow the literal is spelled — a test consumers do not inherit.
Consequence
A consumer that makes this edit has a candidate whose pins are unanchored in both
directions while every check stays green, including the one
RainDeployBroadcast.run()runs before it broadcasts.This repo is not currently in that state: its candidate records
CLONE_FACTORY_CREATION_CODE_CANDIDATE, andLibCloneFactoryDeployCandidateTest.testCandidateCreationCodeMatchesSourcecomparesthe generated constant to
type(CloneFactory).creationCodedirectly. That test isthis repo's own and is not something
rain-deployguarantees a consumer has.Directions (for triage, not a recommendation)
rain.deployuses on itself, as something inheritablerather than a per-repo reimplementation.
record operand.
same place The candidate source anchor can be made self-comparing, and the suite stays green #34's guarantee is stated.
Provenance
Surfaced while fixing #34; see rainlanguage/rain.deploy#242, which names this as a
residual hazard it does not close.
Found by adversarial mutation testing (skill 0.35.0).