Skip to content

Conversation

@0x471
Copy link

@0x471 0x471 commented Oct 11, 2025

Description

Implements a TypeScript local ledger for testing zkApps, replacing the existing OCaml implementation when running with the local blockchain

Attempt to resolve #2378

Blocking Issue

The following parity test fails due to a mismatch in receiptChainHash values between the OCaml and TypeScript implementations:
local-ledger-parity.test.ts, "should apply simple nonce increment transaction identically"

OCaml: 14085731157301269295156321426508462010218801998705391518505779678237624663296
TypeScript: 28899291169992443053148564175730552295359313139162430887426314586130777313107

Attempts

  • Tried varying packing order (fields-first vs packed-first).
  • Experimented with different hash prefixes ("CodaReceiptUC", "CodaReceiptUC*******").
  • Used both hashWithPrefix and manual double salting.
  • Packed all inputs into a single array to control order explicitly.

Reproduction Steps

npm run build:dev
node --experimental-vm-modules node_modules/jest/bin/jest.js \
  dist/node/lib/mina/v1/local-ledger-parity.test.js \
  --testNamePattern="should apply simple nonce increment transaction identically"

We expect all assertions to pass but receiptChainHash comparison fails

@0x471 0x471 requested review from a team as code owners October 11, 2025 06:04
@0x471 0x471 requested review from 45930 and querolita October 11, 2025 06:04
@0x471 0x471 marked this pull request as draft October 11, 2025 06:04
Comment on lines -274 to +277
return emptyHashWithPrefix('CodaReceiptEmpty');
// OCaml uses legacy poseidon: Random_oracle.Legacy.(salt "CodaReceiptEmpty" |> digest)
// returns a different value than Poseidon w/ emptyHashWithPrefix
// Using the correct legacy value to match OCaml's Receipt.Chain_hash.empty
return Field('4836908137238259756355130884394587673375183996506461139740622663058947052555');
Copy link
Contributor

Choose a reason for hiding this comment

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

FYI, we have legacy poseidon implemented in o1js, so you can use that instead of a hard-coded value

Copy link
Author

Choose a reason for hiding this comment

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

Thanks Gregor, will give it a try

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.

Rewrite local ledger in TypeScript

2 participants