Skip to content

Commit

Permalink
implement toFields and make strings 31 chars (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
45930 authored Jan 9, 2024
1 parent b162529 commit 7c8230e
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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!
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "o1js-pack",
"version": "0.4.4",
"version": "0.5.0",
"description": "",
"author": "45930",
"license": "Apache-2.0",
Expand Down
16 changes: 16 additions & 0 deletions src/lib/PackingPlant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ export function PackingPlant<A, T extends InferProvable<A> = InferProvable<A>>(
return unpacked;
}

// 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<Field> {
return [this.packed];
}

assertEquals(other: Packed_) {
this.packed.assertEquals(other.packed);
}
Expand Down Expand Up @@ -216,6 +224,14 @@ export function MultiPackingPlant<
return uints_;
}

// 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<Field> {
return this.packed;
}

assertEquals(other: Packed_) {
for (let x = 0; x < n; x++) {
this.packed[x].assertEquals(other.packed[x]);
Expand Down
41 changes: 36 additions & 5 deletions src/lib/packed-types/PackedString.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Character> = [];

beforeEach(() => {
Expand All @@ -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) {}

Expand All @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions src/lib/packed-types/PackedString.ts
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions tests/provable/example_packed_string_circuit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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<TextInput, TextInput>,
Expand Down

0 comments on commit 7c8230e

Please sign in to comment.