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

feat(noir): separate arguments of inputs #456

Merged
merged 4 commits into from
May 5, 2023
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
21 changes: 21 additions & 0 deletions yarn-project/acir-simulator/src/abi_coder/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,23 @@
import { ABIType } from '@aztec/noir-contracts';

export * from './encoder.js';
export * from './decoder.js';

export function sizeOfType(type: ABIType): number {
switch (type.kind) {
case 'field':
case 'boolean':
case 'integer':
return 1;
case 'string':
return type.length;
case 'array':
return type.length * sizeOfType(type.type);
case 'struct':
return type.fields.reduce((sum, field) => sum + sizeOfType(field.type), 0);
default: {
const exhaustiveCheck: never = type;
throw new Error(`Unhandled abi type: ${exhaustiveCheck}`);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ describe('Private Execution test suite', () => {
);
const result = await acirSimulator.run(txRequest, abi, AztecAddress.ZERO, EthAddress.ZERO, historicRoots);

expect(result.returnValues[0]).toEqual(142n);
expect(result.callStackItem.publicInputs.returnValues[0]).toEqual(new Fr(142n));
});

it('parent should call child', async () => {
Expand Down Expand Up @@ -327,11 +327,11 @@ describe('Private Execution test suite', () => {
historicRoots,
);

expect(result.returnValues[0]).toEqual(42n);
expect(result.callStackItem.publicInputs.returnValues[0]).toEqual(new Fr(42n));
expect(oracle.getFunctionABI.mock.calls[0]).toEqual([childAddress, childSelector]);
expect(oracle.getPortalContractAddress.mock.calls[0]).toEqual([childAddress]);
expect(result.nestedExecutions).toHaveLength(1);
expect(result.nestedExecutions[0].returnValues[0]).toEqual(42n);
expect(result.nestedExecutions[0].callStackItem.publicInputs.returnValues[0]).toEqual(new Fr(42n));
});
});
});
6 changes: 4 additions & 2 deletions yarn-project/acir-simulator/src/client/private_execution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ClientTxExecutionContext } from './client_execution_context.js';
import { Fr } from '@aztec/foundation/fields';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { sizeOfType } from '../index.js';

