Skip to content

Commit

Permalink
feat: add foreign call support to noir_codegen functions (#3933)
Browse files Browse the repository at this point in the history
# Description

## Problem\*

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

## Summary\*

This PR exposes custom foreign call handler functionality into the
functions which are codegened by `noir_codegen`.

## 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 authored Jan 4, 2024
1 parent 4b16090 commit e5e52a8
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 6 deletions.
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/monomorphization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ impl<'interner> Monomorphizer<'interner> {
}

/// Adds a function argument that contains type metadata that is required to tell
/// `println` how to convert values passed to an foreign call back to a human-readable string.
/// `println` how to convert values passed to an foreign call back to a human-readable string.
/// The values passed to an foreign call will be a simple list of field elements,
/// thus requiring extra metadata to correctly decode this list of elements.
///
Expand Down
10 changes: 7 additions & 3 deletions tooling/noir_codegen/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ const codegenPrelude = `/* Autogenerated file, do not edit! */
/* eslint-disable */
import { Noir, InputMap, CompiledCircuit } from "@noir-lang/noir_js"
import { Noir, InputMap, CompiledCircuit, ForeignCallHandler } from "@noir-lang/noir_js"
export { ForeignCallHandler } from "@noir-lang/noir_js"
`;

const codegenFunction = (
Expand All @@ -22,10 +24,12 @@ const codegenFunction = (

return `export const ${name}_circuit: CompiledCircuit = ${JSON.stringify(compiled_program)};
export async function ${name}(${args_with_types}): Promise<${function_signature.returnValue}> {
export async function ${name}(${args_with_types}, foreignCallHandler?: ForeignCallHandler): Promise<${
function_signature.returnValue
}> {
const program = new Noir(${name}_circuit);
const args: InputMap = { ${args} };
const { returnValue } = await program.execute(args);
const { returnValue } = await program.execute(args, foreignCallHandler);
return returnValue as ${function_signature.returnValue};
}
`;
Expand Down
1 change: 1 addition & 0 deletions tooling/noir_codegen/test/assert_lt/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fn main(
assert(my_struct.foo.foo);
assert(string == "12345");

print(x);
assert(x < y);
(x + y, 3, my_struct.foo)
}
2 changes: 1 addition & 1 deletion tooling/noir_codegen/test/assert_lt/target/assert_lt.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"noir_version":"0.22.0+528d7c9fa244611cd54636493c730e6ce0734ece","hash":9387426530776910287,"abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},{"name":"array","type":{"kind":"array","length":5,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"my_struct","type":{"kind":"struct","path":"NestedStruct","fields":[{"name":"foo","type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}}},{"name":"baz","type":{"kind":"integer","sign":"unsigned","width":64}}]},"visibility":"private"},{"name":"string","type":{"kind":"string","length":5},"visibility":"private"}],"param_witnesses":{"array":[{"start":3,"end":8}],"my_struct":[{"start":8,"end":73}],"string":[{"start":73,"end":78}],"x":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"integer","sign":"unsigned","width":64},{"kind":"integer","sign":"unsigned","width":64},{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}]},"visibility":"public"},"return_witnesses":[80,81,82,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},"bytecode":"H4sIAAAAAAAA/82Y6W/TQBDFNy5HylGgXAEKmHKF2xvbic3VUM62OaDwCYkPSeMIJFAQiui/j59iw+YFIoFnJVaKnF+OyXhmN7vvvVNKfVCTUUofTnZtGuwQL6SPssF7iPcS7yPen3H+myqLj+EVG7ps/JYZ1/fqQZA0aon2dc+rxf0o9IKwX490pMMoHNQi30+iIGrE/bjhxTrwEz0MY3+YBS7L5ejldVikuhwgPkh8iPgw8RLxEeKjxMeIl4mPE58gPkl8ivi0xT5X0hgVC32uKPk+n6G6nCU+R7xCfJ74AvFFYpf4EvEq8WXiK8RXia8RX7fY52oao2qhz1Ul3+cbVJebxLeIbxPfIb5LfI/YI9bENWKfOCAOievEDYt9jtIYkYU+R0q+zzHV5T7xA+KHxI+IHxOvETeJnxCvEz8lfkb8nPgF8UviV2p6/9+g9zeJt4hbxG31ax7lw8Y5oCk0h2zmuSGQZzLEGFjNc1Msz52hzTy35PJMbObZkstzYDPPtlyeO9ANjpodjnDOJSW39p1/z0vzC7+5dbHYZl072bWrJlosnxf5Z6DX1tXsnCkZz/N9xZnzmdIf4iwar+XfXzLeL3rzM8Uwf1wqZicrpPSBpCOX488DSdeImY8F4XrYWlRFY70VrOe8+v1lnh7lqTuC99wV7GuB+s39g/uf1828PnvFxtQ68YoNLblOXiv5/x0zpq2+v5HL27eZ57Zg31tGjpif2LCxkcNIzc1TbLIwDGESwhiEGYhNFqYfjD6YezD0YOLBuINZB4MOphxMLphSMKJgPsFwgskEYwlmkqsmptGqmphDMIRgAsH4gdkD8wRmBwwOmBowMmBewLCASYEFhk0ZBgSKDqMB5gIMBZgIEOUQ0RDOEMsQyBDFEMJrWR0hcnG4gJiFgIVohVCFOIUghXCCKMGBH/Vqq+nDy3L2vEidML8x/7bV9OHlfXZdya698Tj58nXsjkdubzBwdz+NP7qj78m34efR7g+ltqXnYRcAAA=="}
{"noir_version":"0.22.0+6f69b3f511c8b4c51404ad4c18131bdf6b7f6a94","hash":3763979860977920209,"abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},{"name":"array","type":{"kind":"array","length":5,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"my_struct","type":{"kind":"struct","path":"NestedStruct","fields":[{"name":"foo","type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}}},{"name":"baz","type":{"kind":"integer","sign":"unsigned","width":64}}]},"visibility":"private"},{"name":"string","type":{"kind":"string","length":5},"visibility":"private"}],"param_witnesses":{"array":[{"start":3,"end":8}],"my_struct":[{"start":8,"end":73}],"string":[{"start":73,"end":78}],"x":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"integer","sign":"unsigned","width":64},{"kind":"integer","sign":"unsigned","width":64},{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}]},"visibility":"public"},"return_witnesses":[98,99,100,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},"bytecode":"H4sIAAAAAAAA/+1cC3PTRhBex8SJ40cezsNxaOtSoGnpQ7Jsy+6LkFJaSFIoKVCgQGzsTJlpCWU85Zf1/9Ur6drz9pAF3jtZM9FMRvliZff7bqXV6bTeYwD4E/wtNfyZCfY7Ep4hOD38mZfwGYJnCc4QPBdg4RMC+7hZk232vORLtutYzXq979b6tmN3rFq722pY9Ua32bJbdqPV6NVajtNv1Vtuu9t2rbZdd/r2caPtHAeG5/k4WmIcsmRcFgjOEZwnuEBwkeBFgpcIXiZ4heASwasErxG8TvCGxjiXhzbKGuJcBv44b5JxqRC8RfBZgt8h+F2C3yO4SvD7BJ8j+AOCzxN8geCLBH+oMc7bQxvbGuK8Dfxx/oiMy8cEXyL4E4I/Jfgzgj8n2CLYJrhGsENwneAGwU2CXY1xbg1ttDTEuQX8cW6TcfmC4C8J/orgrwn+huDLBO8QfIXgXYK/Jfgqwd8RfI3g7wn+AUbv/9fJ5zcI3iN4n+AD+O88EpuOecAO0zkk85whPCe1fZ3R1o9s4+fYaSkmOuPEx9m/PsV2E/x5qRwz3NLBPqNBCxA/dPyKir+xOtcRnJsa7N4C3otTh+5b/DHSmkhuMNr6iU2zUzOVSPg4jyaS23CaSFiCc1uD3UOY7kSCug/5Y6Q1kewx2vqZTbPjmEokfJxHE8kdOE0kLMG5o8HuXZjuRIK67/LHSAtXnDkdAv+j/D1IRgLdZ7T1C5tmp24qgfJxHk2g9+E0gbIE574Guw9guhMo6n7AHyMtXDHR3wP+BPoQkpFADxht/cqm2WmYSqB8nEcT6CM4TaAswXmkwe5jmO4Eirof88dIC1dM9A+BP4E+mXLdGJ8nihhNqttU4ksB/w3q72CPxRYzhH9GMVbWhJuGJGrJ3MV+VuJfDH5Pa9CSYbVZa6CWM6A+j2gs5BhlAs2M+my0Ocdr0xLFTnw23S7ayEpjIsZPcM9Jn89L45VlHq+U5FPYFTirzW8N6xi84qgw/QsKHgsG9S9o89vsCo1h+nMKHjmD+nPa/Dax3sIrfgvTn1fwyBvUn9fmt9lHG4Ux+gsKHgWD+gva/DaxTsm7x4XpLyp4FA3ql/lF5ZqNmSu/X6eDNhbH6F9U8Fg0qF/mF5VrNmau/H5drPfzioLD9C8peCwZ1C/zi8o1HzNXfr8u1m56Bdth+pcVPJYN6pf5ReWai5krv98m1sl6xfRh+lcUPFYM6pf5ReWaj5krv9+mlwNLY/SXFDxKBvXL/KJyLSSIay5BXPMxc+X363rz69Ux+lcVPFYN6pf5ReW6kiCuywniGve48vt1vTWmtTH61xQ81gzql/lF5ZqNmSu/39pTtLE+Rv+6gse6Qf0yv6hcszFz5ffrenPhjTH6NxQ8Ngzql/lF5ZpLENdCgriWYubK77eJ30H0vqwcpr+s4FE2qF/mF5VrNkFcizFz5ffr4PdzvS+Xh+nfVPDYNKh/U5tfx3tuqYzRX1HwqBjUX9Hm1+2hja0x+rcUPLYM6he+8L20eH//4uWz5wNKGre09LsodEhJx1xQHDsHGivI0vD/qhGZHJcfufJl0mqdmbfnZdM/KKSz2ZbH9SjY4+ujWSnw4hg8AXal41PSPiXFZBdGTxx6TOo1duTqCvH/iStNPAoGkrvs7YiP4789FDqSTbExly9pu6gmtdVnHM+w8XtDnhbhaR8xau4wxnWC8QtNcNN83YTF2Zps4yy7tDmvky7w5x3Zpq64P+Xj7ejk2WOM+77EEc9PvGGLElXR7w1vslieJsq1cFkCb7JYWoCvrHEJHJeWcQkAl1hx6Q6XhPCRGB9fcAqP01icUmKPLOyLhb2wsP9VFfw+V+fA72d1HvzZ4kXw+1Nhvyfsz4Q9mS6B33sJ+y1hjyXsq4QXGN6UcR0YBx2fLfDdID5j4RoWPsNjHRr2+sH+PtjTB/v4YO+ey8E4XgF/coH9d66C32fnGvj9dLCHDvZ6wTYNe+D3xDmA0cmLWFafZJzw/Mbzrwejk5fnwf5ssO8MBv0/Xgyqg5Nqp9ervno2+K168lf/5fHvJ6/+ASeieLQUUAAA"}
84 changes: 83 additions & 1 deletion tooling/noir_codegen/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import { assert_lt, MyStruct, u64 } from './codegen/index.js';
import { assert_lt, MyStruct, u64, ForeignCallHandler } from './codegen/index.js';

