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",
diff --git a/src/lib/PackingPlant.ts b/src/lib/PackingPlant.ts
index 7ad518d..fb56b6b 100644
--- a/src/lib/PackingPlant.ts
+++ b/src/lib/PackingPlant.ts
@@ -92,6 +92,14 @@ export function PackingPlant = InferProvable>(
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 {
+ return [this.packed];
+ }
+
assertEquals(other: Packed_) {
this.packed.assertEquals(other.packed);
}
@@ -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 {
+ 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) {
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,