Repository navigation
Bump deps to prerelease, add ecdsa tests - #145
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
| // Query ctx | ||
| const modifiedTxCtx: QueryContext = { | ||
| ...ctx.currentQueryContext, | ||
| ...ctx.callContext.currentQueryContext, |
There was a problem hiding this comment.
🔴 blocking: the newCtx literal just below (lines 142-149) is still the pre-0.18 flat shape. Under 0.18 CircuitContext requires callContext, queryContexts, gasCosts, callProofDataTrace and events, so that object is a type error (TS2353: 'currentQueryContext' does not exist in type 'CircuitContext<…>', reproduced by compiling the same shape under src/). It passes at runtime only because toEqual(newCtx) compares two plain objects, so the only test covering setContext now asserts nothing about a context the runtime would accept.
Unblocks: rebuild newCtx via createCircuitContext (or copyCircuitContext(ctx) plus the override) so the assertion runs against a real 0.18 context.
added by claude (dev3-midnight-basic-review)
| // Query ctx | ||
| const modifiedTxCtx: QueryContext = { | ||
| ...ctx.currentQueryContext, | ||
| ...ctx.callContext.currentQueryContext, |
There was a problem hiding this comment.
🔴 blocking: test/** is never typechecked, which is why the broken literal above ships green. packages/simulator/tsconfig.types.json sets include: ["src/**/*"], and its exclude lists "tests" while the directory is actually test. This PR hand-migrates five test files to a new context shape with no type verification, and one of them is already wrong.
Unblocks: prove test/** compiles under 0.18. Cheapest route is a tsconfig.test.json wired into the types turbo task.
added by claude (dev3-midnight-basic-review)
| // (`callContext` + per-contract `queryContexts`/`gasCosts`). Build it via | ||
| // the runtime's `createCircuitContext` factory rather than a hand-rolled | ||
| // literal so every required field is populated correctly. | ||
| this.context = createCircuitContext<P>( |
There was a problem hiding this comment.
🔴 blocking: this drops the optional time arg, so simulated block time changes from a fixed 0 to wall-clock. Upstream defaults it to Math.floor(Date.now() / 1000) and stamps it into initialQueryContext.block.secondsSinceEpoch; under 0.16 the hand-rolled new QueryContext(...) left it at 0n (verified against the installed 0.16). Every downstream suite reading kernel.blockTime() flips to a non-reproducible clock, with no option, no test and no note in the PR body. useCircuitContextSender compounds it: it drops the existing callContext.time and re-stamps mid-flow.
Unblocks, any one of:
- pass
timeexplicitly (0preserves today's behaviour), - add
SimulatorOptions.timedefaulting to0, thread it throughinit()anduseCircuitContextSender, and pin it with a test, - or confirm wall-clock is intended and document it as a breaking behaviour change for consumers.
added by claude (dev3-midnight-basic-review)
| public context: CircuitContext<P>; | ||
| // Assigned by the async `init()`; the manager is always constructed and then | ||
| // awaited (`init`) before any circuit call reads the context. | ||
| public context!: CircuitContext<P>; |
There was a problem hiding this comment.
🔴 blocking: two-phase construction with no guard. CircuitContextManager is a barrel export, so an external caller who skips init() gets Cannot read properties of undefined (reading 'callContext') instead of a useful message. Pre-PR the constructor always returned a usable object; this PR is what makes it constructible-but-unusable.
Unblocks: back context with a getter that throws "CircuitContextManager: call init() before use". Same applies to contractAddress! in createDrySimulator.ts.
added by claude (dev3-midnight-basic-review)
| * which includes private state, public (ledger) state, zswap local state, and transaction context. | ||
| */ | ||
| /** Shape of a compiled contract's constructor result (sync or async in 0.18). */ | ||
| type InitialStateResult<P> = { |
There was a problem hiding this comment.
🔴 blocking: this local InitialStateResult exists because IMinimalContract.initialState (src/types/Contract.ts:22-32) still declares the sync-only return type. The canonical interface now lies about 0.18, and anything else typed against it gets the wrong shape.
Unblocks: move the T | Promise<T> union onto IMinimalContract and have this file reuse it rather than redeclaring.
added by claude (dev3-midnight-basic-review)
| if: ${{ inputs.skip-compact != 'true' }} | ||
| shell: bash | ||
| env: | ||
| VER: ${{ inputs.compact-prerelease }} |
There was a problem hiding this comment.
🔴 blocking: the compact-prerelease input is non-functional as written. VER is scoped to this step, and test/setup.ts:55 reads process.env.COMPACTC_VERSION, which nothing sets. Override the input and CI installs one toolchain while the tests compile with the hardcoded +0.33.0-rc.2.
Unblocks: export it, e.g. echo "COMPACTC_VERSION=$VER" >> "$GITHUB_ENV" in this step.
added by claude (dev3-midnight-basic-review)
| [ -z "$PLAT" ] && PLAT="$(uname -m)-unknown-linux-musl" | ||
| DEST="$HOME/.compact/versions/$VER/$PLAT" | ||
| mkdir -p "$DEST" | ||
| curl -fsSL -o /tmp/compactc.zip \ |
There was a problem hiding this comment.
🔴 blocking (downgrade if the team disagrees): the pre-release compiler is downloaded, chmod +x'd and executed with no integrity check. Every other action in this file is pinned by commit SHA and the repo runs OpenSSF scorecard, so this is a step down in posture on the one artifact that runs arbitrary code in CI.
Unblocks: pin a sha256 next to compact-prerelease and sha256sum -c before unzip. If the release publishes no checksum, say so and I'll drop this to a followup.
added by claude (dev3-midnight-basic-review)
| // (compactc 0.31.x) emits code expecting compact-runtime 0.16.0, which the | ||
| // 0.18.0-rc.1 runtime this package now depends on rejects at load time. | ||
| // Override via COMPACTC_VERSION if a newer pinned toolchain is installed. | ||
| const compilerVersion = process.env.COMPACTC_VERSION ?? '0.33.0-rc.2'; |
There was a problem hiding this comment.
🔴 blocking: the compiler version is now part of what the artifacts depend on, but not part of the cache key. The staleness check above (lines 33-41) compares artifact mtime against source mtime only, so anyone with an existing clone keeps their 0.31-compiled artifacts and hits a load-time rejection against the 0.18 runtime. CI is unaffected (the test turbo task is cache: false and the checkout is clean), so this lands on every local dev instead.
Unblocks: write compilerVersion (and the zkir flag) into outputDir and recompile on mismatch.
added by claude (dev3-midnight-basic-review)
| const result = fn(context(), ...args).result; | ||
| ) => { result: unknown } | Promise<{ result: unknown }>; | ||
| // 0.18 circuits are async; `await` also tolerates the older sync shape. | ||
| const { result } = await fn(context(), ...args); |
There was a problem hiding this comment.
❔ question: does 0.33-generated circuit code copy the context before executing? The pure proxy is wired with () => this.circuitContext (createDrySimulator.ts:105), so circuits receive the live base context, and 0.18's finalizeCallProofData pushes into callProofDataTrace in place. If generated code does not copyCircuitContext first, every circuits.pure.* call permanently appends trace, events and gas to the persistent context even though its result context is discarded. I could not get a 0.33-compiled artifact to check this.
added by claude (dev3-midnight-basic-review)
|
|
||
| this.context = { | ||
| currentPrivateState, | ||
| // compact-runtime 0.18 restructured `CircuitContext` into a call-tree |
There was a problem hiding this comment.
❔ question (non-blocking): heads-up on an upstream quirk this comment glosses. createCircuitContext calls createCallContext twice and seeds queryContexts[addr] / gasCosts[addr] from the first while callContext is the second, so context.queryContexts[addr] !== context.callContext.currentQueryContext from birth. Nothing here reads the former today. Worth confirming that still holds if the simulator grows a cross-contract path.
added by claude (dev3-midnight-basic-review)
| } from '../fixtures/sample-contracts/witnesses/EcdsaWitnesses'; | ||
|
|
||
| /** Runtime shape the generated circuits accept for an ECDSA signature. */ | ||
| export type Secp256k1EcdsaSignature = { r: bigint; s: bigint }; |
There was a problem hiding this comment.
❔ question (non-blocking): Ecdsa.compact:9 re-exports Secp256k1EcdsaSignature and Secp256k1Point "so the generated TS exposes them", but this file hand-rolls { r: bigint; s: bigint } and imports Secp256k1Point from @midnight-ntwrk/compact-runtime. Is the re-export dead, or should the simulator consume the generated types?
added by claude (dev3-midnight-basic-review)
| // compact-runtime 0.18: the caller-scoped fields live on `callContext`. | ||
| // Copy (shallow-clones `callContext`) before overriding the Zswap local | ||
| // state so the base context is left untouched. | ||
| const ctx = copyCircuitContext(baseCtx) as CircuitContext<P>; |
There was a problem hiding this comment.
🔵 followup (non-blocking): copyCircuitContext is marked @internal in the runtime's typings, so a patch release could drop it without notice. Nothing better to do here (hand-rolling the copy is worse). Worth a note in the comment above and an upstream ask to make it public.
added by claude (dev3-midnight-basic-review)
| // compact-runtime 0.18: `createCircuitContext` populates the full call-tree | ||
| // shape (callContext + queryContexts/gasCosts) and derives an empty Zswap | ||
| // local state from `sender`. | ||
| return createCircuitContext<P>( |
There was a problem hiding this comment.
🔵 followup (non-blocking): neither useCircuitContext nor useCircuitContextSender is referenced anywhere in packages/, and neither is exported from src/index.ts. Checked origin/beta: already dead and unexported before this PR, so deleting it is pre-existing cleanup rather than yours. Flagging only because it got hand-migrated to the call-tree shape untested. Delete it, or export and cover it.
added by claude (dev3-midnight-basic-review)
| */ | ||
| public getPrivateState(): P { | ||
| return this.circuitContext.currentPrivateState; | ||
| return this.circuitContext.callContext.currentPrivateState as P; |
There was a problem hiding this comment.
⚪ nitpick: as P casts over PS | undefined. Harmless once init() has run, but it is the same hole as the missing init guard: before init() this returns undefined typed as P.
added by claude (dev3-midnight-basic-review)
| * after construction, before any circuit call. Split out from the | ||
| * constructor because compact-runtime 0.18 made `initialState` async. | ||
| */ | ||
| async init(): Promise<this> { |
There was a problem hiding this comment.
⚪ nitpick: docs went stale with the async migration. Line 15 still calls this the "Internal synchronous simulator primitive"; DryBackend.ts:38-42 still says it "wraps the synchronous result in a resolved promise" and that dry behaviour is preserved "byte-for-byte"; the exported SyncSimulator type name and its (...args) => unknown circuit signature are both misleading now.
added by claude (dev3-midnight-basic-review)
| const compilerVersion = process.env.COMPACTC_VERSION ?? '0.33.0-rc.2'; | ||
| // secp256k1 primitives (e.g. secp256k1EcdsaVerify) exist only in the ZKIR v3 | ||
| // backend, so contracts that use them must opt in; others stay on the default. | ||
| const usesSecp256k1 = /secp256k1/i.test(readFileSync(inputPath, 'utf8')); |
There was a problem hiding this comment.
⚪ nitpick: this sniffs the raw file, so a contract that mentions secp256k1 only in a comment gets --feature-zkir-v3, and one that pulls it in through an import does not. An explicit per-fixture flag beside CONTRACT_FILES would be less surprising as the fixture set grows.
added by claude (dev3-midnight-basic-review)
| for (let i = 0; i < length; i++) { | ||
| out[i] = Number(v & 0xffn); | ||
| v >>= 8n; | ||
| } |
There was a problem hiding this comment.
⚪ nitpick: byte order matches 0.16 (little-endian, checked against the installed 0.16 casts.js), but the original threw range error … does not fit into n bytes while this silently truncates. Only small counters go through it today, so nothing is wrong now, but a truncating helper in a test can green-light a wrong value later. if (v !== 0n) throw … after the loop restores parity.
added by claude (dev3-midnight-basic-review)
| // A zero-filled byte array of `length`. (Previously `convertFieldToBytes(length, | ||
| // 0n, '')` from compact-runtime 0.16, which was removed in 0.18; a `new | ||
| // Uint8Array` is zero-initialized and behaves identically here.) | ||
| export const zeroUint8Array = (length = 32) => new Uint8Array(length); |
There was a problem hiding this comment.
⚪ nitpick: third near-identical zero/field-byte helper in the tree, alongside src/signers/Signers.ts:41 and the local convertFieldToBytes in test/integration/SampleZOwnable.test.ts. Worth collapsing into one shared test util.
added by claude (dev3-midnight-basic-review)
There was a problem hiding this comment.
Thank you @andrew-fleming, looking good! left comments and questions.
Also marked the beta branch as a protected branch.
0xisk
left a comment
There was a problem hiding this comment.
Thank you @andrew-fleming ! Will fix the rest in the next PR.
* fix(simulator): pin simulated block time to zero compact-runtime 0.18 defaults `createCircuitContext`'s `time` to wall-clock, where the hand-rolled 0.16 `QueryContext` left it at 0. Any suite reading `kernel.blockTime()` silently became non-reproducible. Threads an explicit `time` from `BaseSimulatorOptions` through to the runtime factory, defaulting to 0 to restore the previous behaviour. * refactor(simulator): drop the dead circuit-context helpers `useCircuitContext` and `useCircuitContextSender` had no callers and were never exported from the barrel, so they were unreachable before this migration and got hand-ported to the 0.18 call-tree shape untested. * fix(simulator): guard context reads before init() 0.18 split construction from state building, so a caller that skipped `init()` got `Cannot read properties of undefined (reading 'callContext')`. Both `CircuitContextManager.context` and the simulator's `contractAddress` now throw a named error instead. * fix(simulator): declare initialState async on IMinimalContract The canonical interface still promised the sync-only 0.16 return type, so anything typed against it got the wrong shape and `CircuitContextManager` carried a private redeclaration to compensate. * fix(simulator): typecheck the test tree `tsconfig.types.json` compiled `src/**` only, and its `exclude` named a `tests` directory that does not exist, so nothing verified the test tree. Adding a project that covers it surfaced 74 errors, of which the load-bearing one is in `src/`: 0.18 circuits return `Promise<CircuitResults>`, which the `ContextlessCircuits` / `AsyncCircuits` conditionals did not match, collapsing every entry on `circuits.pure` and `circuits.impure` to `never`. * src: match the promised circuit shape; keep the anonymous class's address field underscore-public for declaration emit * test: give relative imports the `.js` extension nodenext requires * wiring: run both projects under `yarn types`, and let turbo see the test tree so a regression is not cached away * fix(simulator): build the setContext fixture as a real 0.18 context The replacement context was a hand-rolled literal in the pre-0.18 flat shape, so `setContext`'s only test asserted against a context the runtime would reject. `toEqual` compared two plain objects and passed anyway. Rebuilds it through `createCircuitContext` and asserts identity plus the two fields the test is about. Exporting `BackendDeps` is required for the same reason: it appears in `create`/`_create`, so an exported binding assigned from `createSimulator(...)` could not name it (TS4023). * fix(ci): make the prerelease compiler input functional and verified * `COMPACTC_VERSION` is now exported to `$GITHUB_ENV`. `VER` was step-scoped, so `test/setup.ts` never saw it: overriding the input installed one toolchain while the fixtures compiled with the hardcoded default. * The archive is checked against a pinned SHA-256 before it is unpacked and executed. The release publishes no checksum file, so the digests are pinned per platform here; overriding the version requires passing its digest. * fix(simulator): key the fixture cache on the compiler The staleness check compared artifact mtime against source mtime only, so an existing clone kept its 0.31-compiled artifacts and hit a load-time rejection against the 0.18 runtime. CI never saw it: the `test` turbo task is uncached and the checkout is clean. Artifacts now carry a stamp of the compiler version and the zkir flag, and recompile when it does not match. The flag also moves onto the fixture list, replacing a `secp256k1` regex over the source that a mention in a comment was enough to trip. * test(simulator): collapse the field-to-bytes helpers Two near-identical copies existed in the test tree. The one in `SampleZOwnable.test.ts` silently truncated where the runtime helper it replaced threw, so a wrong value would read as a passing assertion. Keeps one in the shared test utils, with the range check restored, and derives `zeroUint8Array` from it. `Signers.ts` keeps its own copy: `src` cannot import from `test`. * test(simulator): consume the generated secp256k1 types The `Ecdsa.compact` re-export is live: the artifact's `index.d.ts` declares both `Secp256k1EcdsaSignature` and `Secp256k1Point`. The simulator hand-rolled the signature struct and took the point from the runtime instead, so a change to the generated shape would not surface here. * docs(simulator): correct the sync-era comments The async migration left the docs describing a synchronous engine: the dry primitive called "synchronous", `DryBackend` said it wraps a synchronous result in a resolved promise and preserves dry behaviour "byte-for-byte", and the `SyncSimulator` name now describes nothing. Renaming the exported type is a breaking change, so it keeps the name with a `@remarks` note. Also records that `copyCircuitContext` is `@internal` upstream. * ci(turbo): declare COMPACTC_VERSION on the test task The setup action exports it and `test/setup.ts` reads it, but the task never declared it. Pass-through happens to work on turbo 2.9, so this only pins the behaviour against a stricter env mode. * fix(ci): compile fixtures before the type check `yarn types` now covers `test/**`, which imports the generated artifacts, but `checks.yml` runs it before `yarn test` — the only thing that compiled them. It passed locally only because the artifacts were already on disk. Lifts fixture compilation into its own turbo task that `types` depends on. `test/setup.ts` gains a direct entry point so the task does not have to go through vitest; vitest's `globalSetup` still calls the same function.
* ci(codeql): run analysis on beta (#146) The "Main Branch Protection" ruleset covers main and beta, and its code_scanning rule requires CodeQL results. CodeQL only triggered on main, so PRs into beta were blocked waiting on an analysis that never ran. * Bump deps to prerelease, add ecdsa tests (#145) * add tmp runtime dep * update to 0.18 runtime * wire sim to 0.18-rc/ledger-9 stack * fix fmt * add ecdsa tests * add pre-release compact install * fix(simulator): clear the #145 review comments (#147) * fix(simulator): pin simulated block time to zero compact-runtime 0.18 defaults `createCircuitContext`'s `time` to wall-clock, where the hand-rolled 0.16 `QueryContext` left it at 0. Any suite reading `kernel.blockTime()` silently became non-reproducible. Threads an explicit `time` from `BaseSimulatorOptions` through to the runtime factory, defaulting to 0 to restore the previous behaviour. * refactor(simulator): drop the dead circuit-context helpers `useCircuitContext` and `useCircuitContextSender` had no callers and were never exported from the barrel, so they were unreachable before this migration and got hand-ported to the 0.18 call-tree shape untested. * fix(simulator): guard context reads before init() 0.18 split construction from state building, so a caller that skipped `init()` got `Cannot read properties of undefined (reading 'callContext')`. Both `CircuitContextManager.context` and the simulator's `contractAddress` now throw a named error instead. * fix(simulator): declare initialState async on IMinimalContract The canonical interface still promised the sync-only 0.16 return type, so anything typed against it got the wrong shape and `CircuitContextManager` carried a private redeclaration to compensate. * fix(simulator): typecheck the test tree `tsconfig.types.json` compiled `src/**` only, and its `exclude` named a `tests` directory that does not exist, so nothing verified the test tree. Adding a project that covers it surfaced 74 errors, of which the load-bearing one is in `src/`: 0.18 circuits return `Promise<CircuitResults>`, which the `ContextlessCircuits` / `AsyncCircuits` conditionals did not match, collapsing every entry on `circuits.pure` and `circuits.impure` to `never`. * src: match the promised circuit shape; keep the anonymous class's address field underscore-public for declaration emit * test: give relative imports the `.js` extension nodenext requires * wiring: run both projects under `yarn types`, and let turbo see the test tree so a regression is not cached away * fix(simulator): build the setContext fixture as a real 0.18 context The replacement context was a hand-rolled literal in the pre-0.18 flat shape, so `setContext`'s only test asserted against a context the runtime would reject. `toEqual` compared two plain objects and passed anyway. Rebuilds it through `createCircuitContext` and asserts identity plus the two fields the test is about. Exporting `BackendDeps` is required for the same reason: it appears in `create`/`_create`, so an exported binding assigned from `createSimulator(...)` could not name it (TS4023). * fix(ci): make the prerelease compiler input functional and verified * `COMPACTC_VERSION` is now exported to `$GITHUB_ENV`. `VER` was step-scoped, so `test/setup.ts` never saw it: overriding the input installed one toolchain while the fixtures compiled with the hardcoded default. * The archive is checked against a pinned SHA-256 before it is unpacked and executed. The release publishes no checksum file, so the digests are pinned per platform here; overriding the version requires passing its digest. * fix(simulator): key the fixture cache on the compiler The staleness check compared artifact mtime against source mtime only, so an existing clone kept its 0.31-compiled artifacts and hit a load-time rejection against the 0.18 runtime. CI never saw it: the `test` turbo task is uncached and the checkout is clean. Artifacts now carry a stamp of the compiler version and the zkir flag, and recompile when it does not match. The flag also moves onto the fixture list, replacing a `secp256k1` regex over the source that a mention in a comment was enough to trip. * test(simulator): collapse the field-to-bytes helpers Two near-identical copies existed in the test tree. The one in `SampleZOwnable.test.ts` silently truncated where the runtime helper it replaced threw, so a wrong value would read as a passing assertion. Keeps one in the shared test utils, with the range check restored, and derives `zeroUint8Array` from it. `Signers.ts` keeps its own copy: `src` cannot import from `test`. * test(simulator): consume the generated secp256k1 types The `Ecdsa.compact` re-export is live: the artifact's `index.d.ts` declares both `Secp256k1EcdsaSignature` and `Secp256k1Point`. The simulator hand-rolled the signature struct and took the point from the runtime instead, so a change to the generated shape would not surface here. * docs(simulator): correct the sync-era comments The async migration left the docs describing a synchronous engine: the dry primitive called "synchronous", `DryBackend` said it wraps a synchronous result in a resolved promise and preserves dry behaviour "byte-for-byte", and the `SyncSimulator` name now describes nothing. Renaming the exported type is a breaking change, so it keeps the name with a `@remarks` note. Also records that `copyCircuitContext` is `@internal` upstream. * ci(turbo): declare COMPACTC_VERSION on the test task The setup action exports it and `test/setup.ts` reads it, but the task never declared it. Pass-through happens to work on turbo 2.9, so this only pins the behaviour against a stricter env mode. * fix(ci): compile fixtures before the type check `yarn types` now covers `test/**`, which imports the generated artifacts, but `checks.yml` runs it before `yarn test` — the only thing that compiled them. It passed locally only because the artifacts were already on disk. Lifts fixture compilation into its own turbo task that `types` depends on. `test/setup.ts` gains a direct entry point so the task does not have to go through vitest; vitest's `globalSetup` still calls the same function. * ci: add a beta release channel (#150) * ci: add a beta release channel Prerelease versions publish under the `beta` npm dist-tag, stable ones under `latest`. The publish workflow derives the tag from the version string alone, so a prerelease cannot take over `latest` no matter which ref triggered the run. Yarn's `version` has no `--preid`, so a pre* strategy off a stable version lands a bare counter (0.3.1 -> 0.3.2-0). The bump step relabels that once to `-beta.0`; yarn carries the identifier forward on every later prerelease. * docs: add a beta graduation cycle example * build: upgrade to compact toolchain 0.34.0 (#152) 0.34.0 is the first stable release carrying the secp256k1 primitives and ledger 9, so the prerelease-compiler bridge in the setup action is no longer needed. `setup-compact-action` passes the version straight to `compact update`, which serves 0.34.0. Generated artifacts assert the runtime minor at load time, so the compact-runtime pin moves 0.18.0-rc.1 -> 0.19.0 in lockstep with the compiler. midnight-js goes to 5.0.0-beta.7 to stay on the current beta line. 0.34.0 makes `Secp256k1Point` an internally handled type that a contract can no longer re-export. The Ecdsa fixture drops it from its export list and `EcdsaSimulator` sources the type from compact-runtime, which is where the generated artifact now references it. * fix(simulator): async proxy types and live address binding (#154) * fix(simulator): type circuit proxies as promise-returning The 0.18 migration made every circuit proxy async but left ContextlessCircuits mapping to the bare result, so a consumer typed `boolean` received `Promise<boolean>` and any truthiness check passed vacuously. The cast on the Proxy return masked the mismatch from tsc. * Circuit.ts: map ContextlessCircuits to `Promise<R>`; AsyncCircuits becomes an alias so the two cannot drift. * create-contract.type-test.ts: pin the promise mapping for both the 0.18 promise shape and the 0.16 sync shape; fails on the old mapping. * createDrySimulator.ts: narrow the init guard to `=== undefined` and note why the private-state cast is sound. * AbstractSimulator.ts: same cast note. * fix(simulator): bind live pure evaluation to deployed address In live mode the local evaluator was built before the LiveContext resolved, so it kept the dummy address in its circuit context while the public simulator reported the deployed one. Resolve the context first, seed the evaluator with the deployed address, and reject an explicit contractAddress that disagrees with it. The deployed address now reaches the runtime, so a live harness must supply a parseable one; the mock worlds in the tests move from a made-up string to dummyContractAddress(). * docs(release): hyphenate and align prerelease wording --------- Co-authored-by: Andrew Fleming <fleming.andrew@protonmail.com>
Targeting
betabranch with unstable prerelease deps and necessary changes. This PR also includes ecdsa tests from the new deps