diff --git a/CHANGELOG.md b/CHANGELOG.md index de4d0dd104..cbb7280cde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Fixes - Fix type inference for `method.returns(Type)`, to require a matching return signature https://github.com/o1-labs/o1js/pull/1653 +- Fix `Struct.empty()` returning a garbage object when one of the base types doesn't support `empty()` https://github.com/o1-labs/o1js/pull/1657 ## [1.2.0](https://github.com/o1-labs/o1js/compare/4a17de857...6a1012162) - 2024-05-14 diff --git a/src/bindings b/src/bindings index 03241cd44f..55481e7444 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 03241cd44f895249fc28dda7bd133479f2ef0de2 +Subproject commit 55481e7444b48cd452375bc8a23a5a5fc42264b7 diff --git a/src/lib/provable/group.ts b/src/lib/provable/group.ts index 10a30e3fc7..5584e7d59d 100644 --- a/src/lib/provable/group.ts +++ b/src/lib/provable/group.ts @@ -352,6 +352,10 @@ class Group { fields: [x.x, x.y], }; } + + static empty() { + return Group.zero; + } } // internal helpers @@ -360,10 +364,6 @@ function isConstant(g: Group) { return g.x.isConstant() && g.y.isConstant(); } -function toTuple(g: Group): [0, FieldVar, FieldVar] { - return [0, g.x.value, g.y.value]; -} - function toProjective(g: Group) { return Pallas.fromAffine({ x: g.x.toBigInt(), diff --git a/src/lib/provable/scalar.ts b/src/lib/provable/scalar.ts index 2277b304d3..fe4602fbd1 100644 --- a/src/lib/provable/scalar.ts +++ b/src/lib/provable/scalar.ts @@ -317,6 +317,10 @@ class Scalar implements ShiftedScalar { static fromJSON(x: string) { return Scalar.from(SignableFq.fromJSON(x)); } + + static empty() { + return Scalar.from(0n); + } } // internal helpers diff --git a/src/lib/provable/test/struct.unit-test.ts b/src/lib/provable/test/struct.unit-test.ts index 5fae21d659..5554aafc81 100644 --- a/src/lib/provable/test/struct.unit-test.ts +++ b/src/lib/provable/test/struct.unit-test.ts @@ -18,6 +18,8 @@ import { Bool } from '../bool.js'; import assert from 'assert/strict'; import { FieldType } from '../core/fieldvar.js'; import { From } from '../../../bindings/lib/provable-generic.js'; +import { Group } from '../group.js'; +import { modifiedField } from '../types/fields.js'; let type = provable({ nested: { a: Number, b: Boolean }, @@ -85,6 +87,26 @@ expect(jsValue).toEqual({ expect(type.fromValue(jsValue)).toEqual(value); +// empty +let empty = type.empty(); +expect(empty).toEqual({ + nested: { a: 0, b: false }, + other: '', + pk: PublicKey.empty(), + bool: new Bool(false), + uint: [UInt32.zero, UInt32.zero], +}); + +// empty with Group +expect(provable({ value: Group }).empty()).toEqual({ value: Group.zero }); + +// fails with a clear error on input without an empty method +const FieldWithoutEmpty = modifiedField({}); +delete (FieldWithoutEmpty as any).empty; +expect(() => provable({ value: FieldWithoutEmpty }).empty()).toThrow( + 'Expected `empty()` method on anonymous type object' +); + // check await Provable.runAndCheck(() => { type.check(value); @@ -120,7 +142,7 @@ class MyStructPure extends Struct({ uint: [UInt32, UInt32], }) {} -// Struct.from() works on both js and provable inputs +// Struct.fromValue() works on both js and provable inputs let myStructInput = { nested: { a: Field(1), b: 2n }, diff --git a/src/lib/provable/types/struct.ts b/src/lib/provable/types/struct.ts index 587b2efa3f..60e9d23c30 100644 --- a/src/lib/provable/types/struct.ts +++ b/src/lib/provable/types/struct.ts @@ -1,7 +1,6 @@ import { Field, Bool, Scalar, Group } from '../wrapped.js'; import { provable, - provablePure, provableTuple, HashInput, NonMethods,