UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

183 lines 8.04 kB
import { Test } from '../../bindings.js'; import { Common, hashPayment, hashStakeDelegation, SignedCommand, SignedCommandV1, userCommandToEnum, userCommandToV1, } from './transaction-hash.js'; import { commonFromJson, paymentFromJson, delegationFromJson, } from './sign-legacy.js'; import { Signature } from './signature.js'; import { PublicKey } from './curve-bigint.js'; import { Memo } from './memo.js'; import { expect } from 'expect'; 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 = mlTest.transactionHash.serializeCommon(JSON.stringify(commonToOcaml(payment.data.common))); let bytes0 = [...result.data]; let common = commonFromJson(payment.data.common); let bytes1 = Common.toBytes(common); expect(JSON.stringify(bytes1)).toEqual(JSON.stringify(bytes0)); // payment serialization let ocamlPayment = JSON.stringify(paymentToOcaml(payment)); result = mlTest.transactionHash.serializePayment(ocamlPayment); let paymentBytes0 = [...result.data]; let payload = userCommandToEnum(paymentFromJson(payment.data)); let command = { signer: PublicKey.fromBase58(payment.data.common.feePayer), signature: Signature.fromJSON(payment.signature), payload, }; let paymentBytes1 = SignedCommand.toBytes(command); expect(JSON.stringify(paymentBytes1)).toEqual(JSON.stringify(paymentBytes0)); // payment roundtrip let commandRecovered = SignedCommand.fromBytes(paymentBytes1); expect(commandRecovered).toEqual(command); // payment hash 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 = mlTest.transactionHash.serializePayment(ocamlDelegation); let delegationBytes0 = [...result.data]; payload = userCommandToEnum(delegationFromJson(delegation.data)); command = { signer: PublicKey.fromBase58(delegation.data.common.feePayer), signature: Signature.fromJSON(delegation.signature), payload, }; let delegationBytes1 = SignedCommand.toBytes(command); expect(JSON.stringify(delegationBytes1)).toEqual(JSON.stringify(delegationBytes0)); // delegation roundtrip commandRecovered = SignedCommand.fromBytes(delegationBytes1); expect(commandRecovered).toEqual(command); // delegation hash 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 = mlTest.transactionHash.serializePaymentV1(ocamlPaymentV1); let v1Bytes0 = stringToBytesOcaml(mlTest.encoding.ofBase58(ocamlBase58V1, versionBytes.signedCommandV1).c); let paymentV1Body = userCommandToV1(paymentFromJson(payment.data)); let paymentV1 = { signer: PublicKey.fromBase58(payment.data.common.feePayer), signature: Signature.fromJSON(payment.signature), payload: paymentV1Body, }; let v1Bytes1 = SignedCommandV1.toBytes(paymentV1); expect(JSON.stringify(v1Bytes1)).toEqual(JSON.stringify(v1Bytes0)); // payment v1 hash digest0 = mlTest.transactionHash.hashPaymentV1(ocamlPaymentV1); digest1 = hashPayment(payment); expect(digest1).toEqual(digest0); // delegation v1 serialization let ocamlDelegationV1 = JSON.stringify(delegationToOcamlV1(delegation)); ocamlBase58V1 = mlTest.transactionHash.serializePaymentV1(ocamlDelegationV1); v1Bytes0 = stringToBytesOcaml(mlTest.encoding.ofBase58(ocamlBase58V1, versionBytes.signedCommandV1).c); let delegationV1Body = userCommandToV1(delegationFromJson(delegation.data)); let delegationV1 = { signer: PublicKey.fromBase58(delegation.data.common.feePayer), signature: Signature.fromJSON(delegation.signature), payload: delegationV1Body, }; v1Bytes1 = SignedCommandV1.toBytes(delegationV1); expect(JSON.stringify(v1Bytes1)).toEqual(JSON.stringify(v1Bytes0)); // delegation v1 hash digest0 = mlTest.transactionHash.hashPaymentV1(ocamlDelegationV1); digest1 = hashStakeDelegation(delegation); expect(digest1).toEqual(digest0); }); // negative tests test.negative(RandomTransaction.signedPayment.invalid, (payment) => hashPayment(payment)); test.negative(RandomTransaction.signedPayment.invalid, (payment) => { hashPayment(payment, { berkeley: true }); // for "berkeley" hashing, it's fine if the signature is invalid because it's not part of the hash // => make invalid signatures fail independently Signature.fromJSON(payment.signature); }); test.negative(RandomTransaction.signedDelegation.invalid, (delegation) => hashStakeDelegation(delegation)); test.negative(RandomTransaction.signedDelegation.invalid, (delegation) => { hashStakeDelegation(delegation, { berkeley: true }); // for "berkeley" hashing, it's fine if the signature is invalid because it's not part of the hash // => make invalid signatures fail independently Signature.fromJSON(delegation.signature); }); function paymentToOcaml({ data: { common, body: { receiver, amount }, }, signature, }) { return { payload: { common: commonToOcaml(common), body: ['Payment', { receiver_pk: receiver, amount }], }, signer: common.feePayer, signature: signatureToOCaml(signature), }; } function paymentToOcamlV1({ data: { common, body: { receiver, amount }, }, signature, }) { return { payload: { common: commonToOcamlV1(common), body: [ 'Payment', { source_pk: common.feePayer, receiver_pk: receiver, amount, token_id: '1', }, ], }, signer: common.feePayer, signature: signatureToOCaml(signature), }; } function delegationToOcaml({ data: { common, body: { newDelegate }, }, signature, }) { return { payload: { common: commonToOcaml(common), body: ['Stake_delegation', ['Set_delegate', { new_delegate: newDelegate }]], }, signer: common.feePayer, signature: signatureToOCaml(signature), }; } function delegationToOcamlV1({ data: { common, body: { newDelegate }, }, signature, }) { return { payload: { common: commonToOcamlV1(common), body: [ 'Stake_delegation', ['Set_delegate', { delegator: common.feePayer, new_delegate: newDelegate }], ], }, signer: common.feePayer, signature: signatureToOCaml(signature), }; } function commonToOcaml({ fee, feePayer, nonce, validUntil, memo }) { memo = Memo.toBase58(Memo.fromString(memo)); return { fee: fee === '0' ? fee : fee.slice(0, -9), fee_payer_pk: feePayer, nonce, valid_until: ['Since_genesis', validUntil], memo, }; } function commonToOcamlV1({ fee, feePayer, nonce, validUntil, memo }) { memo = Memo.toBase58(Memo.fromString(memo)); return { fee: fee.slice(0, -9), fee_payer_pk: feePayer, nonce, valid_until: validUntil, memo, fee_token: '1', }; } function signatureToOCaml(signature) { return Signature.toBase58(Signature.fromJSON(signature)); } function stringToBytesOcaml(string) { return [...string].map((_, i) => string.charCodeAt(i)); } //# sourceMappingURL=transaction-hash.unit-test.js.map