Skip to content

Commit 991fe58

Browse files
committed
feat(standard-contracts): pin compiled artifacts for release-branch reproducibility check
1 parent 7e4e2fa commit 991fe58

7 files changed

Lines changed: 106 additions & 0 deletions

File tree

yarn-project/.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ noir-contracts.js/**/*.json
55
noir-contracts.js/src
66
noir-test-contracts.js/**/*.json
77
noir-test-contracts.js/src
8+
standard-contracts/src/**/pinned/*.json
89
noir-protocol-circuits-types/src/target/*
910
*.md
1011
end-to-end/src/fixtures/dumps/*.json

yarn-project/standard-contracts/src/auth-registry/pinned/AuthRegistry.artifact.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Release-branch reproducibility gate for the auth_registry contract.
2+
//
3+
// Symmetric to the freshness gate in `derive_auth_registry.test.ts`: that test asserts the
4+
// committed `.nr` stamp / TS twin stay aligned with the freshly-built artifact. This test goes
5+
// one level further and pins the *full artifact JSON* so a release branch can detect any
6+
// unintended bytecode drift between the pinned release artifact and the current build output.
7+
//
8+
// TODO: enable on release branches. Run manually with:
9+
// yarn workspace @aztec/standard-contracts test src/auth-registry/reproducibility.test.ts
10+
// and then drop the `it.skip` once the release branch is cut.
11+
import { createHash } from 'node:crypto';
12+
import { promises as fs } from 'node:fs';
13+
import path from 'node:path';
14+
import { fileURLToPath } from 'node:url';
15+
16+
import { ARTIFACT_PATH } from './derive_auth_registry.js';
17+
18+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
19+
const PINNED_ARTIFACT_PATH = path.join(__dirname, 'pinned/AuthRegistry.artifact.json');
20+
21+
const REGEN_HINT =
22+
'auth_registry pinned artifact is stale; if this drift is intentional on a release branch, copy ' +
23+
`${ARTIFACT_PATH} over ${PINNED_ARTIFACT_PATH} and commit the result.`;
24+
25+
describe('auth_registry artifact reproducibility', () => {
26+
it.skip('committed pinned artifact matches the freshly-built artifact byte-for-byte', async () => {
27+
const [pinned, fresh] = await Promise.all([fs.readFile(PINNED_ARTIFACT_PATH), fs.readFile(ARTIFACT_PATH)]);
28+
const pinnedHash = createHash('sha256').update(pinned).digest('hex');
29+
const freshHash = createHash('sha256').update(fresh).digest('hex');
30+
if (pinnedHash !== freshHash) {
31+
throw new Error(`${REGEN_HINT}\n pinned sha256 = ${pinnedHash}\n fresh sha256 = ${freshHash}`);
32+
}
33+
});
34+
});

yarn-project/standard-contracts/src/multi-call-entrypoint/pinned/MultiCallEntrypoint.artifact.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Release-branch reproducibility gate for the multi_call_entrypoint contract.
2+
//
3+
// Symmetric to the freshness gate in `derive_multi_call_entrypoint.test.ts`: that test asserts
4+
// the committed TS twin stays aligned with the freshly-built artifact. This test goes one level
5+
// further and pins the *full artifact JSON* so a release branch can detect any unintended
6+
// bytecode drift between the pinned release artifact and the current build output.
7+
//
8+
// TODO: enable on release branches. Run manually with:
9+
// yarn workspace @aztec/standard-contracts test src/multi-call-entrypoint/reproducibility.test.ts
10+
// and then drop the `it.skip` once the release branch is cut.
11+
import { createHash } from 'node:crypto';
12+
import { promises as fs } from 'node:fs';
13+
import path from 'node:path';
14+
import { fileURLToPath } from 'node:url';
15+
16+
import { ARTIFACT_PATH } from './derive_multi_call_entrypoint.js';
17+
18+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
19+
const PINNED_ARTIFACT_PATH = path.join(__dirname, 'pinned/MultiCallEntrypoint.artifact.json');
20+
21+
const REGEN_HINT =
22+
'multi_call_entrypoint pinned artifact is stale; if this drift is intentional on a release branch, copy ' +
23+
`${ARTIFACT_PATH} over ${PINNED_ARTIFACT_PATH} and commit the result.`;
24+
25+
describe('multi_call_entrypoint artifact reproducibility', () => {
26+
it.skip('committed pinned artifact matches the freshly-built artifact byte-for-byte', async () => {
27+
const [pinned, fresh] = await Promise.all([fs.readFile(PINNED_ARTIFACT_PATH), fs.readFile(ARTIFACT_PATH)]);
28+
const pinnedHash = createHash('sha256').update(pinned).digest('hex');
29+
const freshHash = createHash('sha256').update(fresh).digest('hex');
30+
if (pinnedHash !== freshHash) {
31+
throw new Error(`${REGEN_HINT}\n pinned sha256 = ${pinnedHash}\n fresh sha256 = ${freshHash}`);
32+
}
33+
});
34+
});

yarn-project/standard-contracts/src/public-checks/pinned/PublicChecks.artifact.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Release-branch reproducibility gate for the public_checks contract.
2+
//
3+
// Symmetric to the freshness gate in `derive_public_checks.test.ts`: that test asserts the
4+
// committed `.nr` stamp / TS twin stay aligned with the freshly-built artifact. This test goes
5+
// one level further and pins the *full artifact JSON* so a release branch can detect any
6+
// unintended bytecode drift between the pinned release artifact and the current build output.
7+
//
8+
// TODO: enable on release branches. Run manually with:
9+
// yarn workspace @aztec/standard-contracts test src/public-checks/reproducibility.test.ts
10+
// and then drop the `it.skip` once the release branch is cut.
11+
import { createHash } from 'node:crypto';
12+
import { promises as fs } from 'node:fs';
13+
import path from 'node:path';
14+
import { fileURLToPath } from 'node:url';
15+
16+
import { ARTIFACT_PATH } from './derive_public_checks.js';
17+
18+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
19+
const PINNED_ARTIFACT_PATH = path.join(__dirname, 'pinned/PublicChecks.artifact.json');
20+
21+
const REGEN_HINT =
22+
'public_checks pinned artifact is stale; if this drift is intentional on a release branch, copy ' +
23+
`${ARTIFACT_PATH} over ${PINNED_ARTIFACT_PATH} and commit the result.`;
24+
25+
describe('public_checks artifact reproducibility', () => {
26+
it.skip('committed pinned artifact matches the freshly-built artifact byte-for-byte', async () => {
27+
const [pinned, fresh] = await Promise.all([fs.readFile(PINNED_ARTIFACT_PATH), fs.readFile(ARTIFACT_PATH)]);
28+
const pinnedHash = createHash('sha256').update(pinned).digest('hex');
29+
const freshHash = createHash('sha256').update(fresh).digest('hex');
30+
if (pinnedHash !== freshHash) {
31+
throw new Error(`${REGEN_HINT}\n pinned sha256 = ${pinnedHash}\n fresh sha256 = ${freshHash}`);
32+
}
33+
});
34+
});

0 commit comments

Comments
 (0)