it('codegens a callable function', async () => {
const my_struct = { foo: true, bar: ['12345', '12345', '12345'] };
Expand All @@ -20,3 +20,85 @@ it('codegens a callable function', async () => {
expect(constant).to.be.eq('0x03');
expect(struct).to.be.deep.eq({ foo: true, bar: ['12345', '12345', '12345'] });
});

it('allows passing a custom foreign call handler', async () => {
let observedName = '';
let observedInputs: string[][] = [];
const foreignCallHandler: ForeignCallHandler = async (name: string, inputs: string[][]) => {
// Throwing inside the oracle callback causes a timeout so we log the observed values
// and defer the check against expected values until after the execution is complete.
observedName = name;
observedInputs = inputs;

return [];
};

const my_struct = { foo: true, bar: ['12345', '12345', '12345'] };

const [sum, constant, struct]: [u64, u64, MyStruct] = await assert_lt(
'2',
'3',
[0, 0, 0, 0, 0],
{
foo: my_struct,
bar: [my_struct, my_struct, my_struct],
baz: '64',
},
'12345',
foreignCallHandler,
);

expect(observedName).to.be.eq('print');
expect(observedInputs).to.be.deep.eq([
// add newline?
['0x0000000000000000000000000000000000000000000000000000000000000000'],
// x
['0x0000000000000000000000000000000000000000000000000000000000000002'],
// Type metadata
[
'0x000000000000000000000000000000000000000000000000000000000000007b',
'0x0000000000000000000000000000000000000000000000000000000000000022',
'0x000000000000000000000000000000000000000000000000000000000000006b',
'0x0000000000000000000000000000000000000000000000000000000000000069',
'0x000000000000000000000000000000000000000000000000000000000000006e',
'0x0000000000000000000000000000000000000000000000000000000000000064',
'0x0000000000000000000000000000000000000000000000000000000000000022',
'0x000000000000000000000000000000000000000000000000000000000000003a',
'0x0000000000000000000000000000000000000000000000000000000000000022',
'0x0000000000000000000000000000000000000000000000000000000000000075',
'0x000000000000000000000000000000000000000000000000000000000000006e',
'0x0000000000000000000000000000000000000000000000000000000000000073',
'0x0000000000000000000000000000000000000000000000000000000000000069',
'0x0000000000000000000000000000000000000000000000000000000000000067',
'0x000000000000000000000000000000000000000000000000000000000000006e',
'0x0000000000000000000000000000000000000000000000000000000000000065',
'0x0000000000000000000000000000000000000000000000000000000000000064',
'0x0000000000000000000000000000000000000000000000000000000000000069',
'0x000000000000000000000000000000000000000000000000000000000000006e',
'0x0000000000000000000000000000000000000000000000000000000000000074',
'0x0000000000000000000000000000000000000000000000000000000000000065',
'0x0000000000000000000000000000000000000000000000000000000000000067',
'0x0000000000000000000000000000000000000000000000000000000000000065',
'0x0000000000000000000000000000000000000000000000000000000000000072',
'0x0000000000000000000000000000000000000000000000000000000000000022',
'0x000000000000000000000000000000000000000000000000000000000000002c',
'0x0000000000000000000000000000000000000000000000000000000000000022',
'0x0000000000000000000000000000000000000000000000000000000000000077',
'0x0000000000000000000000000000000000000000000000000000000000000069',
'0x0000000000000000000000000000000000000000000000000000000000000064',
'0x0000000000000000000000000000000000000000000000000000000000000074',
'0x0000000000000000000000000000000000000000000000000000000000000068',
'0x0000000000000000000000000000000000000000000000000000000000000022',
'0x000000000000000000000000000000000000000000000000000000000000003a',
'0x0000000000000000000000000000000000000000000000000000000000000036',
'0x0000000000000000000000000000000000000000000000000000000000000034',
'0x000000000000000000000000000000000000000000000000000000000000007d',
],
// format string?
['0x0000000000000000000000000000000000000000000000000000000000000000'],
]);

expect(sum).to.be.eq('0x05');
expect(constant).to.be.eq('0x03');
expect(struct).to.be.deep.eq({ foo: true, bar: ['12345', '12345', '12345'] });
});

0 comments on commit e5e52a8

Please sign in to comment.