Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement toFields and make strings 31 chars #18

Merged
merged 5 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading