UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

129 lines (105 loc) 4.37 kB
import { mocks } from '../../../bindings/crypto/constants.js'; import { AccountUpdate, PrivateKey, Field, Bool, Mina, Int64, Types } from '../../../index.js'; import { Test } from '../../../bindings.js'; import { expect } from 'expect'; let mlTest = await Test(); let address = PrivateKey.random().toPublicKey(); function createAccountUpdate() { let accountUpdate = AccountUpdate.default(address); accountUpdate.body.balanceChange = Int64.from(1e9).neg(); return accountUpdate; } function createAccountUpdateWithMayUseToken(mayUseToken: AccountUpdate['body']['mayUseToken']) { let accountUpdate = AccountUpdate.default(address); accountUpdate.body.mayUseToken = mayUseToken; return accountUpdate; } // can convert account update to fields consistently { let accountUpdate = createAccountUpdate(); // convert accountUpdate to fields in OCaml, going via AccountUpdate.of_json let json = JSON.stringify(accountUpdate.toJSON().body); 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); // this is useful console output in the case the test should fail if (fields1.length !== fields2.length) { console.log(`unequal length. expected ${fields1.length}, actual: ${fields2.length}`); } for (let i = 0; i < fields1.length; i++) { if (fields1[i].toString() !== fields2[i].toString()) { console.log('unequal at', i); console.log(`expected: ${fields1[i]} actual: ${fields2[i]}`); } } expect(fields1.length).toEqual(fields2.length); expect(fields1.map(String)).toEqual(fields2.map(String)); expect(fields1).toEqual(fields2); } // can hash an account update { let accountUpdate = createAccountUpdate(); let hash = accountUpdate.hash(); // if we clone the accountUpdate, hash should be the same let accountUpdate2 = AccountUpdate.clone(accountUpdate); expect(accountUpdate2.hash()).toEqual(hash); // if we change something on the cloned accountUpdate, the hash should become different AccountUpdate.setValue(accountUpdate2.update.appState[0], Field(1)); expect(accountUpdate2.hash()).not.toEqual(hash); } // converts account update to a public input that's consistent with the ocaml implementation { let otherAddress = PrivateKey.random().toPublicKey(); let accountUpdate = AccountUpdate.create(address); let otherUpdate = AccountUpdate.create(otherAddress); accountUpdate.approve(otherUpdate); let publicInput = accountUpdate.toPublicInput({ accountUpdates: [accountUpdate, otherUpdate], }); // create transaction JSON with the same accountUpdate structure, for ocaml version let tx = await Mina.transaction(async () => { let accountUpdate = AccountUpdate.create(address); accountUpdate.approve(AccountUpdate.create(otherAddress)); }); let publicInputOcaml = mlTest.hashFromJson.zkappPublicInput(tx.toJSON(), 0); expect(publicInput).toEqual({ accountUpdate: Field(publicInputOcaml.accountUpdate), calls: Field(publicInputOcaml.calls), }); } // creates the right empty sequence state { let accountUpdate = createAccountUpdate(); expect(accountUpdate.body.preconditions.account.actionState.value.toString()).toEqual( '25079927036070901246064867767436987657692091363973573142121686150614948079097' ); } // creates the right empty vk hash { let accountUpdate = createAccountUpdate(); expect(accountUpdate.body.authorizationKind.verificationKeyHash.toString()).toEqual( mocks.dummyVerificationKeyHash ); } // does not throw an error if private key is missing unless if .send is executed { let Local = await Mina.LocalBlockchain({ proofsEnabled: false }); Mina.setActiveInstance(Local); const [feePayer] = Local.testAccounts; let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); }); tx.sign([]); await expect(tx.send()).rejects.toThrow( 'Check signature: Invalid signature on fee payer for key' ); } // correctly identifies when neither flag is set { let accountUpdate = createAccountUpdateWithMayUseToken({ parentsOwnToken: Bool(false), inheritFromParent: Bool(false), }); expect(AccountUpdate.MayUseToken.isNo(accountUpdate).toBoolean()).toEqual(true); }