diff --git a/.config/cspell.json b/.config/cspell.json index e555c6df3..e7a3b99e0 100644 --- a/.config/cspell.json +++ b/.config/cspell.json @@ -7,8 +7,11 @@ "words": [ "ACMRT", "Iseconds", + "merkletree", "nixbuild", "Oxlint", + "sideloaded", + "sideloading", "stefanzweifel", "tarides", "rimraf", diff --git a/scripts/tests/check-cache-regressions.sh b/scripts/tests/check-cache-regressions.sh index 3df59a75a..cdc90cca8 100755 --- a/scripts/tests/check-cache-regressions.sh +++ b/scripts/tests/check-cache-regressions.sh @@ -9,7 +9,7 @@ source ./scripts/lib/ux.sh ./run ./src/tests/cache/simple-regression.ts --bundle --mode check --tarball ./tests/test-artifacts/cache/simple-regression.tar.gz # This pin is generated in ./dump-cache-regressions.sh -ARTIFACT_PIN=2025-10-14T13:40:45-04:00 +ARTIFACT_PIN=2025-10-14T13:59:51-04:00 WORKDIR=tests/test-artifacts/cache/ mkdir -p $WORKDIR @@ -23,5 +23,6 @@ WORKDIR=tests/test-artifacts/cache/$ARTIFACT_PIN ./run ./src/tests/cache/simple-regression.ts --bundle --mode check --tarball $WORKDIR/simple-regression.tar.gz ./run ./src/tests/cache/complex-regression.ts --bundle --mode check --tarball $WORKDIR/complex-regression.tar.gz ./run ./src/tests/cache/rsa-regression.ts --bundle --keep --mode check --tarball $WORKDIR/rsa-regression.tar.gz +./run ./src/tests/cache/sideloading-regression.ts --bundle --keep --mode check --tarball $WORKDIR/sideloading-regression.tar.gz echo "Artifacts checked successfully!" \ No newline at end of file diff --git a/scripts/tests/dump-cache-regressions.sh b/scripts/tests/dump-cache-regressions.sh index adf108fcc..9bf848dd2 100755 --- a/scripts/tests/dump-cache-regressions.sh +++ b/scripts/tests/dump-cache-regressions.sh @@ -11,6 +11,7 @@ mkdir -p $WORKDIR ./run ./src/tests/cache/simple-regression.ts --bundle --mode dump --tarball $WORKDIR/simple-regression.tar.gz ./run ./src/tests/cache/complex-regression.ts --bundle --keep --mode dump --tarball $WORKDIR/complex-regression.tar.gz ./run ./src/tests/cache/rsa-regression.ts --bundle --keep --mode dump --tarball $WORKDIR/rsa-regression.tar.gz +./run ./src/tests/cache/sideloading-regression.ts --bundle --keep --mode dump --tarball $WORKDIR/sideloading-regression.tar.gz gcloud storage cp --recursive $WORKDIR gs://o1js-ci/tests/cache/fixtures/ diff --git a/src/tests/cache/sideloading-regression.ts b/src/tests/cache/sideloading-regression.ts new file mode 100644 index 000000000..2dd498d95 --- /dev/null +++ b/src/tests/cache/sideloading-regression.ts @@ -0,0 +1,67 @@ +import minimist from 'minimist'; +import assert from 'node:assert'; +import { Field, MerkleTree } from 'o1js'; +import { + MainProgramState, + MerkleTreeWitness, + SideloadedProgramProof, + mainProgram, + sideloadedProgram, +} from '../../examples/zkprogram/side-loading/dynamic-keys-merkletree.js'; +import { CacheHarness } from './harness.js'; + +const { mode, tarball } = minimist(process.argv.slice(2)); + +const harness = await CacheHarness({ mode, tarball }); + +const { verificationKey: sideVk } = await sideloadedProgram.compile({ cache: harness.cache }); +harness.check(sideVk, 'sideVk'); + +const { verificationKey: mainVk } = await mainProgram.compile({ cache: harness.cache }); +harness.check(mainVk, 'mainVk'); + +const tree = new MerkleTree(64); +const rootBefore = tree.getRoot(); +tree.setLeaf(1n, sideVk.hash); +const witness = new MerkleTreeWitness(tree.getWitness(1n)); + +// verifying adding a sideloaded program +{ + const { proof } = await mainProgram.addSideloadedProgram( + new MainProgramState({ + treeRoot: rootBefore, + state: Field(0), + }), + sideVk, + witness + ); + const ok = await harness.verify(proof, 'mainVk'); + assert.equal(ok, true, 'adding a sideloaded program should verify'); + + { + const { proof: childProof } = await sideloadedProgram.compute(Field(0), Field(10)); + const { proof: validationProof } = await mainProgram.validateUsingTree( + proof.publicOutput, + proof, + sideVk, + witness, + SideloadedProgramProof.fromProof(childProof) + ); + const ok = await harness.verify(validationProof, 'mainVk'); + assert.equal(ok, true, 'validation using tree should work'); + } + { + const { proof: childProof } = await sideloadedProgram.assertAndAdd(Field(0), Field(10)); + const { proof: validationProof } = await mainProgram.validateUsingTree( + proof.publicOutput, + proof, + sideVk, + witness, + SideloadedProgramProof.fromProof(childProof) + ); + const ok = await harness.verify(validationProof, 'mainVk'); + assert.equal(ok, true, 'validation on assert and add should work'); + } +} + +await harness.finish();