Skip to content

Commit

Permalink
fix: allow abi encoding arrays of structs from JS (#3867)
Browse files Browse the repository at this point in the history
# Description

## Problem\*

Resolves <!-- Link to GitHub Issue -->

## Summary\*

We currently do not allow arrays of structs when abi encoding from JS
due to the `InputValue` type being too restrictive. This PR loosens this
and adds a test to demonstrate how this is used.

## Additional Context



## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
TomAFrench committed Dec 19, 2023
1 parent a40269a commit 9b713f8
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 1 deletion.
2 changes: 1 addition & 1 deletion tooling/noirc_abi_wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use js_witness_map::JsWitnessMap;
#[wasm_bindgen(typescript_custom_section)]
const INPUT_MAP: &'static str = r#"
export type Field = string | number | boolean;
export type InputValue = Field | Field[] | InputMap;
export type InputValue = Field | Field[] | InputMap | InputMap[];
export type InputMap = { [key: string]: InputValue };
"#;

Expand Down
26 changes: 26 additions & 0 deletions tooling/noirc_abi_wasm/test/browser/structs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { expect } from '@esm-bundle/chai';
import initNoirAbi, { abiEncode, abiDecode, WitnessMap } from '@noir-lang/noirc_abi';
import { MyNestedStruct, MyStruct } from '../shared/structs';
import { DecodedInputs } from '../types';

beforeEach(async () => {
await initNoirAbi();
});

it('correctly handles struct inputs', async () => {
const { abi, inputs } = await import('../shared/structs');

const initial_witness: WitnessMap = abiEncode(abi, inputs);
const decoded_inputs: DecodedInputs = abiDecode(abi, initial_witness);

const struct_arg: MyStruct = inputs.struct_arg as MyStruct;
const struct_array_arg: MyStruct[] = inputs.struct_array_arg as MyStruct[];
const nested_struct_arg: MyNestedStruct = inputs.nested_struct_arg as MyNestedStruct;

expect(BigInt(decoded_inputs.inputs.struct_arg.foo)).to.be.equal(BigInt(struct_arg.foo));
expect(BigInt(decoded_inputs.inputs.struct_array_arg[0].foo)).to.be.equal(BigInt(struct_array_arg[0].foo));
expect(BigInt(decoded_inputs.inputs.struct_array_arg[1].foo)).to.be.equal(BigInt(struct_array_arg[1].foo));
expect(BigInt(decoded_inputs.inputs.struct_array_arg[2].foo)).to.be.equal(BigInt(struct_array_arg[2].foo));
expect(BigInt(decoded_inputs.inputs.nested_struct_arg.foo.foo)).to.be.equal(BigInt(nested_struct_arg.foo.foo));
expect(decoded_inputs.return_value).to.be.null;
});
22 changes: 22 additions & 0 deletions tooling/noirc_abi_wasm/test/node/structs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expect } from 'chai';
import { abiEncode, abiDecode, WitnessMap } from '@noir-lang/noirc_abi';
import { MyNestedStruct, MyStruct } from '../shared/structs';
import { DecodedInputs } from '../types';

it('correctly handles struct inputs', async () => {
const { abi, inputs } = await import('../shared/structs');

const initial_witness: WitnessMap = abiEncode(abi, inputs);
const decoded_inputs: DecodedInputs = abiDecode(abi, initial_witness);

const struct_arg: MyStruct = inputs.struct_arg as MyStruct;
const struct_array_arg: MyStruct[] = inputs.struct_array_arg as MyStruct[];
const nested_struct_arg: MyNestedStruct = inputs.nested_struct_arg as MyNestedStruct;

expect(BigInt(decoded_inputs.inputs.struct_arg.foo)).to.be.equal(BigInt(struct_arg.foo));
expect(BigInt(decoded_inputs.inputs.struct_array_arg[0].foo)).to.be.equal(BigInt(struct_array_arg[0].foo));
expect(BigInt(decoded_inputs.inputs.struct_array_arg[1].foo)).to.be.equal(BigInt(struct_array_arg[1].foo));
expect(BigInt(decoded_inputs.inputs.struct_array_arg[2].foo)).to.be.equal(BigInt(struct_array_arg[2].foo));
expect(BigInt(decoded_inputs.inputs.nested_struct_arg.foo.foo)).to.be.equal(BigInt(nested_struct_arg.foo.foo));
expect(decoded_inputs.return_value).to.be.null;
});
79 changes: 79 additions & 0 deletions tooling/noirc_abi_wasm/test/shared/structs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Abi, Field, InputMap } from '@noir-lang/noirc_abi';

export type MyStruct = {
foo: Field;
};

export type MyNestedStruct = {
foo: MyStruct;
};

export const abi: Abi = {
parameters: [
{
name: 'struct_arg',
type: { kind: 'struct', path: 'MyStruct', fields: [{ name: 'foo', type: { kind: 'field' } }] },
visibility: 'private',
},
{
name: 'struct_array_arg',
type: {
kind: 'array',
type: {
kind: 'struct',
path: 'MyStruct',
fields: [{ name: 'foo', type: { kind: 'field' } }],
},
length: 3,
},
visibility: 'private',
},
{
name: 'nested_struct_arg',
type: {
kind: 'struct',
path: 'MyNestedStruct',
fields: [
{
name: 'foo',
type: {
kind: 'struct',
path: 'MyStruct',
fields: [{ name: 'foo', type: { kind: 'field' } }],
},
},
],
},
visibility: 'private',
},
],
param_witnesses: {
struct_arg: [{ start: 1, end: 2 }],
struct_array_arg: [{ start: 2, end: 5 }],
nested_struct_arg: [{ start: 5, end: 6 }],
},
return_type: null,
return_witnesses: [],
};

export const inputs: InputMap = {
struct_arg: {
foo: '1',
},
struct_array_arg: [
{
foo: '2',
},
{
foo: '3',
},
{
foo: '4',
},
],
nested_struct_arg: {
foo: {
foo: '5',
},
},
};

0 comments on commit 9b713f8

Please sign in to comment.