Skip to content

Commit

Permalink
make ml Test module an async function
Browse files Browse the repository at this point in the history
  • Loading branch information
mitschabaude committed Apr 15, 2024
1 parent 24ebf5e commit 963e0f0
Show file tree
Hide file tree
Showing 14 changed files with 73 additions and 66 deletions.
2 changes: 1 addition & 1 deletion src/bindings
27 changes: 5 additions & 22 deletions src/lib/mina/account-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -875,28 +875,11 @@ class AccountUpdate implements Types.AccountUpdate {
}

hash(): Field {
// these two ways of hashing are (and have to be) consistent / produce the same hash
// TODO: there's no reason anymore to use two different hashing methods here!
// -- the "inCheckedComputation" branch works in all circumstances now
// we just leave this here for a couple more weeks, because it checks
// consistency between JS & OCaml hashing on *every single account update
// proof* we create. It will give us 100% confidence that the two
// implementations are equivalent, and catch regressions quickly
if (Provable.inCheckedComputation()) {
let input = Types.AccountUpdate.toInput(this);
return hashWithPrefix(
zkAppBodyPrefix(activeInstance.getNetworkId()),
packToFields(input)
);
} else {
let json = Types.AccountUpdate.toJSON(this);
return Field(
Test.hashFromJson.accountUpdate(
JSON.stringify(json),
NetworkId.toString(activeInstance.getNetworkId())
)
);
}
let input = Types.AccountUpdate.toInput(this);
return hashWithPrefix(
zkAppBodyPrefix(activeInstance.getNetworkId()),
packToFields(input)
);
}