export interface NewNoteData {
preimage: Fr[];
Expand Down Expand Up @@ -73,6 +74,7 @@ export class PrivateFunctionExecution {

const acir = Buffer.from(this.abi.bytecode, 'hex');
const initialWitness = this.writeInputs();

const newNotePreimages: NewNoteData[] = [];
const newNullifiers: NewNullifierData[] = [];
const nestedExecutionContexts: ExecutionResult[] = [];
Expand Down Expand Up @@ -142,9 +144,8 @@ export class PrivateFunctionExecution {
// We still need this function until we can get user-defined ordering of structs for fn arguments
// TODO When that is sorted out on noir side, we can use instead the utilities in serialize.ts
private writeInputs() {
const argsSize = this.abi.parameters.reduce((acc, param) => acc + sizeOfType(param.type), 0);
const fields = [
...this.args,

this.callContext.isContractDeployment,
this.callContext.isDelegateCall,
this.callContext.isStaticCall,
Expand All @@ -160,6 +161,7 @@ export class PrivateFunctionExecution {
this.context.historicRoots.contractTreeRoot,
this.context.historicRoots.nullifierTreeRoot,
this.context.historicRoots.privateDataTreeRoot,
...this.args.slice(0, argsSize),
];

return toACVMWitness(1, fields);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,20 @@ contract Child {
use dep::aztec3::abi::Inputs;
use dep::aztec3::context::PrivateFunctionContext;

/// ABI constructor type "secret"
/// ABI constructor params []
/// ABI constructor return []
fn constructor(
inputs: pub Inputs,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
PrivateFunctionContext::new().finish(inputs)
}

/// ABI value type "secret"
/// ABI value params [{"name":"input","type":{"kind":"field"},"visibility":"public"}]
/// ABI value return [{"kind":"field"}]
Copy link
Collaborator

@spalladino spalladino May 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we keep the return annotation at least? Can the client consume this value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users currently cannot consume the return value for secret functions! The idea is to phase out the ABI manual comments for the introduction of the aztec noir compiler 😄

fn value(
inputs: pub Inputs,
input: pub Field,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
let mut context = PrivateFunctionContext::new();
context.args = context.args.push(input);

context.return_values = context.return_values.push(inputs.args[0] + 42);
context.return_values = context.return_values.push(input + 42);

context.finish(inputs)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ struct Inputs {
old_contract_tree_root : Field,

contract_deployment_data: ContractDeploymentData,
args: [Field; MAX_ARGS],
}

struct CallContext {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::abi;

// When finished, one can call .finish() to convert back to the abi
struct PrivateFunctionContext {
args : BoundedVec<Field, abi::MAX_ARGS>,
return_values : BoundedVec<Field, abi::MAX_RETURN_VALUES>,
logs : BoundedVec<Field, abi::MAX_LOGS>,

Expand All @@ -17,6 +18,7 @@ struct PrivateFunctionContext {
impl PrivateFunctionContext {
fn new() -> PrivateFunctionContext {
PrivateFunctionContext {
args: BoundedVec::new(0),
return_values: BoundedVec::new(0),
logs: BoundedVec::new(0),

Expand All @@ -33,7 +35,7 @@ impl PrivateFunctionContext {
fn finish(self, inputs: abi::Inputs) -> [Field; abi::PUBLIC_INPUTS_LENGTH] {
let priv_circuit_pub_inputs = abi::PrivateCircuitPublicInputs {
call_context: inputs.call_context,
args: inputs.args,
args: self.args.storage,
return_values: self.return_values.storage,
emitted_events: self.logs.storage,
new_commitments: self.new_commitments.storage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,19 @@ contract Parent {
use dep::aztec3::context::PrivateFunctionContext;
use dep::aztec3::private_call_stack_item::PrivateCallStackItem;

/// ABI constructor type "secret"
/// ABI constructor params []
/// ABI constructor return []
fn constructor(
inputs: pub Inputs,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
PrivateFunctionContext::new().finish(inputs)
}

/// ABI entryPoint type "secret"
/// ABI entryPoint params [{"name":"targetContract","type":{"kind":"field"},"visibility":"public"},{"name":"targetSelector","type":{"kind":"field"}}]
/// ABI entryPoint return [{"kind":"field"}]
fn entryPoint(
inputs: pub Inputs,
targetContract: pub Field,
targetSelector: pub Field,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
let targetContract = inputs.args[0];
let targetSelector = inputs.args[1];

let mut initialContext = PrivateFunctionContext::new();
initialContext.args = initialContext.args.push_array([targetContract, targetSelector]);

let (callStackItem, mut context) = PrivateCallStackItem::call(targetContract, targetSelector, [0; dep::aztec3::abi::MAX_ARGS], initialContext);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,25 @@ contract PublicToken {

global balances = StorageMap { storage_slot: 1 };

/// ABI constructor type "secret"
/// ABI constructor params []
/// ABI constructor return []
fn constructor(
inputs: pub Inputs,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
PrivateFunctionContext::new().finish(inputs)
}

/// ABI mint type "open"
/// ABI mint params [{"name":"amount","type":{"kind":"field"},"visibility":"public"},{"name":"recipient","type":{"kind":"struct","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"visibility":"public"}}]
fn mint(
_call_context: pub CallContext,
amount: pub Field,
recipient: pub Point,
open fn mint(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoa!

_call_context: CallContext,
amount: Field,
recipient: Point,
) -> pub Field {
let recipient_balance = balances.at(recipient.x);
recipient_balance.write(recipient_balance.read() + amount)
}

/// ABI transfer type "open"
/// ABI transfer params [{"name":"amount","type":{"kind":"field"},"visibility":"public"},{"name":"recipient","type":{"kind":"struct","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"visibility":"public"}}]
fn transfer(
call_context: pub CallContext,
amount: pub Field,
recipient: pub Point,
open fn transfer(
call_context: CallContext,
amount: Field,
recipient: Point,
) -> pub Field {
let sender = call_context.msg_sender;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,9 @@ contract Test {
use dep::aztec3::abi::Inputs;
use dep::aztec3::context::PrivateFunctionContext;

/// ABI constructor type "secret"
/// ABI constructor params []
/// ABI constructor return []
fn constructor(
inputs: pub Inputs,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
for i in 0..abi::MAX_ARGS {
constrain inputs.args[i] == 0;
}

let mut context = PrivateFunctionContext::new();

context.finish(inputs)
PrivateFunctionContext::new().finish(inputs)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,16 @@ contract ZkToken {
// `balances: Mapping<Field, Set<Note>>;`
//*********************************/

/// ABI constructor type "secret"
/// ABI constructor params [{"name":"value","type":{"kind":"field"},"visibility":"public"},{"name":"owner","type":{"kind":"struct","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]},"visibility":"public"}]
/// ABI constructor return []
fn constructor(
//*********************************/
// Should eventually be hidden:
inputs: pub Inputs,
//*********************************/

// initial_supply: pub Field,
// owner: pub Point,
initial_supply: pub Field,
owner: pub Point,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
//*********************************/
// Should eventually be hidden:
let initial_supply = inputs.args[0];
let owner = Point::new(inputs.args[1], inputs.args[2]);

let mut context = PrivateFunctionContext::new();
//*********************************/
context.args = context.args.push_array([initial_supply, owner.x, owner.y]);

let owner_balance = balances.at(owner.x);
let note = Note::new(initial_supply, owner);
Expand All @@ -40,25 +31,16 @@ contract ZkToken {
.finish(inputs)
}

/// ABI mint type "secret"
/// ABI mint params [{"name":"value","type":{"kind":"field"},"visibility":"public"},{"name":"owner","type":{"kind":"struct","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]},"visibility":"public"}]
/// ABI mint return []
fn mint(
//*********************************/
// Should eventually be hidden:
inputs: pub Inputs,
//*********************************/

// amount: pub Field,
// owner: pub Point,
amount: pub Field,
owner: pub Point,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
//*********************************/
// Should eventually be hidden:
let amount = inputs.args[0];
let owner = Point::new(inputs.args[1], inputs.args[2]);

let mut context = PrivateFunctionContext::new();
//*********************************/
context.args = context.args.push_array([amount, owner.x, owner.y]);

let owner_balance = balances.at(owner.x);
let note = Note::new(amount, owner);
Expand All @@ -67,30 +49,20 @@ contract ZkToken {
.finish(inputs)
}

/// ABI transfer type "secret"
/// ABI transfer params [{"name":"amount","type":{"kind":"field"},"visibility":"public"},{"name":"sender","type":{"kind":"struct","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"visibility":"public"}},{"name":"recipient","type":{"kind":"struct","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"visibility":"public"}}]
/// ABI transfer return []
fn transfer(
//*********************************/
// Should eventually be hidden:
inputs: pub Inputs,
//*********************************/
//
// amount: pub Field,
// sender: pub Point,
// recipient: pub Point
amount: pub Field,
sender: pub Point,
recipient: pub Point,
) -> pub [Field; dep::aztec3::abi::PUBLIC_INPUTS_LENGTH] {
//*********************************/
// Should eventually be hidden:
let amount = inputs.args[0];
let sender = Point::new(inputs.args[1], inputs.args[2]);
let recipient = Point::new(inputs.args[3], inputs.args[4]);

let context1 = PrivateFunctionContext::new();
//*********************************/
let mut initialContext = PrivateFunctionContext::new();
initialContext.args = initialContext.args.push_array([amount, sender.x, sender.y, recipient.x, recipient.y]);

let sender_balance = balances.at(sender.x);
let (mut context, (note1, note2)) = sender_balance.get_2(inputs, context1);
let (mut context, (note1, note2)) = sender_balance.get_2(inputs, initialContext);

// TODO: Removing this return breaks the circuit (???)
context.return_values = context.return_values.push(note1.is_real as Field);
Expand Down
Loading