From 67123f37bea083a6a3683ff7615b50e2310eb902 Mon Sep 17 00:00:00 2001 From: Coby Date: Mon, 8 Jan 2024 20:26:07 -0500 Subject: [PATCH 1/5] implement toFields and make strings 31 chars --- src/lib/PackingPlant.ts | 14 ++++++++ src/lib/packed-types/PackedString.test.ts | 41 ++++++++++++++++++++--- src/lib/packed-types/PackedString.ts | 6 ++-- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/lib/PackingPlant.ts b/src/lib/PackingPlant.ts index 7ad518d..04269f1 100644 --- a/src/lib/PackingPlant.ts +++ b/src/lib/PackingPlant.ts @@ -92,6 +92,13 @@ export function PackingPlant = InferProvable>( return unpacked; } + /** + * @returns array of single Field element which constitute the packed object + */ + toFields(): Array { + return [this.packed]; + } + assertEquals(other: Packed_) { this.packed.assertEquals(other.packed); } @@ -216,6 +223,13 @@ export function MultiPackingPlant< return uints_; } + /** + * @returns array of Field elements which constitute the multi-packed object + */ + toFields(): Array { + return this.packed; + } + assertEquals(other: Packed_) { for (let x = 0; x < n; x++) { this.packed[x].assertEquals(other.packed[x]); diff --git a/src/lib/packed-types/PackedString.test.ts b/src/lib/packed-types/PackedString.test.ts index ced12c7..1417ca5 100644 --- a/src/lib/packed-types/PackedString.test.ts +++ b/src/lib/packed-types/PackedString.test.ts @@ -4,7 +4,7 @@ import { PackedStringFactory, MultiPackedStringFactory } from './PackedString'; describe('PackedString', () => { describe('Outside of the Circuit', () => { const vitalik_dot_eth = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; - class EthAddressString extends MultiPackedStringFactory(3) {} + class EthAddressString extends MultiPackedStringFactory(2) {} let characters: Array = []; beforeEach(() => { @@ -30,17 +30,48 @@ describe('PackedString', () => { ); const packed = EthAddressString.pack(unpacked); - expect(packed.length).toBe(Math.ceil(vitalik_dot_eth.length / 15)); + expect(packed.length).toBe(Math.ceil(vitalik_dot_eth.length / 31)); expect(unpacked.length).toBe(EthAddressString.l); - expect(unpacked.length).toBe(45); + expect(unpacked.length).toBe(62); expect(unpacked.slice(0, characters.length).toString()).toBe( characters.toString() ); }); + + it('#toFields', () => { + class Single extends PackedStringFactory() {} + class Double extends MultiPackedStringFactory(2) {} + const abbaPacked = '1633837665'; + + expect(Single.fromString('abba').toFields().toString()).toBe( + [Single.fromString('abba').packed].toString() + ); + expect(Single.fromString('abba').toFields().toString()).toBe(abbaPacked); + expect( + Single.unpack(Field(abbaPacked)).slice(0, 4).join('').toString() + ).toBe('abba'); + + const abbaAlot = 'abba'.repeat(10); + const abbaAlotPacked1 = + '173830008860859097861870638220020642754739197069143560335286125952244015713'; + const abbaAlotPacked2 = '1796423510984151425377'; + expect(Double.fromString(abbaAlot).toFields().toString()).toBe( + [Double.fromString(abbaAlot).packed].toString() + ); + expect(Double.fromString(abbaAlot).toFields().toString()).toBe( + abbaAlotPacked1 + ',' + abbaAlotPacked2 + ); + expect( + Double.unpack([Field(abbaAlotPacked1), Field(abbaAlotPacked2)]) + .slice(0, 40) + .join('') + .toString() + ).toBe(abbaAlot); + }); }); describe('Provable Properties', () => { it('#sizeInFields', () => { - class one extends PackedStringFactory(15) {} + class one extends PackedStringFactory(31) {} class two extends MultiPackedStringFactory(2) {} class three extends MultiPackedStringFactory(3) {} @@ -67,7 +98,7 @@ describe('PackedString', () => { }).toThrow(); }); it('Exceeds maximum size string', () => { - const tooLong = 'too long!'.repeat(20); + const tooLong = 'too long!'.repeat(50); class MaxString extends MultiPackedStringFactory(8) {} expect(() => { MaxString.fromString(tooLong); diff --git a/src/lib/packed-types/PackedString.ts b/src/lib/packed-types/PackedString.ts index 85b8c19..8fdbab0 100644 --- a/src/lib/packed-types/PackedString.ts +++ b/src/lib/packed-types/PackedString.ts @@ -1,9 +1,9 @@ import { Field, Provable, Character, Poseidon } from 'o1js'; import { PackingPlant, MultiPackingPlant } from '../PackingPlant.js'; -const SIZE_IN_BITS = 16n; -const L = 15; // Default to one-field worth of characters -const CHARS_PER_FIELD = 15; +const SIZE_IN_BITS = 8n; +const L = 31; // Default to one-field worth of characters +const CHARS_PER_FIELD = 31; export function PackedStringFactory(l: number = L) { class PackedString_ extends PackingPlant(Character, l, SIZE_IN_BITS) { From 047a534d3b4f25b2ad55f3f0417bfcb98ec91c39 Mon Sep 17 00:00:00 2001 From: Coby Date: Mon, 8 Jan 2024 20:30:28 -0500 Subject: [PATCH 2/5] changelog and package version --- .eslintrc.cjs | 2 +- CHANGELOG.md | 5 +++++ package.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 818c574..e15928e 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -16,7 +16,7 @@ module.exports = { ecmaVersion: 'latest', }, plugins: ['@typescript-eslint', 'o1js'], - ignorePatterns: ['README.md'], + ignorePatterns: ['*.md'], rules: { 'no-constant-condition': 'off', 'prefer-const': 'off', diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6490c3b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +## v0.5 + +- Making PackedString class 31 characters instead of 15 + - This has implications in any source code using the default packed string implementation + - Unpacked character arrays will now be 31 characters long, so code expecting a 15-character array may break! diff --git a/package.json b/package.json index 57383c5..2bde520 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "o1js-pack", - "version": "0.4.4", + "version": "0.5.0", "description": "", "author": "45930", "license": "Apache-2.0", From f9d9c3f5aa018d41cb83e5cc1d4cc5bc17dffab5 Mon Sep 17 00:00:00 2001 From: Coby Date: Mon, 8 Jan 2024 20:34:58 -0500 Subject: [PATCH 3/5] cant use toFields --- src/lib/PackingPlant.ts | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/lib/PackingPlant.ts b/src/lib/PackingPlant.ts index 04269f1..91f1a31 100644 --- a/src/lib/PackingPlant.ts +++ b/src/lib/PackingPlant.ts @@ -92,12 +92,13 @@ export function PackingPlant = InferProvable>( return unpacked; } - /** - * @returns array of single Field element which constitute the packed object - */ - toFields(): Array { - return [this.packed]; - } + // NOTE: adding to fields here breaks the proof generation. Probably not overriding it correctly + // /** + // * @returns array of single Field element which constitute the packed object + // */ + // toFields(): Array { + // return [this.packed]; + // } assertEquals(other: Packed_) { this.packed.assertEquals(other.packed); @@ -223,12 +224,13 @@ export function MultiPackingPlant< return uints_; } - /** - * @returns array of Field elements which constitute the multi-packed object - */ - toFields(): Array { - return this.packed; - } + // NOTE: adding to fields here breaks the proof generation. Probably not overriding it correctly + // /** + // * @returns array of Field elements which constitute the multi-packed object + // */ + // toFields(): Array { + // return this.packed; + // } assertEquals(other: Packed_) { for (let x = 0; x < n; x++) { From 9281d3840e626ed1a4e5726535edffeea54a6f5e Mon Sep 17 00:00:00 2001 From: Coby Date: Mon, 8 Jan 2024 20:38:25 -0500 Subject: [PATCH 4/5] cant use toFields (test) --- src/lib/packed-types/PackedString.test.ts | 60 +++++++++++------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/lib/packed-types/PackedString.test.ts b/src/lib/packed-types/PackedString.test.ts index 1417ca5..097f066 100644 --- a/src/lib/packed-types/PackedString.test.ts +++ b/src/lib/packed-types/PackedString.test.ts @@ -38,36 +38,36 @@ describe('PackedString', () => { ); }); - it('#toFields', () => { - class Single extends PackedStringFactory() {} - class Double extends MultiPackedStringFactory(2) {} - const abbaPacked = '1633837665'; - - expect(Single.fromString('abba').toFields().toString()).toBe( - [Single.fromString('abba').packed].toString() - ); - expect(Single.fromString('abba').toFields().toString()).toBe(abbaPacked); - expect( - Single.unpack(Field(abbaPacked)).slice(0, 4).join('').toString() - ).toBe('abba'); - - const abbaAlot = 'abba'.repeat(10); - const abbaAlotPacked1 = - '173830008860859097861870638220020642754739197069143560335286125952244015713'; - const abbaAlotPacked2 = '1796423510984151425377'; - expect(Double.fromString(abbaAlot).toFields().toString()).toBe( - [Double.fromString(abbaAlot).packed].toString() - ); - expect(Double.fromString(abbaAlot).toFields().toString()).toBe( - abbaAlotPacked1 + ',' + abbaAlotPacked2 - ); - expect( - Double.unpack([Field(abbaAlotPacked1), Field(abbaAlotPacked2)]) - .slice(0, 40) - .join('') - .toString() - ).toBe(abbaAlot); - }); + // it.skip('#toFields', () => { + // class Single extends PackedStringFactory() {} + // class Double extends MultiPackedStringFactory(2) {} + // const abbaPacked = '1633837665'; + + // expect(Single.fromString('abba').toFields().toString()).toBe( + // [Single.fromString('abba').packed].toString() + // ); + // expect(Single.fromString('abba').toFields().toString()).toBe(abbaPacked); + // expect( + // Single.unpack(Field(abbaPacked)).slice(0, 4).join('').toString() + // ).toBe('abba'); + + // const abbaAlot = 'abba'.repeat(10); + // const abbaAlotPacked1 = + // '173830008860859097861870638220020642754739197069143560335286125952244015713'; + // const abbaAlotPacked2 = '1796423510984151425377'; + // expect(Double.fromString(abbaAlot).toFields().toString()).toBe( + // [Double.fromString(abbaAlot).packed].toString() + // ); + // expect(Double.fromString(abbaAlot).toFields().toString()).toBe( + // abbaAlotPacked1 + ',' + abbaAlotPacked2 + // ); + // expect( + // Double.unpack([Field(abbaAlotPacked1), Field(abbaAlotPacked2)]) + // .slice(0, 40) + // .join('') + // .toString() + // ).toBe(abbaAlot); + // }); }); describe('Provable Properties', () => { it('#sizeInFields', () => { From 274ec5151b728fda7c8850ca0f80dfa3f347a05e Mon Sep 17 00:00:00 2001 From: Coby Date: Mon, 8 Jan 2024 20:50:33 -0500 Subject: [PATCH 5/5] fixing tests --- src/lib/PackingPlant.ts | 24 ++++---- src/lib/packed-types/PackedString.test.ts | 60 +++++++++---------- .../provable/example_packed_string_circuit.ts | 6 +- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/lib/PackingPlant.ts b/src/lib/PackingPlant.ts index 91f1a31..fb56b6b 100644 --- a/src/lib/PackingPlant.ts +++ b/src/lib/PackingPlant.ts @@ -93,12 +93,12 @@ export function PackingPlant = InferProvable>( } // NOTE: adding to fields here breaks the proof generation. Probably not overriding it correctly - // /** - // * @returns array of single Field element which constitute the packed object - // */ - // toFields(): Array { - // return [this.packed]; - // } + /** + * @returns array of single Field element which constitute the packed object + */ + toFields(): Array { + return [this.packed]; + } assertEquals(other: Packed_) { this.packed.assertEquals(other.packed); @@ -225,12 +225,12 @@ export function MultiPackingPlant< } // NOTE: adding to fields here breaks the proof generation. Probably not overriding it correctly - // /** - // * @returns array of Field elements which constitute the multi-packed object - // */ - // toFields(): Array { - // return this.packed; - // } + /** + * @returns array of Field elements which constitute the multi-packed object + */ + toFields(): Array { + return this.packed; + } assertEquals(other: Packed_) { for (let x = 0; x < n; x++) { diff --git a/src/lib/packed-types/PackedString.test.ts b/src/lib/packed-types/PackedString.test.ts index 097f066..1417ca5 100644 --- a/src/lib/packed-types/PackedString.test.ts +++ b/src/lib/packed-types/PackedString.test.ts @@ -38,36 +38,36 @@ describe('PackedString', () => { ); }); - // it.skip('#toFields', () => { - // class Single extends PackedStringFactory() {} - // class Double extends MultiPackedStringFactory(2) {} - // const abbaPacked = '1633837665'; - - // expect(Single.fromString('abba').toFields().toString()).toBe( - // [Single.fromString('abba').packed].toString() - // ); - // expect(Single.fromString('abba').toFields().toString()).toBe(abbaPacked); - // expect( - // Single.unpack(Field(abbaPacked)).slice(0, 4).join('').toString() - // ).toBe('abba'); - - // const abbaAlot = 'abba'.repeat(10); - // const abbaAlotPacked1 = - // '173830008860859097861870638220020642754739197069143560335286125952244015713'; - // const abbaAlotPacked2 = '1796423510984151425377'; - // expect(Double.fromString(abbaAlot).toFields().toString()).toBe( - // [Double.fromString(abbaAlot).packed].toString() - // ); - // expect(Double.fromString(abbaAlot).toFields().toString()).toBe( - // abbaAlotPacked1 + ',' + abbaAlotPacked2 - // ); - // expect( - // Double.unpack([Field(abbaAlotPacked1), Field(abbaAlotPacked2)]) - // .slice(0, 40) - // .join('') - // .toString() - // ).toBe(abbaAlot); - // }); + it('#toFields', () => { + class Single extends PackedStringFactory() {} + class Double extends MultiPackedStringFactory(2) {} + const abbaPacked = '1633837665'; + + expect(Single.fromString('abba').toFields().toString()).toBe( + [Single.fromString('abba').packed].toString() + ); + expect(Single.fromString('abba').toFields().toString()).toBe(abbaPacked); + expect( + Single.unpack(Field(abbaPacked)).slice(0, 4).join('').toString() + ).toBe('abba'); + + const abbaAlot = 'abba'.repeat(10); + const abbaAlotPacked1 = + '173830008860859097861870638220020642754739197069143560335286125952244015713'; + const abbaAlotPacked2 = '1796423510984151425377'; + expect(Double.fromString(abbaAlot).toFields().toString()).toBe( + [Double.fromString(abbaAlot).packed].toString() + ); + expect(Double.fromString(abbaAlot).toFields().toString()).toBe( + abbaAlotPacked1 + ',' + abbaAlotPacked2 + ); + expect( + Double.unpack([Field(abbaAlotPacked1), Field(abbaAlotPacked2)]) + .slice(0, 40) + .join('') + .toString() + ).toBe(abbaAlot); + }); }); describe('Provable Properties', () => { it('#sizeInFields', () => { diff --git a/tests/provable/example_packed_string_circuit.ts b/tests/provable/example_packed_string_circuit.ts index 630239c..b6e63dd 100644 --- a/tests/provable/example_packed_string_circuit.ts +++ b/tests/provable/example_packed_string_circuit.ts @@ -6,9 +6,9 @@ import { Provable, Field, } from 'o1js'; -import { MultiPackedStringFactory } from '../../src/lib/packed-types/PackedString'; +import { PackedStringFactory } from '../../src/lib/packed-types/PackedString'; -export class TextInput extends MultiPackedStringFactory(3) {} +export class TextInput extends PackedStringFactory() {} export const TextInputProgram = ZkProgram({ name: 'TextInputProgram', @@ -23,7 +23,7 @@ export const TextInputProgram = ZkProgram({ }, }, changeFirstLetter: { - privateInputs: [SelfProof, Provable.Array(Character, 45), Character], + privateInputs: [SelfProof, Provable.Array(Character, 31), Character], method( newState: TextInput, oldProof: SelfProof,