toPublicInput({
Expand Down
6 changes: 4 additions & 2 deletions src/lib/mina/account-update.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
import { Test } from '../../snarky.js';
import { expect } from 'expect';

let mlTest = await Test();

let address = PrivateKey.random().toPublicKey();

function createAccountUpdate() {
Expand All @@ -24,7 +26,7 @@ function createAccountUpdate() {

// convert accountUpdate to fields in OCaml, going via AccountUpdate.of_json
let json = JSON.stringify(accountUpdate.toJSON().body);
let [, ...fields1_] = Test.fieldsFromJson.accountUpdate(json);
let [, ...fields1_] = mlTest.fieldsFromJson.accountUpdate(json);
let fields1 = fields1_.map(Field);
// convert accountUpdate to fields in pure JS, leveraging generated code
let fields2 = Types.AccountUpdate.toFields(accountUpdate);
Expand Down Expand Up @@ -79,7 +81,7 @@ function createAccountUpdate() {
let accountUpdate = AccountUpdate.create(address);
accountUpdate.approve(AccountUpdate.create(otherAddress));
});
let publicInputOcaml = Test.hashFromJson.zkappPublicInput(tx.toJSON(), 0);
let publicInputOcaml = mlTest.hashFromJson.zkappPublicInput(tx.toJSON(), 0);

expect(publicInput).toEqual({
accountUpdate: Field(publicInputOcaml.accountUpdate),
Expand Down
2 changes: 1 addition & 1 deletion src/lib/mina/hash-input.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { MlHashInput } from '../ml/conversion.js';
import { MlFieldConstArray } from '../ml/fields.js';
import { Test } from '../../snarky.js';

let { hashInputFromJson } = Test;
let { hashInputFromJson } = await Test();

// types
type Body = Types.AccountUpdate['body'];
Expand Down
3 changes: 2 additions & 1 deletion src/lib/mina/local-blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ async function LocalBlockchain({
}
});

const hash = Test.transactionHash.hashZkAppCommand(txn.toJSON());
let test = await Test();
const hash = test.transactionHash.hashZkAppCommand(txn.toJSON());
const pendingTransaction: Omit<PendingTransaction, 'wait' | 'safeWait'> =
{
status,
Expand Down
3 changes: 2 additions & 1 deletion src/lib/mina/mina.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ function Network(

const status: PendingTransactionStatus =
errors.length === 0 ? 'pending' : 'rejected';
const hash = Test.transactionHash.hashZkAppCommand(txn.toJSON());
let mlTest = await Test();
const hash = mlTest.transactionHash.hashZkAppCommand(txn.toJSON());
const pendingTransaction: Omit<PendingTransaction, 'wait' | 'safeWait'> =
{
status,
Expand Down
18 changes: 10 additions & 8 deletions src/lib/ml/consistency.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { FieldConst } from '../provable/core/fieldvar.js';
import { Provable } from '../provable/provable.js';
import { runAndCheckSync } from '../provable/core/provable-context.js';

let mlTest = await Test();

// PrivateKey.toBase58, fromBase58

test(Random.privateKey, (s) => {
Expand All @@ -19,13 +21,13 @@ test(Random.privateKey, (s) => {
let skMl = Ml.fromPrivateKey(sk);

// toBase58 - check consistency with ml
let ml = Test.encoding.privateKeyToBase58(skMl);
let ml = mlTest.encoding.privateKeyToBase58(skMl);
let js = sk.toBase58();
expect(js).toEqual(ml);

// fromBase58 - check consistency with where we started
expect(PrivateKey.fromBase58(js)).toEqual(sk);
expect(Test.encoding.privateKeyOfBase58(ml)).toEqual(skMl);
expect(mlTest.encoding.privateKeyOfBase58(ml)).toEqual(skMl);
});

// PublicKey.toBase58, fromBase58
Expand All @@ -36,25 +38,25 @@ test(Random.publicKey, (pk0) => {
let pkMl = Ml.fromPublicKey(pk);

// toBase58 - check consistency with ml
let ml = Test.encoding.publicKeyToBase58(pkMl);
let ml = mlTest.encoding.publicKeyToBase58(pkMl);
let js = pk.toBase58();
expect(js).toEqual(ml);

// fromBase58 - check consistency with where we started
expect(PublicKey.fromBase58(js)).toEqual(pk);
expect(Test.encoding.publicKeyOfBase58(ml)).toEqual(pkMl);
expect(mlTest.encoding.publicKeyOfBase58(ml)).toEqual(pkMl);
});

// dummy signature
let js = dummySignature();
let ml = Test.signature.dummySignature();
let ml = mlTest.signature.dummySignature();
expect(js).toEqual(ml);

// token id to/from base58

test(Random.field, (x) => {
let js = TokenId.toBase58(Field(x));
let ml = Test.encoding.tokenIdToBase58(FieldConst.fromBigint(x));
let ml = mlTest.encoding.tokenIdToBase58(FieldConst.fromBigint(x));
expect(js).toEqual(ml);

expect(TokenId.fromBase58(js).toBigInt()).toEqual(x);
Expand All @@ -78,7 +80,7 @@ test(Random.publicKey, randomTokenId, (publicKey, field) => {

let js = TokenId.derive(tokenOwner, parentTokenId);
let ml = Field(
Test.tokenId.derive(
mlTest.tokenId.derive(
Ml.fromPublicKey(tokenOwner),
Ml.constFromField(parentTokenId)
)
Expand All @@ -101,7 +103,7 @@ test(Random.publicKey, randomTokenId, (publicKey, field) => {

let js = TokenId.derive(tokenOwner, parentTokenId);
let ml = Field(
Test.tokenId.deriveChecked(
mlTest.tokenId.deriveChecked(
Ml.fromPublicKeyVar(tokenOwner),
Ml.varFromField(parentTokenId)
)
Expand Down
4 changes: 3 additions & 1 deletion src/lib/util/base58.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Test } from '../../snarky.js';
import { expect } from 'expect';
import { test, Random, withHardCoded } from '../testing/property.js';

let mlTest = await Test();

let bytes = withHardCoded(
Random.bytes(Random.nat(100)),
[0, 0, 0, 0] // definitely test some zero bytes
Expand All @@ -12,7 +14,7 @@ let version = Random.nat(100);
test(bytes, version, (bytes, version, assert) => {
let binaryString = String.fromCharCode(...bytes);
let ocamlBytes = { t: 9, c: binaryString, l: bytes.length };
let base58Ocaml = Test.encoding.toBase58(ocamlBytes, version);
let base58Ocaml = mlTest.encoding.toBase58(ocamlBytes, version);

// check consistency with OCaml result
let base58 = toBase58Check(bytes, version);
Expand Down
18 changes: 9 additions & 9 deletions src/mina-signer/src/sign-zkapp-command.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
import { Random, test, withHardCoded } from '../../lib/testing/property.js';
import { PrivateKey, PublicKey } from './curve-bigint.js';
import { hashWithPrefix, packToFields, prefixes } from './poseidon-bigint.js';
import { Pickles, Test, initializeBindings } from '../../snarky.js';
import { Pickles, Test } from '../../snarky.js';
import { Memo } from './memo.js';
import { RandomTransaction } from './random-transaction.js';
import {
Expand All @@ -42,7 +42,7 @@ import {
} from './signature.js';
import { NetworkId } from './types.js';

await initializeBindings();
let mlTest = await Test();

// monkey-patch bigint to json
(BigInt.prototype as any).toJSON = function () {
Expand All @@ -69,7 +69,7 @@ expect(AccountUpdate.toJSON(dummy)).toEqual(

let dummyInput = AccountUpdate.toInput(dummy);
let dummyInputSnarky = MlHashInput.from(
Test.hashInputFromJson.body(
mlTest.hashInputFromJson.body(
JSON.stringify(AccountUpdateSnarky.toJSON(dummySnarky).body)
)
);
Expand Down Expand Up @@ -135,7 +135,7 @@ let memoGenerator = withHardCoded(Random.json.memoString, 'hello world');
test(memoGenerator, (memoString) => {
let memo = Memo.fromString(memoString);
let memoBase58 = Memo.toBase58(memo);
let memoBase581 = Test.encoding.memoToBase58(memoString);
let memoBase581 = mlTest.encoding.memoToBase58(memoString);
expect(memoBase58).toEqual(memoBase581);
let memoRecovered = Memo.fromBase58(memoBase58);
expect(memoRecovered).toEqual(memo);
Expand All @@ -150,7 +150,7 @@ test(

assert(isCallDepthValid(zkappCommand));
let zkappCommandJson = ZkappCommand.toJSON(zkappCommand);
let ocamlCommitments = Test.hashFromJson.transactionCommitments(
let ocamlCommitments = mlTest.hashFromJson.transactionCommitments(
JSON.stringify(zkappCommandJson),
NetworkId.toString(networkId)
);
Expand Down Expand Up @@ -198,7 +198,7 @@ test(
expect(recoveredZkappCommand).toEqual(zkappCommand);

// tx commitment
let ocamlCommitments = Test.hashFromJson.transactionCommitments(
let ocamlCommitments = mlTest.hashFromJson.transactionCommitments(
JSON.stringify(zkappCommandJson),
NetworkId.toString(networkId)
);
Expand All @@ -210,15 +210,15 @@ test(

let memo = Memo.fromBase58(memoBase58);
let memoHash = Memo.hash(memo);
let memoHashSnarky = Test.encoding.memoHashBase58(memoBase58);
let memoHashSnarky = mlTest.encoding.memoHashBase58(memoBase58);
expect(memoHash).toEqual(FieldConst.toBigint(memoHashSnarky));

let feePayerAccountUpdate = accountUpdateFromFeePayer(feePayer);
let feePayerJson = AccountUpdate.toJSON(feePayerAccountUpdate);

let feePayerInput = AccountUpdate.toInput(feePayerAccountUpdate);
let feePayerInput1 = MlHashInput.from(
Test.hashInputFromJson.body(JSON.stringify(feePayerJson.body))
mlTest.hashInputFromJson.body(JSON.stringify(feePayerJson.body))
);
expect(stringify(feePayerInput.fields)).toEqual(
stringify(feePayerInput1.fields)
Expand Down Expand Up @@ -247,7 +247,7 @@ test(
feePayerKey,
networkId
);
let sigOCaml = Test.signature.signFieldElement(
let sigOCaml = mlTest.signature.signFieldElement(
ocamlCommitments.fullCommitment,
Ml.fromPrivateKey(feePayerKeySnarky),
NetworkId.toString(networkId)
Expand Down
4 changes: 3 additions & 1 deletion src/mina-signer/src/signature.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { Ml } from '../../lib/ml/conversion.js';
import { FieldConst } from '../../lib/provable/core/fieldvar.js';
import { NetworkId } from './types.js';

let mlTest = await Test();

// check consistency with OCaml, where we expose the function to sign 1 field element with "testnet"
function checkConsistentSingle(
msg: Field,
Expand All @@ -44,7 +46,7 @@ function checkConsistentSingle(
// consistent with OCaml
let msgMl = FieldConst.fromBigint(msg);
let keyMl = Ml.fromPrivateKey(keySnarky);
let actualTest = Test.signature.signFieldElement(
let actualTest = mlTest.signature.signFieldElement(
msgMl,
keyMl,
NetworkId.toString(networkId)
Expand Down
30 changes: 16 additions & 14 deletions src/mina-signer/src/transaction-hash.unit-test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Ledger, Test } from '../../snarky.js';
import { Test } from '../../snarky.js';
import {
Common,
hashPayment,
Expand All @@ -11,12 +11,10 @@ import {
} from './transaction-hash.js';
import {
PaymentJson,
PaymentJsonV1,
commonFromJson,
paymentFromJson,
CommonJson,
DelegationJson,
DelegationJsonV1,
delegationFromJson,
} from './sign-legacy.js';
import { Signature, SignatureJson } from './signature.js';
Expand All @@ -27,12 +25,14 @@ import { versionBytes } from '../../bindings/crypto/constants.js';
import { test } from '../../lib/testing/property.js';
import { RandomTransaction } from './random-transaction.js';

let mlTest = await Test();

test(
RandomTransaction.signedPayment,
RandomTransaction.signedDelegation,
(payment, delegation) => {
// common serialization
let result = Test.transactionHash.serializeCommon(
let result = mlTest.transactionHash.serializeCommon(
JSON.stringify(commonToOcaml(payment.data.common))
);
let bytes0 = [...result.data];
Expand All @@ -42,7 +42,7 @@ test(

// payment serialization
let ocamlPayment = JSON.stringify(paymentToOcaml(payment));
result = Test.transactionHash.serializePayment(ocamlPayment);
result = mlTest.transactionHash.serializePayment(ocamlPayment);
let paymentBytes0 = [...result.data];
let payload = userCommandToEnum(paymentFromJson(payment.data));
let command = {
Expand All @@ -60,13 +60,13 @@ test(
expect(commandRecovered).toEqual(command);

// payment hash
let digest0 = Test.transactionHash.hashPayment(ocamlPayment);
let digest0 = mlTest.transactionHash.hashPayment(ocamlPayment);
let digest1 = hashPayment(payment, { berkeley: true });
expect(digest1).toEqual(digest0);

// delegation serialization
let ocamlDelegation = JSON.stringify(delegationToOcaml(delegation));
result = Test.transactionHash.serializePayment(ocamlDelegation);
result = mlTest.transactionHash.serializePayment(ocamlDelegation);
let delegationBytes0 = [...result.data];
payload = userCommandToEnum(delegationFromJson(delegation.data));
command = {
Expand All @@ -84,15 +84,16 @@ test(
expect(commandRecovered).toEqual(command);

// delegation hash
digest0 = Test.transactionHash.hashPayment(ocamlDelegation);
digest0 = mlTest.transactionHash.hashPayment(ocamlDelegation);
digest1 = hashStakeDelegation(delegation, { berkeley: true });
expect(digest1).toEqual(digest0);

// payment v1 serialization
let ocamlPaymentV1 = JSON.stringify(paymentToOcamlV1(payment));
let ocamlBase58V1 = Test.transactionHash.serializePaymentV1(ocamlPaymentV1);
let ocamlBase58V1 =
mlTest.transactionHash.serializePaymentV1(ocamlPaymentV1);
let v1Bytes0 = stringToBytesOcaml(
Test.encoding.ofBase58(ocamlBase58V1, versionBytes.signedCommandV1).c
mlTest.encoding.ofBase58(ocamlBase58V1, versionBytes.signedCommandV1).c
);
let paymentV1Body = userCommandToV1(paymentFromJson(payment.data));
let paymentV1 = {
Expand All @@ -104,15 +105,16 @@ test(
expect(JSON.stringify(v1Bytes1)).toEqual(JSON.stringify(v1Bytes0));

// payment v1 hash
digest0 = Test.transactionHash.hashPaymentV1(ocamlPaymentV1);
digest0 = mlTest.transactionHash.hashPaymentV1(ocamlPaymentV1);
digest1 = hashPayment(payment);
expect(digest1).toEqual(digest0);

// delegation v1 serialization
let ocamlDelegationV1 = JSON.stringify(delegationToOcamlV1(delegation));
ocamlBase58V1 = Test.transactionHash.serializePaymentV1(ocamlDelegationV1);
ocamlBase58V1 =
mlTest.transactionHash.serializePaymentV1(ocamlDelegationV1);
v1Bytes0 = stringToBytesOcaml(
Test.encoding.ofBase58(ocamlBase58V1, versionBytes.signedCommandV1).c
mlTest.encoding.ofBase58(ocamlBase58V1, versionBytes.signedCommandV1).c
);
let delegationV1Body = userCommandToV1(delegationFromJson(delegation.data));
let delegationV1 = {
Expand All @@ -124,7 +126,7 @@ test(
expect(JSON.stringify(v1Bytes1)).toEqual(JSON.stringify(v1Bytes0));

// delegation v1 hash
digest0 = Test.transactionHash.hashPaymentV1(ocamlDelegationV1);
digest0 = mlTest.transactionHash.hashPaymentV1(ocamlDelegationV1);
digest1 = hashStakeDelegation(delegation);
expect(digest1).toEqual(digest0);
}
Expand Down
Loading

0 comments on commit 963e0f0

Please sign in to comment.