From ea7729105fd5a2bebff400eabfdf5a58b78d349b Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 24 Nov 2023 21:54:21 +0100 Subject: [PATCH 01/14] refactor sizeInBits/Bytes --- src/bindings | 2 +- src/lib/bool.ts | 4 +--- src/lib/field.ts | 20 ++++---------------- src/lib/gadgets/bitwise.ts | 8 ++++---- src/mina-signer/src/memo.ts | 4 +--- src/provable/field-bigint.ts | 4 +--- 6 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/bindings b/src/bindings index 87996f7d27..f00805ef39 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 87996f7d27b37208d536349ab9449047964736f2 +Subproject commit f00805ef39896acc504cfb6f6f6c46454cb7a9f4 diff --git a/src/lib/bool.ts b/src/lib/bool.ts index 387a4908da..e9710a510e 100644 --- a/src/lib/bool.ts +++ b/src/lib/bool.ts @@ -314,9 +314,7 @@ class Bool { return BoolBinable.readBytes(bytes, offset); } - static sizeInBytes() { - return 1; - } + static sizeInBytes: 1; static check(x: Bool): void { Snarky.field.assertBoolean(x.value); diff --git a/src/lib/field.ts b/src/lib/field.ts index de52ecf621..f09ebd085a 100644 --- a/src/lib/field.ts +++ b/src/lib/field.ts @@ -1253,26 +1253,14 @@ class Field { } /** - * **Warning**: This function is mainly for internal use. Normally it is not intended to be used by a zkApp developer. - * - * As all {@link Field} elements have 32 bytes, this function returns 32. - * - * @return The size of a {@link Field} element - 32. + * The size of a {@link Field} element in bytes - 32. */ - static sizeInBytes() { - return Fp.sizeInBytes(); - } + static sizeInBytes = Fp.sizeInBytes; /** - * **Warning**: This function is mainly for internal use. Normally it is not intended to be used by a zkApp developer. - * - * As all {@link Field} elements have 255 bits, this function returns 255. - * - * @return The size of a {@link Field} element in bits - 255. + * The size of a {@link Field} element in bits - 255. */ - static sizeInBits() { - return Fp.sizeInBits; - } + static sizeInBits = Fp.sizeInBits; } const FieldBinable = defineBinable({ diff --git a/src/lib/gadgets/bitwise.ts b/src/lib/gadgets/bitwise.ts index 4a8a66f041..027d996488 100644 --- a/src/lib/gadgets/bitwise.ts +++ b/src/lib/gadgets/bitwise.ts @@ -20,8 +20,8 @@ function not(a: Field, length: number, checked: boolean = false) { // Check that length does not exceed maximum field size in bits assert( - length < Field.sizeInBits(), - `Length ${length} exceeds maximum of ${Field.sizeInBits()} bits.` + length < Field.sizeInBits, + `Length ${length} exceeds maximum of ${Field.sizeInBits} bits.` ); // obtain pad length until the length is a multiple of 16 for n-bit length lookup table @@ -156,8 +156,8 @@ function and(a: Field, b: Field, length: number) { // check that length does not exceed maximum field size in bits assert( - length <= Field.sizeInBits(), - `Length ${length} exceeds maximum of ${Field.sizeInBits()} bits.` + length <= Field.sizeInBits, + `Length ${length} exceeds maximum of ${Field.sizeInBits} bits.` ); // obtain pad length until the length is a multiple of 16 for n-bit length lookup table diff --git a/src/mina-signer/src/memo.ts b/src/mina-signer/src/memo.ts index 976c822ca6..8b3ae05f6f 100644 --- a/src/mina-signer/src/memo.ts +++ b/src/mina-signer/src/memo.ts @@ -62,9 +62,7 @@ const Memo = { hash, ...withBits(Binable, SIZE * 8), ...base58(Binable, versionBytes.userCommandMemo), - sizeInBytes() { - return SIZE; - }, + sizeInBytes: SIZE, emptyValue() { return Memo.fromString(''); }, diff --git a/src/provable/field-bigint.ts b/src/provable/field-bigint.ts index ea2d797c83..88e6afd5cd 100644 --- a/src/provable/field-bigint.ts +++ b/src/provable/field-bigint.ts @@ -64,9 +64,7 @@ const Bool = pseudoClass( checkBool(x); return x; }, - sizeInBytes() { - return 1; - }, + sizeInBytes: 1, fromField(x: Field) { checkBool(x); return x as 0n | 1n; From f5f656e47dc550dae8339c23f58c59006dd12b71 Mon Sep 17 00:00:00 2001 From: Gregor Mitscha-Baude Date: Sat, 25 Nov 2023 00:32:53 +0100 Subject: [PATCH 02/14] bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index f00805ef39..544c8a7306 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit f00805ef39896acc504cfb6f6f6c46454cb7a9f4 +Subproject commit 544c8a730618c9b912037abd7703755ef8b4c84d From 77162a43b67219b7416bb9c96dfa1e2e740fccb4 Mon Sep 17 00:00:00 2001 From: Gregor Mitscha-Baude Date: Sat, 25 Nov 2023 00:33:42 +0100 Subject: [PATCH 03/14] remove provable from mina-signer types --- src/lib/bool.ts | 4 ++++ src/lib/events.ts | 4 ++-- src/lib/field.ts | 4 ++++ src/lib/hash-generic.ts | 4 ++-- src/lib/testing/random.ts | 19 +++++++++++-------- src/provable/curve-bigint.ts | 3 ++- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/lib/bool.ts b/src/lib/bool.ts index e9710a510e..15d0db2548 100644 --- a/src/lib/bool.ts +++ b/src/lib/bool.ts @@ -295,6 +295,10 @@ class Bool { return 1; } + static emptyValue() { + return new Bool(false); + } + static toInput(x: Bool): { packed: [Field, number][] } { return { packed: [[x.toField(), 1] as [Field, number]] }; } diff --git a/src/lib/events.ts b/src/lib/events.ts index 3e92a30389..04efe23185 100644 --- a/src/lib/events.ts +++ b/src/lib/events.ts @@ -1,8 +1,8 @@ import { prefixes } from '../bindings/crypto/constants.js'; import { prefixToField } from '../bindings/lib/binable.js'; import { - GenericField, GenericProvableExtended, + GenericSignableField, } from '../bindings/lib/generic.js'; export { createEvents, dataAsHash }; @@ -15,7 +15,7 @@ function createEvents({ Field, Poseidon, }: { - Field: GenericField; + Field: GenericSignableField; Poseidon: Poseidon; }) { type Event = Field[]; diff --git a/src/lib/field.ts b/src/lib/field.ts index f09ebd085a..fe117f65ab 100644 --- a/src/lib/field.ts +++ b/src/lib/field.ts @@ -1148,6 +1148,10 @@ class Field { // ProvableExtended + static emptyValue() { + return new Field(0n); + } + /** * Serialize the {@link Field} to a JSON string, e.g. for printing. Trying to print a {@link Field} without this function will directly stringify the Field object, resulting in unreadable output. * diff --git a/src/lib/hash-generic.ts b/src/lib/hash-generic.ts index c5e240ae0a..c2907a3963 100644 --- a/src/lib/hash-generic.ts +++ b/src/lib/hash-generic.ts @@ -1,4 +1,4 @@ -import { GenericField } from '../bindings/lib/generic.js'; +import { GenericField, GenericSignableField } from '../bindings/lib/generic.js'; import { prefixToField } from '../bindings/lib/binable.js'; export { createHashHelpers, HashHelpers }; @@ -11,7 +11,7 @@ type Hash = { type HashHelpers = ReturnType>; function createHashHelpers( - Field: GenericField, + Field: GenericSignableField, Hash: Hash ) { function salt(prefix: string) { diff --git a/src/lib/testing/random.ts b/src/lib/testing/random.ts index 0d9c457cf2..65f0c1d4dc 100644 --- a/src/lib/testing/random.ts +++ b/src/lib/testing/random.ts @@ -23,10 +23,10 @@ import { PublicKey, StateHash, } from '../../bindings/mina-transaction/transaction-leaves-bigint.js'; -import { genericLayoutFold } from '../../bindings/lib/from-layout.js'; +import { genericLayoutFold } from '../../bindings/lib/from-layout-signable.js'; import { jsLayout } from '../../bindings/mina-transaction/gen/js-layout.js'; import { - GenericProvable, + GenericSignable, primitiveTypeMap, } from '../../bindings/lib/generic.js'; import { Scalar, PrivateKey, Group } from '../../provable/curve-bigint.js'; @@ -35,7 +35,10 @@ import { randomBytes } from '../../bindings/crypto/random.js'; import { alphabet } from '../base58.js'; import { bytesToBigInt } from '../../bindings/crypto/bigint-helpers.js'; import { Memo } from '../../mina-signer/src/memo.js'; -import { ProvableExtended } from '../../bindings/lib/provable-bigint.js'; +import { + ProvableExtended, + Signable, +} from '../../bindings/lib/provable-bigint.js'; import { tokenSymbolLength } from '../../bindings/mina-transaction/derived-leaves.js'; import { stringLengthInBytes } from '../../bindings/lib/binable.js'; import { mocks } from '../../bindings/crypto/constants.js'; @@ -113,9 +116,9 @@ const zkappUri = map(string(nat(50)), ZkappUri.fromJSON); const PrimitiveMap = primitiveTypeMap(); type Types = typeof TypeMap & typeof customTypes & typeof PrimitiveMap; -type Provable = GenericProvable; +type Signable_ = GenericSignable; type Generators = { - [K in keyof Types]: Types[K] extends Provable ? Random : never; + [K in keyof Types]: Types[K] extends Signable_ ? Random : never; }; const Generators: Generators = { Field: field, @@ -138,7 +141,7 @@ const Generators: Generators = { string: base58(nat(50)), // TODO replace various strings, like signature, with parsed types number: nat(3), }; -let typeToBigintGenerator = new Map, Random>( +let typeToBigintGenerator = new Map, Random>( [TypeMap, PrimitiveMap, customTypes] .map(Object.entries) .flat() @@ -214,7 +217,7 @@ function withInvalidRandomString(rng: Random) { } type JsonGenerators = { - [K in keyof Types]: Types[K] extends ProvableExtended + [K in keyof Types]: Types[K] extends Signable ? Random : never; }; @@ -241,7 +244,7 @@ const JsonGenerators: JsonGenerators = { string: base58(nat(50)), number: nat(3), }; -let typeToJsonGenerator = new Map, Random>( +let typeToJsonGenerator = new Map, Random>( [TypeMap, PrimitiveMap, customTypes] .map(Object.entries) .flat() diff --git a/src/provable/curve-bigint.ts b/src/provable/curve-bigint.ts index 78e1e37a45..bdb11d9640 100644 --- a/src/provable/curve-bigint.ts +++ b/src/provable/curve-bigint.ts @@ -12,6 +12,7 @@ import { BinableBigint, ProvableBigint, provable, + signable, } from '../bindings/lib/provable-bigint.js'; import { HashInputLegacy } from './poseidon-bigint.js'; @@ -79,7 +80,7 @@ let BinablePublicKey = withVersionNumber( * A public key, represented by a non-zero point on the Pallas curve, in compressed form { x, isOdd } */ const PublicKey = { - ...provable({ x: Field, isOdd: Bool }), + ...signable({ x: Field, isOdd: Bool }), ...withBase58(BinablePublicKey, versionBytes.publicKey), toJSON(publicKey: PublicKey) { From 6632eba4e277e0d6f8b70576d8b2c90243c1c3a4 Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 08:19:06 +0100 Subject: [PATCH 04/14] test fixes --- src/bindings | 2 +- src/lib/testing/testing.unit-test.ts | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/bindings b/src/bindings index 544c8a7306..d307af5e58 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 544c8a730618c9b912037abd7703755ef8b4c84d +Subproject commit d307af5e584c3b49aba6bf9c2735b0cfbfb5d91c diff --git a/src/lib/testing/testing.unit-test.ts b/src/lib/testing/testing.unit-test.ts index 4a0abe91fb..0c5859f829 100644 --- a/src/lib/testing/testing.unit-test.ts +++ b/src/lib/testing/testing.unit-test.ts @@ -20,10 +20,11 @@ test(Random.accountUpdate, (accountUpdate, assert) => { jsonString === JSON.stringify(AccountUpdate.toJSON(AccountUpdate.fromJSON(json))) ); - let fields = AccountUpdate.toFields(accountUpdate); - let auxiliary = AccountUpdate.toAuxiliary(accountUpdate); - let recovered = AccountUpdate.fromFields(fields, auxiliary); - assert(jsonString === JSON.stringify(AccountUpdate.toJSON(recovered))); + // TODO add back using `fromValue` + // let fields = AccountUpdate.toFields(accountUpdate); + // let auxiliary = AccountUpdate.toAuxiliary(accountUpdate); + // let recovered = AccountUpdate.fromFields(fields, auxiliary); + // assert(jsonString === JSON.stringify(AccountUpdate.toJSON(recovered))); }); test(Random.json.accountUpdate, (json) => { let jsonString = JSON.stringify(json); From 5dc5751bb1a729214342cff097cb6eaf02e7c60a Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 09:37:15 +0100 Subject: [PATCH 05/14] make empty value required --- src/bindings | 2 +- src/lib/circuit_value.ts | 10 ++++++++++ src/lib/hash-generic.ts | 2 +- src/lib/hash.ts | 3 +++ src/lib/int.ts | 4 ++-- src/lib/provable.ts | 9 +++++++++ 6 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/bindings b/src/bindings index d307af5e58..161b82c520 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit d307af5e584c3b49aba6bf9c2735b0cfbfb5d91c +Subproject commit 161b82c52098fa7186933f14ec9e63577a0ce4c9 diff --git a/src/lib/circuit_value.ts b/src/lib/circuit_value.ts index 0f4106ebb9..2ac58ad54b 100644 --- a/src/lib/circuit_value.ts +++ b/src/lib/circuit_value.ts @@ -49,6 +49,7 @@ type ProvableExtension = { toInput: (x: T) => { fields?: Field[]; packed?: [Field, number][] }; toJSON: (x: T) => TJson; fromJSON: (x: TJson) => T; + emptyValue: () => T; }; type ProvableExtended = Provable & @@ -246,6 +247,15 @@ abstract class CircuitValue { } return Object.assign(Object.create(this.prototype), props); } + + static emptyValue(): InstanceType { + const fields: [string, any][] = (this as any).prototype._fields ?? []; + let props: any = {}; + fields.forEach(([key, propType]) => { + props[key] = propType.emptyValue(); + }); + return Object.assign(Object.create(this.prototype), props); + } } function prop(this: any, target: any, key: string) { diff --git a/src/lib/hash-generic.ts b/src/lib/hash-generic.ts index c2907a3963..7e76c8ceee 100644 --- a/src/lib/hash-generic.ts +++ b/src/lib/hash-generic.ts @@ -1,4 +1,4 @@ -import { GenericField, GenericSignableField } from '../bindings/lib/generic.js'; +import { GenericSignableField } from '../bindings/lib/generic.js'; import { prefixToField } from '../bindings/lib/binable.js'; export { createHashHelpers, HashHelpers }; diff --git a/src/lib/hash.ts b/src/lib/hash.ts index 684b7632ce..7a56b95b56 100644 --- a/src/lib/hash.ts +++ b/src/lib/hash.ts @@ -179,6 +179,9 @@ const TokenSymbolPure: ProvableExtended< toInput({ field }) { return { packed: [[field, 48]] }; }, + emptyValue() { + return { symbol: '', field: Field(0n) }; + }, }; class TokenSymbol extends Struct(TokenSymbolPure) { static get empty() { diff --git a/src/lib/int.ts b/src/lib/int.ts index a48118fa2c..10a7813a3b 100644 --- a/src/lib/int.ts +++ b/src/lib/int.ts @@ -723,8 +723,8 @@ class Sign extends CircuitValue { // x^2 === 1 <=> x === 1 or x === -1 x.value.square().assertEquals(Field(1)); } - static emptyValue(): Sign { - return Sign.one; + static emptyValue(): InstanceType { + return Sign.one as any; } static toInput(x: Sign): HashInput { return { packed: [[x.isPositive().toField(), 1]] }; diff --git a/src/lib/provable.ts b/src/lib/provable.ts index 0b1a5e00aa..b3fa385eda 100644 --- a/src/lib/provable.ts +++ b/src/lib/provable.ts @@ -566,5 +566,14 @@ function provableArray>( HashInput.empty ); }, + + emptyValue() { + if (!('emptyValue' in type)) { + throw Error( + 'circuitArray.emptyValue: element type has no emptyValue method' + ); + } + return Array(length).fill(type.emptyValue()); + }, } satisfies ProvableExtended as any; } From 1c77343d6f9c6490207f7fdae5f38f048260ed3a Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 09:48:21 +0100 Subject: [PATCH 06/14] minor simplification --- src/bindings | 2 +- src/lib/testing/random.ts | 23 ++++++++++------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/bindings b/src/bindings index 161b82c520..9d3506ea05 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 161b82c52098fa7186933f14ec9e63577a0ce4c9 +Subproject commit 9d3506ea05aecd1bb054859909f13736a9bd4e61 diff --git a/src/lib/testing/random.ts b/src/lib/testing/random.ts index 65f0c1d4dc..4e1f4e3669 100644 --- a/src/lib/testing/random.ts +++ b/src/lib/testing/random.ts @@ -26,7 +26,7 @@ import { import { genericLayoutFold } from '../../bindings/lib/from-layout-signable.js'; import { jsLayout } from '../../bindings/mina-transaction/gen/js-layout.js'; import { - GenericSignable, + PrimitiveTypeMap, primitiveTypeMap, } from '../../bindings/lib/generic.js'; import { Scalar, PrivateKey, Group } from '../../provable/curve-bigint.js'; @@ -35,10 +35,7 @@ import { randomBytes } from '../../bindings/crypto/random.js'; import { alphabet } from '../base58.js'; import { bytesToBigInt } from '../../bindings/crypto/bigint-helpers.js'; import { Memo } from '../../mina-signer/src/memo.js'; -import { - ProvableExtended, - Signable, -} from '../../bindings/lib/provable-bigint.js'; +import { Signable } from '../../bindings/lib/provable-bigint.js'; import { tokenSymbolLength } from '../../bindings/mina-transaction/derived-leaves.js'; import { stringLengthInBytes } from '../../bindings/lib/binable.js'; import { mocks } from '../../bindings/crypto/constants.js'; @@ -114,11 +111,11 @@ const verificationKeyHash = oneOf(VerificationKeyHash.emptyValue(), field); const receiptChainHash = oneOf(ReceiptChainHash.emptyValue(), field); const zkappUri = map(string(nat(50)), ZkappUri.fromJSON); -const PrimitiveMap = primitiveTypeMap(); -type Types = typeof TypeMap & typeof customTypes & typeof PrimitiveMap; -type Signable_ = GenericSignable; +type Types = typeof TypeMap & typeof customTypes & PrimitiveTypeMap; type Generators = { - [K in keyof Types]: Types[K] extends Signable_ ? Random : never; + [K in keyof Types]: Types[K] extends Signable + ? Random + : never; }; const Generators: Generators = { Field: field, @@ -141,8 +138,8 @@ const Generators: Generators = { string: base58(nat(50)), // TODO replace various strings, like signature, with parsed types number: nat(3), }; -let typeToBigintGenerator = new Map, Random>( - [TypeMap, PrimitiveMap, customTypes] +let typeToBigintGenerator = new Map, Random>( + [TypeMap, primitiveTypeMap, customTypes] .map(Object.entries) .flat() .map(([key, value]) => [value, Generators[key as keyof Generators]]) @@ -244,8 +241,8 @@ const JsonGenerators: JsonGenerators = { string: base58(nat(50)), number: nat(3), }; -let typeToJsonGenerator = new Map, Random>( - [TypeMap, PrimitiveMap, customTypes] +let typeToJsonGenerator = new Map, Random>( + [TypeMap, primitiveTypeMap, customTypes] .map(Object.entries) .flat() .map(([key, value]) => [value, JsonGenerators[key as keyof JsonGenerators]]) From 5b8cd24956db2c6dbf9b32ffa41114b4da4a2ecd Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 10:23:31 +0100 Subject: [PATCH 07/14] adapt to bindings --- src/bindings | 2 +- src/lib/mina/account.ts | 10 +++------- src/lib/testing/random.ts | 10 ++++++++-- src/lib/testing/testing.unit-test.ts | 6 +++--- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/bindings b/src/bindings index 9d3506ea05..e767497368 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 9d3506ea05aecd1bb054859909f13736a9bd4e61 +Subproject commit e7674973687e8b4ffadfa5652e839aa34c8a7d17 diff --git a/src/lib/mina/account.ts b/src/lib/mina/account.ts index c45d38587b..7025b37508 100644 --- a/src/lib/mina/account.ts +++ b/src/lib/mina/account.ts @@ -10,6 +10,7 @@ import { TypeMap, } from '../../bindings/mina-transaction/gen/transaction.js'; import { jsLayout } from '../../bindings/mina-transaction/gen/js-layout.js'; +import { ProvableExtended } from '../circuit_value.js'; export { FetchedAccount, Account, PartialAccount }; export { accountQuery, parseFetchedAccount, fillPartialAccount }; @@ -184,19 +185,14 @@ function parseFetchedAccount({ } function fillPartialAccount(account: PartialAccount): Account { - return genericLayoutFold( + return genericLayoutFold>( TypeMap, customTypes, { map(type, value) { // if value exists, use it; otherwise fall back to dummy value if (value !== undefined) return value; - // fall back to dummy value - if (type.emptyValue) return type.emptyValue(); - return type.fromFields( - Array(type.sizeInFields()).fill(Field(0)), - type.toAuxiliary() - ); + return type.emptyValue(); }, reduceArray(array) { return array; diff --git a/src/lib/testing/random.ts b/src/lib/testing/random.ts index 4e1f4e3669..4821df520b 100644 --- a/src/lib/testing/random.ts +++ b/src/lib/testing/random.ts @@ -23,7 +23,7 @@ import { PublicKey, StateHash, } from '../../bindings/mina-transaction/transaction-leaves-bigint.js'; -import { genericLayoutFold } from '../../bindings/lib/from-layout-signable.js'; +import { genericLayoutFold } from '../../bindings/lib/from-layout.js'; import { jsLayout } from '../../bindings/mina-transaction/gen/js-layout.js'; import { PrimitiveTypeMap, @@ -329,7 +329,13 @@ function generatorFromLayout( { isJson }: { isJson: boolean } ): Random { let typeToGenerator = isJson ? typeToJsonGenerator : typeToBigintGenerator; - return genericLayoutFold, TypeMap, Json.TypeMap>( + return genericLayoutFold< + Signable, + undefined, + Random, + TypeMap, + Json.TypeMap + >( TypeMap, customTypes, { diff --git a/src/lib/testing/testing.unit-test.ts b/src/lib/testing/testing.unit-test.ts index 0c5859f829..6041b155b4 100644 --- a/src/lib/testing/testing.unit-test.ts +++ b/src/lib/testing/testing.unit-test.ts @@ -6,11 +6,11 @@ import { PublicKey, UInt32, UInt64, - provableFromLayout, + signableFromLayout, ZkappCommand, Json, } from '../../bindings/mina-transaction/gen/transaction-bigint.js'; -import { test, Random, sample } from './property.js'; +import { test, Random } from './property.js'; // some trivial roundtrip tests test(Random.accountUpdate, (accountUpdate, assert) => { @@ -53,7 +53,7 @@ test.custom({ negative: true, timeBudget: 1000 })( AccountUpdate.fromJSON ); -const FeePayer = provableFromLayout< +const FeePayer = signableFromLayout< ZkappCommand['feePayer'], Json.ZkappCommand['feePayer'] >(jsLayout.ZkappCommand.entries.feePayer as any); From 32fd4a3c3bb0787f55e9a911fac38a7279e343ad Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 11:43:52 +0100 Subject: [PATCH 08/14] adapt type generation script --- src/build/jsLayoutToTypes.mjs | 55 ++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/build/jsLayoutToTypes.mjs b/src/build/jsLayoutToTypes.mjs index 2f0b87caef..be9648bf51 100644 --- a/src/build/jsLayoutToTypes.mjs +++ b/src/build/jsLayoutToTypes.mjs @@ -106,11 +106,22 @@ function writeType(typeData, isJson, withTypeMap) { }; } -function writeTsContent(types, isJson, leavesRelPath) { +function writeTsContent({ + jsLayout: types, + isJson, + isProvable, + leavesRelPath, +}) { let output = ''; let dependencies = new Set(); let converters = {}; let exports = new Set(isJson ? [] : ['customTypes']); + + let fromLayout = isProvable ? 'provableFromLayout' : 'signableFromLayout'; + let FromLayout = isProvable ? 'ProvableFromLayout' : 'SignableFromLayout'; + let GenericType = isProvable ? 'GenericProvableExtended' : 'GenericSignable'; + let GeneratedType = isProvable ? 'ProvableExtended' : 'Signable'; + for (let [Type, value] of Object.entries(types)) { let inner = writeType(value, isJson); exports.add(Type); @@ -118,7 +129,7 @@ function writeTsContent(types, isJson, leavesRelPath) { mergeObject(converters, inner.converters); output += `type ${Type} = ${inner.output};\n\n`; if (!isJson) { - output += `let ${Type} = provableFromLayout<${Type}, Json.${Type}>(jsLayout.${Type} as any);\n\n`; + output += `let ${Type} = ${fromLayout}<${Type}, Json.${Type}>(jsLayout.${Type} as any);\n\n`; } } @@ -135,8 +146,8 @@ function writeTsContent(types, isJson, leavesRelPath) { import { ${[...imports].join(', ')} } from '${importPath}'; ${ !isJson - ? "import { GenericProvableExtended } from '../../lib/generic.js';\n" + - "import { ProvableFromLayout, GenericLayout } from '../../lib/from-layout.js';\n" + + ? `import { ${GenericType} } from '../../lib/generic.js';\n` + + `import { ${FromLayout}, GenericLayout } from '../../lib/from-layout.js';\n` + "import * as Json from './transaction-json.js';\n" + "import { jsLayout } from './js-layout.js';\n" : '' @@ -147,7 +158,7 @@ ${ !isJson ? 'export { Json };\n' + `export * from '${leavesRelPath}';\n` + - 'export { provableFromLayout, toJSONEssential, emptyValue, Layout, TypeMap };\n' + `export { ${fromLayout}, toJSONEssential, emptyValue, Layout, TypeMap };\n` : `export * from '${leavesRelPath}';\n` + 'export { TypeMap };\n' } @@ -158,7 +169,7 @@ ${ (!isJson || '') && ` const TypeMap: { - [K in keyof TypeMap]: ProvableExtended; + [K in keyof TypeMap]: ${GeneratedType}; } = { ${[...typeMapKeys].join(', ')} } @@ -168,14 +179,14 @@ const TypeMap: { ${ (!isJson || '') && ` -type ProvableExtended = GenericProvableExtended; +type ${GeneratedType} = ${GenericType}; type Layout = GenericLayout; type CustomTypes = { ${customTypes - .map((c) => `${c.typeName}: ProvableExtended<${c.type}, ${c.jsonType}>;`) + .map((c) => `${c.typeName}: ${GeneratedType}<${c.type}, ${c.jsonType}>;`) .join(' ')} } let customTypes: CustomTypes = { ${customTypeNames.join(', ')} }; -let { provableFromLayout, toJSONEssential, emptyValue } = ProvableFromLayout< +let { ${fromLayout}, toJSONEssential, emptyValue } = ${FromLayout}< TypeMap, Json.TypeMap >(TypeMap, customTypes); @@ -196,25 +207,27 @@ async function writeTsFile(content, relPath) { let genPath = '../../bindings/mina-transaction/gen'; await ensureDir(genPath); -let jsonTypesContent = writeTsContent( +let jsonTypesContent = writeTsContent({ jsLayout, - true, - '../transaction-leaves-json.js' -); + isJson: true, + leavesRelPath: '../transaction-leaves-json.js', +}); await writeTsFile(jsonTypesContent, `${genPath}/transaction-json.ts`); -let jsTypesContent = writeTsContent( +let jsTypesContent = writeTsContent({ jsLayout, - false, - '../transaction-leaves.js' -); + isJson: false, + isProvable: true, + leavesRelPath: '../transaction-leaves.js', +}); await writeTsFile(jsTypesContent, `${genPath}/transaction.ts`); -jsTypesContent = writeTsContent( +jsTypesContent = writeTsContent({ jsLayout, - false, - '../transaction-leaves-bigint.js' -); + isJson: false, + isProvable: false, + leavesRelPath: '../transaction-leaves-bigint.js', +}); await writeTsFile(jsTypesContent, `${genPath}/transaction-bigint.ts`); await writeTsFile( From 563e9a585bb82e069dc31eae08665328f1109b7d Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 11:48:11 +0100 Subject: [PATCH 09/14] use signable for private key --- src/provable/curve-bigint.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/provable/curve-bigint.ts b/src/provable/curve-bigint.ts index bdb11d9640..f4d18dc4a9 100644 --- a/src/provable/curve-bigint.ts +++ b/src/provable/curve-bigint.ts @@ -11,7 +11,6 @@ import { Bool, checkRange, Field, pseudoClass } from './field-bigint.js'; import { BinableBigint, ProvableBigint, - provable, signable, } from '../bindings/lib/provable-bigint.js'; import { HashInputLegacy } from './poseidon-bigint.js'; @@ -138,7 +137,7 @@ let Base58PrivateKey = base58(BinablePrivateKey, versionBytes.privateKey); */ const PrivateKey = { ...Scalar, - ...provable(Scalar), + ...signable(Scalar), ...Base58PrivateKey, ...BinablePrivateKey, toPublicKey(key: PrivateKey) { From b1d1cd7fcb16168800894fccdac9425eb5cbb534 Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 11:48:14 +0100 Subject: [PATCH 10/14] bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index cd8146bb18..a92bf1a2e9 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit cd8146bb1897eca5c90f11df2611ea2451d42cc4 +Subproject commit a92bf1a2e9cbe5c4fe6775698df15809978a2f5c From 2e76d384025bc11be88da5b0436f23940ad16a0a Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 11:52:29 +0100 Subject: [PATCH 11/14] fix: don't use Array.fill bc it breaks mutation --- src/lib/provable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/provable.ts b/src/lib/provable.ts index b3fa385eda..cd825d04db 100644 --- a/src/lib/provable.ts +++ b/src/lib/provable.ts @@ -573,7 +573,7 @@ function provableArray>( 'circuitArray.emptyValue: element type has no emptyValue method' ); } - return Array(length).fill(type.emptyValue()); + return Array.from({ length }, () => type.emptyValue()); }, } satisfies ProvableExtended as any; } From 000b03f97eafc7f8544d6c5b761f936be967d156 Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 12:14:22 +0100 Subject: [PATCH 12/14] rename emptyValue() to empty() --- src/bindings | 2 +- src/build/jsLayoutToTypes.mjs | 4 ++-- src/lib/account_update.ts | 4 ++-- src/lib/bool.ts | 2 +- src/lib/circuit_value.ts | 6 +++--- src/lib/events.ts | 16 +++++++--------- src/lib/field.ts | 2 +- src/lib/hash.ts | 2 +- src/lib/int.ts | 2 +- src/lib/mina.ts | 2 +- src/lib/mina/account.ts | 2 +- src/lib/provable.ts | 10 ++++------ src/lib/signature.ts | 4 ++-- src/lib/testing/random.ts | 12 ++++++------ src/mina-signer/MinaSigner.ts | 4 ++-- src/mina-signer/src/memo.ts | 2 +- src/mina-signer/src/sign-zkapp-command.ts | 2 +- .../src/sign-zkapp-command.unit-test.ts | 2 +- src/mina-signer/src/signature.unit-test.ts | 2 +- src/mina-signer/tests/zkapp.unit-test.ts | 2 +- src/provable/field-bigint.ts | 2 +- 21 files changed, 41 insertions(+), 45 deletions(-) diff --git a/src/bindings b/src/bindings index a92bf1a2e9..1dd31581aa 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit a92bf1a2e9cbe5c4fe6775698df15809978a2f5c +Subproject commit 1dd31581aacb3e6d76422063f052ea88c1451e1d diff --git a/src/build/jsLayoutToTypes.mjs b/src/build/jsLayoutToTypes.mjs index be9648bf51..d76907da9b 100644 --- a/src/build/jsLayoutToTypes.mjs +++ b/src/build/jsLayoutToTypes.mjs @@ -158,7 +158,7 @@ ${ !isJson ? 'export { Json };\n' + `export * from '${leavesRelPath}';\n` + - `export { ${fromLayout}, toJSONEssential, emptyValue, Layout, TypeMap };\n` + `export { ${fromLayout}, toJSONEssential, empty, Layout, TypeMap };\n` : `export * from '${leavesRelPath}';\n` + 'export { TypeMap };\n' } @@ -186,7 +186,7 @@ type CustomTypes = { ${customTypes .map((c) => `${c.typeName}: ${GeneratedType}<${c.type}, ${c.jsonType}>;`) .join(' ')} } let customTypes: CustomTypes = { ${customTypeNames.join(', ')} }; -let { ${fromLayout}, toJSONEssential, emptyValue } = ${FromLayout}< +let { ${fromLayout}, toJSONEssential, empty } = ${FromLayout}< TypeMap, Json.TypeMap >(TypeMap, customTypes); diff --git a/src/lib/account_update.ts b/src/lib/account_update.ts index 292b77d0cb..c1938bd5e8 100644 --- a/src/lib/account_update.ts +++ b/src/lib/account_update.ts @@ -445,7 +445,7 @@ const Body = { tokenId?: Field, mayUseToken?: MayUseToken ): Body { - let { body } = Types.AccountUpdate.emptyValue(); + let { body } = Types.AccountUpdate.empty(); body.publicKey = publicKey; if (tokenId) { body.tokenId = tokenId; @@ -463,7 +463,7 @@ const Body = { }, dummy(): Body { - return Types.AccountUpdate.emptyValue().body; + return Types.AccountUpdate.empty().body; }, }; diff --git a/src/lib/bool.ts b/src/lib/bool.ts index 15d0db2548..4abaeead51 100644 --- a/src/lib/bool.ts +++ b/src/lib/bool.ts @@ -295,7 +295,7 @@ class Bool { return 1; } - static emptyValue() { + static empty() { return new Bool(false); } diff --git a/src/lib/circuit_value.ts b/src/lib/circuit_value.ts index 2ac58ad54b..85ac7c28ba 100644 --- a/src/lib/circuit_value.ts +++ b/src/lib/circuit_value.ts @@ -49,7 +49,7 @@ type ProvableExtension = { toInput: (x: T) => { fields?: Field[]; packed?: [Field, number][] }; toJSON: (x: T) => TJson; fromJSON: (x: TJson) => T; - emptyValue: () => T; + empty: () => T; }; type ProvableExtended = Provable & @@ -248,11 +248,11 @@ abstract class CircuitValue { return Object.assign(Object.create(this.prototype), props); } - static emptyValue(): InstanceType { + static empty(): InstanceType { const fields: [string, any][] = (this as any).prototype._fields ?? []; let props: any = {}; fields.forEach(([key, propType]) => { - props[key] = propType.emptyValue(); + props[key] = propType.empty(); }); return Object.assign(Object.create(this.prototype), props); } diff --git a/src/lib/events.ts b/src/lib/events.ts index 04efe23185..70fce76400 100644 --- a/src/lib/events.ts +++ b/src/lib/events.ts @@ -60,7 +60,7 @@ function createEvents({ const EventsProvable = { ...Events, ...dataAsHash({ - emptyValue: Events.empty, + empty: Events.empty, toJSON(data: Field[][]) { return data.map((row) => row.map((e) => Field.toJSON(e))); }, @@ -107,7 +107,7 @@ function createEvents({ const SequenceEventsProvable = { ...Actions, ...dataAsHash({ - emptyValue: Actions.empty, + empty: Actions.empty, toJSON(data: Field[][]) { return data.map((row) => row.map((e) => Field.toJSON(e))); }, @@ -123,18 +123,16 @@ function createEvents({ } function dataAsHash({ - emptyValue, + empty, toJSON, fromJSON, }: { - emptyValue: () => { data: T; hash: Field }; + empty: () => { data: T; hash: Field }; toJSON: (value: T) => J; fromJSON: (json: J) => { data: T; hash: Field }; -}): GenericProvableExtended<{ data: T; hash: Field }, J, Field> & { - emptyValue(): { data: T; hash: Field }; -} { +}): GenericProvableExtended<{ data: T; hash: Field }, J, Field> { return { - emptyValue, + empty, sizeInFields() { return 1; }, @@ -142,7 +140,7 @@ function dataAsHash({ return [hash]; }, toAuxiliary(value) { - return [value?.data ?? emptyValue().data]; + return [value?.data ?? empty().data]; }, fromFields([hash], [data]) { return { data, hash }; diff --git a/src/lib/field.ts b/src/lib/field.ts index fe117f65ab..6df164143b 100644 --- a/src/lib/field.ts +++ b/src/lib/field.ts @@ -1148,7 +1148,7 @@ class Field { // ProvableExtended - static emptyValue() { + static empty() { return new Field(0n); } diff --git a/src/lib/hash.ts b/src/lib/hash.ts index 7a56b95b56..c6d66d3f9d 100644 --- a/src/lib/hash.ts +++ b/src/lib/hash.ts @@ -179,7 +179,7 @@ const TokenSymbolPure: ProvableExtended< toInput({ field }) { return { packed: [[field, 48]] }; }, - emptyValue() { + empty() { return { symbol: '', field: Field(0n) }; }, }; diff --git a/src/lib/int.ts b/src/lib/int.ts index 10a7813a3b..45ca4e4011 100644 --- a/src/lib/int.ts +++ b/src/lib/int.ts @@ -723,7 +723,7 @@ class Sign extends CircuitValue { // x^2 === 1 <=> x === 1 or x === -1 x.value.square().assertEquals(Field(1)); } - static emptyValue(): InstanceType { + static empty(): InstanceType { return Sign.one as any; } static toInput(x: Sign): HashInput { diff --git a/src/lib/mina.ts b/src/lib/mina.ts index 28d6e3e7bf..d4a55c6a8b 100644 --- a/src/lib/mina.ts +++ b/src/lib/mina.ts @@ -1240,7 +1240,7 @@ function getProofsEnabled() { } function dummyAccount(pubkey?: PublicKey): Account { - let dummy = Types.Account.emptyValue(); + let dummy = Types.Account.empty(); if (pubkey) dummy.publicKey = pubkey; return dummy; } diff --git a/src/lib/mina/account.ts b/src/lib/mina/account.ts index 7025b37508..dc31d0d864 100644 --- a/src/lib/mina/account.ts +++ b/src/lib/mina/account.ts @@ -192,7 +192,7 @@ function fillPartialAccount(account: PartialAccount): Account { map(type, value) { // if value exists, use it; otherwise fall back to dummy value if (value !== undefined) return value; - return type.emptyValue(); + return type.empty(); }, reduceArray(array) { return array; diff --git a/src/lib/provable.ts b/src/lib/provable.ts index cd825d04db..74992a9568 100644 --- a/src/lib/provable.ts +++ b/src/lib/provable.ts @@ -567,13 +567,11 @@ function provableArray>( ); }, - emptyValue() { - if (!('emptyValue' in type)) { - throw Error( - 'circuitArray.emptyValue: element type has no emptyValue method' - ); + empty() { + if (!('empty' in type)) { + throw Error('circuitArray.empty: element type has no empty() method'); } - return Array.from({ length }, () => type.emptyValue()); + return Array.from({ length }, () => type.empty()); }, } satisfies ProvableExtended as any; } diff --git a/src/lib/signature.ts b/src/lib/signature.ts index e26e68ca2b..58d68ccef0 100644 --- a/src/lib/signature.ts +++ b/src/lib/signature.ts @@ -165,8 +165,8 @@ class PublicKey extends CircuitValue { * Creates an empty {@link PublicKey}. * @returns an empty {@link PublicKey} */ - static empty() { - return PublicKey.from({ x: Field(0), isOdd: Bool(false) }); + static empty(): InstanceType { + return PublicKey.from({ x: Field(0), isOdd: Bool(false) }) as any; } /** diff --git a/src/lib/testing/random.ts b/src/lib/testing/random.ts index 4821df520b..2880ec51f8 100644 --- a/src/lib/testing/random.ts +++ b/src/lib/testing/random.ts @@ -5,7 +5,7 @@ import { Json, AccountUpdate, ZkappCommand, - emptyValue, + empty, } from '../../bindings/mina-transaction/gen/transaction-bigint.js'; import { AuthRequired, @@ -81,7 +81,7 @@ const keypair = map(privateKey, (privatekey) => ({ publicKey: PrivateKey.toPublicKey(privatekey), })); -const tokenId = oneOf(TokenId.emptyValue(), field); +const tokenId = oneOf(TokenId.empty(), field); const stateHash = field; const authRequired = map( oneOf( @@ -106,9 +106,9 @@ const actions = mapWithInvalid( array(array(field, int(1, 5)), nat(2)), Actions.fromList ); -const actionState = oneOf(ActionState.emptyValue(), field); -const verificationKeyHash = oneOf(VerificationKeyHash.emptyValue(), field); -const receiptChainHash = oneOf(ReceiptChainHash.emptyValue(), field); +const actionState = oneOf(ActionState.empty(), field); +const verificationKeyHash = oneOf(VerificationKeyHash.empty(), field); +const receiptChainHash = oneOf(ReceiptChainHash.empty(), field); const zkappUri = map(string(nat(50)), ZkappUri.fromJSON); type Types = typeof TypeMap & typeof customTypes & PrimitiveTypeMap; @@ -365,7 +365,7 @@ function generatorFromLayout( } else { return mapWithInvalid(isSome, value, (isSome, value) => { let isSomeBoolean = TypeMap.Bool.toJSON(isSome); - if (!isSomeBoolean) return emptyValue(typeData); + if (!isSomeBoolean) return empty(typeData); return { isSome, value }; }); } diff --git a/src/mina-signer/MinaSigner.ts b/src/mina-signer/MinaSigner.ts index 36c94e3acb..d4dce0e2df 100644 --- a/src/mina-signer/MinaSigner.ts +++ b/src/mina-signer/MinaSigner.ts @@ -85,9 +85,9 @@ class Client { ) { throw Error('Public key not derivable from private key'); } - let dummy = ZkappCommand.toJSON(ZkappCommand.emptyValue()); + let dummy = ZkappCommand.toJSON(ZkappCommand.empty()); dummy.feePayer.body.publicKey = publicKey; - dummy.memo = Memo.toBase58(Memo.emptyValue()); + dummy.memo = Memo.toBase58(Memo.empty()); let signed = signZkappCommand(dummy, privateKey, this.network); let ok = verifyZkappCommandSignature(signed, publicKey, this.network); if (!ok) throw Error('Could not sign a transaction with private key'); diff --git a/src/mina-signer/src/memo.ts b/src/mina-signer/src/memo.ts index 8b3ae05f6f..04538c3965 100644 --- a/src/mina-signer/src/memo.ts +++ b/src/mina-signer/src/memo.ts @@ -63,7 +63,7 @@ const Memo = { ...withBits(Binable, SIZE * 8), ...base58(Binable, versionBytes.userCommandMemo), sizeInBytes: SIZE, - emptyValue() { + empty() { return Memo.fromString(''); }, toValidString(memo = '') { diff --git a/src/mina-signer/src/sign-zkapp-command.ts b/src/mina-signer/src/sign-zkapp-command.ts index 69578ed193..07d8a37c62 100644 --- a/src/mina-signer/src/sign-zkapp-command.ts +++ b/src/mina-signer/src/sign-zkapp-command.ts @@ -180,7 +180,7 @@ function accountUpdateFromFeePayer({ body: { fee, nonce, publicKey, validUntil }, authorization: signature, }: FeePayer): AccountUpdate { - let { body } = AccountUpdate.emptyValue(); + let { body } = AccountUpdate.empty(); body.publicKey = publicKey; body.balanceChange = { magnitude: fee, sgn: Sign(-1) }; body.incrementNonce = Bool(true); diff --git a/src/mina-signer/src/sign-zkapp-command.unit-test.ts b/src/mina-signer/src/sign-zkapp-command.unit-test.ts index 7538dbd9ff..e400f9c8d4 100644 --- a/src/mina-signer/src/sign-zkapp-command.unit-test.ts +++ b/src/mina-signer/src/sign-zkapp-command.unit-test.ts @@ -62,7 +62,7 @@ test(Random.json.publicKey, (publicKeyBase58) => { }); // empty account update -let dummy = AccountUpdate.emptyValue(); +let dummy = AccountUpdate.empty(); let dummySnarky = AccountUpdateSnarky.dummy(); expect(AccountUpdate.toJSON(dummy)).toEqual( AccountUpdateSnarky.toJSON(dummySnarky) diff --git a/src/mina-signer/src/signature.unit-test.ts b/src/mina-signer/src/signature.unit-test.ts index 2fb520f02c..9743bda23b 100644 --- a/src/mina-signer/src/signature.unit-test.ts +++ b/src/mina-signer/src/signature.unit-test.ts @@ -122,7 +122,7 @@ for (let i = 0; i < 10; i++) { [0xffff_ffff_ffff_ffffn, 64], ], }, - AccountUpdate.toInput(AccountUpdate.emptyValue()), + AccountUpdate.toInput(AccountUpdate.empty()), ]; for (let msg of messages) { checkCanVerify(msg, key, publicKey); diff --git a/src/mina-signer/tests/zkapp.unit-test.ts b/src/mina-signer/tests/zkapp.unit-test.ts index 64d83c2bca..5c2aaf6a3f 100644 --- a/src/mina-signer/tests/zkapp.unit-test.ts +++ b/src/mina-signer/tests/zkapp.unit-test.ts @@ -11,7 +11,7 @@ import { mocks } from '../../bindings/crypto/constants.js'; const client = new Client({ network: 'testnet' }); let { publicKey, privateKey } = client.genKeys(); -let dummy = ZkappCommand.toJSON(ZkappCommand.emptyValue()); +let dummy = ZkappCommand.toJSON(ZkappCommand.empty()); let dummySignature = Signature.toBase58(Signature.dummy()); // we construct a transaction which needs signing of the fee payer and another account update diff --git a/src/provable/field-bigint.ts b/src/provable/field-bigint.ts index 88e6afd5cd..c23e0e0bc4 100644 --- a/src/provable/field-bigint.ts +++ b/src/provable/field-bigint.ts @@ -109,7 +109,7 @@ const Sign = pseudoClass( { ...ProvableBigint(checkSign), ...BinableBigint(1, checkSign), - emptyValue() { + empty() { return 1n; }, toInput(x: Sign): HashInput { From 3cd9e0bb18fb4ae760cedff4e35c248aacb3b833 Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 12:18:55 +0100 Subject: [PATCH 13/14] expose empty on struct --- src/lib/circuit_value.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/circuit_value.ts b/src/lib/circuit_value.ts index 85ac7c28ba..d0a85e5cc9 100644 --- a/src/lib/circuit_value.ts +++ b/src/lib/circuit_value.ts @@ -441,6 +441,15 @@ function Struct< let struct = Object.create(this.prototype); return Object.assign(struct, value); } + /** + * Create an instance of this struct filled with default values + * @returns an empty instance of this struct + */ + static empty(): T { + let value = this.type.empty(); + let struct = Object.create(this.prototype); + return Object.assign(struct, value); + } /** * This method is for internal use, you will probably not need it. * Method to make assertions which should be always made whenever a struct of this type is created in a proof. From c99a92320c2aedf7844baa47b95a57f691e68109 Mon Sep 17 00:00:00 2001 From: Gregor Date: Mon, 27 Nov 2023 15:23:44 +0100 Subject: [PATCH 14/14] fix bool.sizeInBits --- src/lib/bool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/bool.ts b/src/lib/bool.ts index 4abaeead51..9d7fee9e4d 100644 --- a/src/lib/bool.ts +++ b/src/lib/bool.ts @@ -318,7 +318,7 @@ class Bool { return BoolBinable.readBytes(bytes, offset); } - static sizeInBytes: 1; + static sizeInBytes = 1; static check(x: Bool): void { Snarky.field.assertBoolean(x.value);