From cac043f77618427defb452efac44d30147747fbe Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Fri, 11 Aug 2023 15:02:37 +0000 Subject: [PATCH] feat: Add to other contracts --- .../acir-simulator/src/acvm/deserialize.ts | 31 +++---- .../acir-simulator/src/public/executor.ts | 4 - .../structs/public_circuit_public_inputs.ts | 1 - .../foundation/src/aztec-address/index.ts | 2 +- .../src/contracts/child_contract/src/main.nr | 21 +++-- .../src/main.nr | 12 ++- .../contracts/lending_contract/src/main.nr | 81 ++++++++++++------- .../src/contracts/parent_contract/src/main.nr | 28 +++++-- .../src/contracts/test_contract/src/main.nr | 15 ++-- .../src/sequencer/public_processor.test.ts | 3 +- 10 files changed, 125 insertions(+), 73 deletions(-) diff --git a/yarn-project/acir-simulator/src/acvm/deserialize.ts b/yarn-project/acir-simulator/src/acvm/deserialize.ts index 46002447603..cf2a7fa691c 100644 --- a/yarn-project/acir-simulator/src/acvm/deserialize.ts +++ b/yarn-project/acir-simulator/src/acvm/deserialize.ts @@ -17,14 +17,14 @@ import { RETURN_VALUES_LENGTH, } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { padArrayEnd } from '@aztec/foundation/collection'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr, Point } from '@aztec/foundation/fields'; +import { Tuple } from '@aztec/foundation/serialize'; import { getReturnWitness } from 'acvm_js'; import { ACVMField, ACVMWitness, fromACVMField } from './acvm.js'; -import { Tuple } from '@aztec/foundation/serialize'; -import { padArrayEnd } from '@aztec/foundation/collection'; // Utilities to read TS classes from ACVM Field arrays // In the order that the ACVM provides them @@ -110,7 +110,6 @@ export class PublicInputsReader { } return array as Tuple; } - } /** @@ -119,7 +118,10 @@ export class PublicInputsReader { * @param acir - The ACIR bytecode. * @returns The public inputs. */ -export function extractPrivateCircuitPublicInputs(partialWitness: ACVMWitness, acir: Buffer): PrivateCircuitPublicInputs { +export function extractPrivateCircuitPublicInputs( + partialWitness: ACVMWitness, + acir: Buffer, +): PrivateCircuitPublicInputs { const witnessReader = new PublicInputsReader(partialWitness, acir); const callContext = new CallContext( @@ -193,7 +195,6 @@ export function extractPrivateCircuitPublicInputs(partialWitness: ACVMWitness, a ); } - /** * Extracts the public circuit public inputs from the ACVM generated partial witness. * @param partialWitness - The partial witness. @@ -213,9 +214,11 @@ export function extractPublicCircuitPublicInputs(partialWitness: ACVMWitness, ac ); const argsHash = witnessReader.readField(); - const returnValues = padArrayEnd(witnessReader.readFieldArray(RETURN_VALUES_LENGTH),Fr.ZERO, RETURN_VALUES_LENGTH); ; + const returnValues = padArrayEnd(witnessReader.readFieldArray(RETURN_VALUES_LENGTH), Fr.ZERO, RETURN_VALUES_LENGTH); - const contractStorageUpdateRequests = new Array(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL).fill(ContractStorageUpdateRequest.empty()); + const contractStorageUpdateRequests = new Array(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL).fill( + ContractStorageUpdateRequest.empty(), + ); for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) { const request = new ContractStorageUpdateRequest( witnessReader.readField(), @@ -226,10 +229,7 @@ export function extractPublicCircuitPublicInputs(partialWitness: ACVMWitness, ac } const contractStorageReads = new Array(MAX_PUBLIC_DATA_READS_PER_CALL).fill(ContractStorageRead.empty()); for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) { - const request = new ContractStorageRead( - witnessReader.readField(), - witnessReader.readField(), - ); + const request = new ContractStorageRead(witnessReader.readField(), witnessReader.readField()); contractStorageReads[i] = request; } // const contractStorageRead = witnessReader.readFieldArray(MAX_PUBLIC_DATA_READS_PER_CALL); @@ -260,7 +260,10 @@ export function extractPublicCircuitPublicInputs(partialWitness: ACVMWitness, ac argsHash, returnValues, // TODO: how remove - contractStorageUpdateRequests as Tuple, + contractStorageUpdateRequests as Tuple< + ContractStorageUpdateRequest, + typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + >, contractStorageReads as Tuple, publicCallStack, newCommitments, @@ -269,6 +272,6 @@ export function extractPublicCircuitPublicInputs(partialWitness: ACVMWitness, ac unencryptedLogsHash, unencryptedLogPreimagesLength, historicPublicDataTreeRoot, - proverAddress + proverAddress, ); -} \ No newline at end of file +} diff --git a/yarn-project/acir-simulator/src/public/executor.ts b/yarn-project/acir-simulator/src/public/executor.ts index c2dbbb588f3..07f9a960214 100644 --- a/yarn-project/acir-simulator/src/public/executor.ts +++ b/yarn-project/acir-simulator/src/public/executor.ts @@ -16,7 +16,6 @@ import { acvm, convertACVMFieldToBuffer, extractPublicCircuitPublicInputs, - extractReturnWitness, frToAztecAddress, frToSelector, fromACVMField, @@ -30,7 +29,6 @@ import { PackedArgsCache } from '../packed_args_cache.js'; import { CommitmentsDB, PublicContractsDB, PublicStateDB } from './db.js'; import { PublicExecution, PublicExecutionResult } from './execution.js'; import { ContractStorageActionsCollector } from './state_actions.js'; -import { decodeReturnValues } from '@aztec/foundation/abi'; // Copied from crate::abi at noir-contracts/src/contracts/noir-aztec/src/abi.nr const NOIR_MAX_RETURN_VALUES = 4; @@ -163,9 +161,7 @@ export class PublicExecutor { }); // TODO: get the rest of everything from here, this should also be used to get the new Commitments, Nullifiers etc. - console.log("partial witness after execution: ", partialWitness); const publicInputs = extractPublicCircuitPublicInputs(partialWitness, acir); - console.log("decoded public inputs: ", publicInputs); const { returnValues } = publicInputs; const [contractStorageReads, contractStorageUpdateRequests] = storageActions.collect(); diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index 860d443fe08..9fbc10502a9 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -193,7 +193,6 @@ export class PublicCircuitPublicInputs { */ public proverAddress: AztecAddress, ) { - console.log(contractStorageUpdateRequests); assertMemberLength(this, 'returnValues', RETURN_VALUES_LENGTH); assertMemberLength(this, 'publicCallStack', MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL); assertMemberLength(this, 'newCommitments', MAX_NEW_COMMITMENTS_PER_CALL); diff --git a/yarn-project/foundation/src/aztec-address/index.ts b/yarn-project/foundation/src/aztec-address/index.ts index 7e46b96b18a..3910a5ab125 100644 --- a/yarn-project/foundation/src/aztec-address/index.ts +++ b/yarn-project/foundation/src/aztec-address/index.ts @@ -111,7 +111,7 @@ export class AztecAddress { * @param field - The Field element to convert. * @returns An Address Object from a Field element with the same value. */ - static fromField(field: Fr) : AztecAddress { + static fromField(field: Fr): AztecAddress { return new AztecAddress(toBufferBE(field.value, AztecAddress.SIZE_IN_BYTES)); } diff --git a/yarn-project/noir-contracts/src/contracts/child_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/child_contract/src/main.nr index 39e4714216e..5f70919a91a 100644 --- a/yarn-project/noir-contracts/src/contracts/child_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/child_contract/src/main.nr @@ -32,13 +32,20 @@ contract Child { } // Returns base_value + 42. - open fn pubValue(inputs: PublicContextInputs, base_value: Field) -> pub Field { - base_value + inputs.public_global_variables.chain_id + inputs.public_global_variables.version + inputs.public_global_variables.block_number + inputs.public_global_variables.timestamp + open fn pubValue(inputs: PublicContextInputs, base_value: Field) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([base_value])); + + // TODO: make these available on context + let returnValue = base_value + inputs.public_global_variables.chain_id + inputs.public_global_variables.version + inputs.public_global_variables.block_number + inputs.public_global_variables.timestamp; + + context.return_values.push(returnValue); + // TODO(MADDIAA): MAYBE we put the return values inside the finish object? That could have nice UX + context.finish() } // Increments `current_value` by `new_value` and returns `new_value` + 1. - open fn pubStoreValue(inputs: PublicContextInputs, new_value: Field) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([new_value])); + open fn pubStoreValue(inputs: PublicContextInputs, new_value: Field) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([new_value])); let storage = Storage::init(); let old_value = storage.current_value.read(); @@ -47,7 +54,9 @@ contract Child { // Compiler fails with "we do not allow private ABI inputs to be returned as public outputs" if we try to // return new_value as-is, but then it also complains if we add `pub` to `new_value` in the args, so we // just assign it to another variable and tweak it so it's not the same value, and the compiler is happy. - let ret_value = new_value + 1; - ret_value + let return_value = new_value + 1; + + context.return_values.push(return_value); + context.finish() } } diff --git a/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr index 9374b7f8e5f..0ec68fbb492 100644 --- a/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr @@ -33,23 +33,27 @@ contract ExamplePublicStateIncrement { // a = 100; open internal fn initialise_a( inputs: PublicContextInputs, - ) { - let mut _context = PublicContext::new(inputs, abi::hash_args([])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([])); let storage = Storage::init(); storage.a.write(100); + + context.finish() } // a += b; open fn increment_a( inputs: PublicContextInputs, b: Field, - ) { - let mut _context = PublicContext::new(inputs, abi::hash_args([b])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([b])); let storage = Storage::init(); let mut a = storage.a.read(); a += b; storage.a.write(a); + + context.finish() } } diff --git a/yarn-project/noir-contracts/src/contracts/lending_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/lending_contract/src/main.nr index 4ecebd742a0..4bbd19c7f63 100644 --- a/yarn-project/noir-contracts/src/contracts/lending_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/lending_contract/src/main.nr @@ -31,8 +31,8 @@ contract Lending { open fn init( inputs: PublicContextInputs - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([])); let storage = Storage::init(); @@ -48,15 +48,16 @@ contract Lending { last_updated_ts: inputs.public_global_variables.timestamp as u120, }); - 1 + context.return_values.push(1); + context.finish() } // Create a position. open fn update_tot( inputs: PublicContextInputs - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([])); let storage = Storage::init(); let asset = storage.assets.at(0); @@ -77,7 +78,8 @@ contract Lending { asset.write(tot); - 1 + context.return_values.push(1); + context.finish() } // This don't need to be on behalf of self. We should be able to repay on behalf of someone else. @@ -117,19 +119,22 @@ contract Lending { inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); // @todo @LHerskind Transfer tokens into this contract. We can't do it now because too few writes. - call_public_function(inputs.call_context.storage_contract_address, 3009041984, [owner, amount])[0] + let return_values = call_public_function(inputs.call_context.storage_contract_address, 3009041984, [owner, amount]); + + context.return_values.push(return_values[0]); + context.finish() } open internal fn _deposit( inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); let _void = call_public_function_no_args(inputs.call_context.storage_contract_address, 1259373467)[0]; @@ -139,7 +144,9 @@ contract Lending { let collateral = coll_loc.read(); coll_loc.write(collateral + amount); - 1 + + context.return_values.push(1); + context.finish() } fn withdraw_private( @@ -167,12 +174,15 @@ contract Lending { open fn withdraw_public( inputs: PublicContextInputs, amount: Field - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { // TODO(MADDIAA): GET ALL OF THE STUFF FROM CONTEXT IN THIS FILE!!!!! -> ADD TO THE PUBLIC CONTEXT - let mut _context = PublicContext::new(inputs, abi::hash_args([amount])); + let mut context = PublicContext::new(inputs, abi::hash_args([amount])); // @todo @LHerskind Transfer tokens into this contract. We can't do it now because too few writes. - call_public_function(inputs.call_context.storage_contract_address, 1065861440, [inputs.call_context.msg_sender, amount])[0] + let return_values = call_public_function(inputs.call_context.storage_contract_address, 1065861440, [inputs.call_context.msg_sender, amount]); + + context.return_values.push(return_values[0]); + context.finish() } open internal fn _withdraw( @@ -180,9 +190,9 @@ contract Lending { owner: Field, // recipient: Field, amount: Field - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { // Access control. - let mut _context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); let _void = call_public_function_no_args(inputs.call_context.storage_contract_address, 1259373467)[0]; @@ -200,7 +210,8 @@ contract Lending { coll_loc.write(collateral - amount); // Transfer tokens to recipient (could be with shielding or without, for now, can't to either). - 1 + context.return_values.push(1); + context.finish() } fn borrow_private( @@ -228,17 +239,20 @@ contract Lending { open fn borrow_public( inputs: PublicContextInputs, amount: Field - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([amount])); - call_public_function(inputs.call_context.storage_contract_address, 1462609836, [inputs.call_context.msg_sender, amount])[0] + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount])); + let return_values = call_public_function(inputs.call_context.storage_contract_address, 1462609836, [inputs.call_context.msg_sender, amount]); + + context.return_values.push(return_values[0]); + context.finish() } open internal fn _borrow( inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); // Access control. let _void = call_public_function_no_args(inputs.call_context.storage_contract_address, 1259373467)[0]; @@ -256,7 +270,9 @@ contract Lending { // @todo @LHerskind Transferring funds to the recipient. - 1 + // TODO*MD: should internal functions like this return a the context or should they just return vals - will this be inlined? + context.return_values.push(1); + context.finish() } // This don't need to be on behalf of self. We should be able to repay on behalf of someone else. @@ -295,18 +311,21 @@ contract Lending { inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); // @todo @LHerskind Transfer tokens from msg.sender to this contract. - call_public_function(inputs.call_context.storage_contract_address, 3985016136, [owner, amount])[0] + let return_values = call_public_function(inputs.call_context.storage_contract_address, 3985016136, [owner, amount]); + + context.return_values.push(return_values[0]); + context.finish() } open internal fn _repay( inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); let _void = call_public_function_no_args(inputs.call_context.storage_contract_address, 1259373467)[0]; let storage = Storage::init(); @@ -322,7 +341,9 @@ contract Lending { assert (static_debt as u120 >= amount as u120); debt_loc.write(static_debt - amount); - 1 + + context.return_values.push(1); + context.finish() } unconstrained fn getTot( diff --git a/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr index 93491d95512..ec2a54fc506 100644 --- a/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr @@ -38,18 +38,34 @@ contract Parent { } // Public function to directly call another public function to the targetContract using the selector and value provided - open fn pubEntryPoint(inputs: PublicContextInputs, targetContract: Field, targetSelector: Field, initValue: Field) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([targetContract, targetSelector, initValue])); + open fn pubEntryPoint( + inputs: PublicContextInputs, + targetContract: Field, + targetSelector: Field, + initValue: Field + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([targetContract, targetSelector, initValue])); - call_public_function(targetContract, targetSelector, [initValue])[0] + let return_values = call_public_function(targetContract, targetSelector, [initValue]); + + context.return_values.push(return_values[0]); + context.finish() } // Same as pubEntryPoint, but calls the target contract twice, using the return value from the first invocation as the argument for the second. - open fn pubEntryPointTwice(inputs: PublicContextInputs, targetContract: Field, targetSelector: Field, initValue: Field) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([targetContract, targetSelector, initValue])); + open fn pubEntryPointTwice( + inputs: PublicContextInputs, + targetContract: Field, + targetSelector: Field, + initValue: Field + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([targetContract, targetSelector, initValue])); let returnValue = call_public_function(targetContract, targetSelector, [initValue])[0]; - call_public_function(targetContract, targetSelector, [returnValue])[0] + let return_values = call_public_function(targetContract, targetSelector, [returnValue]); + + context.return_values.push(return_values[0]); + context.finish() } // Private function to enqueue a call to the targetContract address using the selector and argument provided diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr index e0e230bb5e1..90b9d250586 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr @@ -72,13 +72,15 @@ contract Test { inputs: PublicContextInputs, amount: Field, secretHash: Field, - ) { - let mut _context = PublicContext::new(inputs, abi::hash_args([amount, secretHash])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, secretHash])); // Create a commitment to the amount let note = DummyNote::new(amount, secretHash); // Public oracle call to emit new commitment. create_l2_to_l1_message(note.get_commitment()); + + context.finish() } // Purely exists for testing @@ -86,15 +88,18 @@ contract Test { inputs: PublicContextInputs, amount: Field, secretHash: Field, - ) -> pub Field { - let mut _context = PublicContext::new(inputs, abi::hash_args([amount, secretHash])); + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, secretHash])); // Create a commitment to the amount let note = DummyNote::new(amount, secretHash); // Public oracle call to emit new commitment. create_nullifier(note.get_commitment()); - 0 + + // TODO(MD): may not need this return value? + context.return_values.push(0); + context.finish() } struct DummyNote { diff --git a/yarn-project/sequencer-client/src/sequencer/public_processor.test.ts b/yarn-project/sequencer-client/src/sequencer/public_processor.test.ts index 3a146575cc9..2262f57cbfc 100644 --- a/yarn-project/sequencer-client/src/sequencer/public_processor.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/public_processor.test.ts @@ -203,8 +203,7 @@ describe('public_processor', () => { expect(publicExecutor.execute).toHaveBeenCalledTimes(1); }); }); - }); - +}); function makePublicExecutionResultFromRequest(item: PublicCallRequest): PublicExecutionResult { return {