-
Notifications
You must be signed in to change notification settings - Fork 288
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(aztec-noir): align public and private execution patterns #1515
Conversation
Tagging @sirasistant, as this touches on some design decisions you've made in the past. |
let returnValue = base_value + context.chain_id() + context.version() + context.block_number() + context.timestamp(); | ||
|
||
context.return_values.push(returnValue); | ||
// TODO(MADDIAA): MAYBE we put the return values inside the finish object? That could have nice UX |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think return_values are part of the PublicCircuitPublicInputs, although I think there are plans to instead return a return_values_hash
. When that change happens, the simulator will keep track of the return_values
, and the simulator could return those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah but it's true that even if we do return_values_hash we don't need to keep them inside the context, they can instead be passed as arguments to finish() both in public and private, and when we have return_values_hash then finish(hash_returns(whatever))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job. Got some minor comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come the ordering change in here? Was there a mismatch or was this to follow the structure of historic_block_data
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ive made a followup pr that does some reorg to prevent structuring mistakes like this: #1567.
It can be merged into this one or run as a standalone pr. It was a big change so Ive broken it up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the cpp using a different formatter? Some of these files have different formats without other stuff changing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, i think these changes came from adams commits where he was using clion as his ide
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the tidy
not have been angry about it? 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good question, im i suppose it exists within both rulesets
@@ -62,7 +62,7 @@ KernelCircuitPublicInputs<NT> native_public_kernel_circuit_private_previous_kern | |||
// validate the kernel execution common to all invocation circumstances | |||
common_validate_kernel_execution(builder, public_kernel_inputs); | |||
|
|||
// vallidate our public call hash | |||
// valLidate our public call hash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// valLidate our public call hash | |
// validate our public call hash |
); | ||
|
||
const argsHash = witnessReader.readField(); | ||
const returnValues = padArrayEnd(witnessReader.readFieldArray(RETURN_VALUES_LENGTH), Fr.ZERO, RETURN_VALUES_LENGTH); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to pad it when reading array of length RETURN_VALUES_LENGTH
? Won't you be filling RETURN_VALUES_LENGTH - RETURN_VALUES_LENGTH = 0
elements with Fr.ZERO
values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is there as a sanity check, i can remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just seemed strange when no others had it.
@@ -160,7 +160,8 @@ export class PublicExecutor { | |||
}, | |||
}); | |||
|
|||
const returnValues = extractReturnWitness(acir, partialWitness).map(fromACVMField); | |||
const publicInputs = extractPublicCircuitPublicInputs(partialWitness, acir); | |||
const { returnValues } = publicInputs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason you are not doing? Don't seems like you are using the publicInputs
const { returnValues } = extractPublicCircuitPublicInputs(partialWitness, acir);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of the public inputs is dependant on some ongoing discussions around how we will handle context in the vm setting. I am unsure if we will use the publicInputs further. When i started the work I was under the impression that I was going to. I will update
@@ -261,6 +261,10 @@ impl ContractStorageRead { | |||
fn hash(self) -> Field { | |||
dep::std::hash::pedersen_with_separator(self.serialize(), GENERATOR_INDEX__PUBLIC_DATA_READ)[0] | |||
} | |||
|
|||
fn empty() -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need empty_contract_storage_read()
if we have empty here, seems like we should use the empty
instead for clarity.
In call_public_function_with_packed_args
in the context
we populate contract_storage_read
with the empty ones.
] | ||
} | ||
} | ||
|
||
fn empty_block_data() -> HistoricBlockData { | ||
HistoricBlockData{ private_data_tree_root: 0, nullifier_tree_root: 0, contract_tree_root: 0, l1_to_l2_messages_tree_root: 0, blocks_tree_root: 0, prev_global_variables_hash: 0, public_data_tree_root: 0 } | ||
HistoricBlockData{ private_data_tree_root: 0, nullifier_tree_root: 0, contract_tree_root: 0, l1_to_l2_messages_tree_root: 0, blocks_tree_root: 0, public_data_tree_root: 0, global_variables_hash: 0 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should replace this with an HistoricBlockData::empty()
instead? Seems better for consistency. Only used in context.call_public_function_with_packed_args
.
|
||
fn empty() -> Self { | ||
Self { storage_slot: 0, old_value: 0, new_value: 0 } | ||
} | ||
} | ||
|
||
fn empty_contract_storage_update_request() -> ContractStorageUpdateRequest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My brain want us to use ContractStorageUpdateRequest::empty()
where this was used and get rid of this one.
prover_address: Field, | ||
|
||
|
||
// TODO: include globals in here and check them elsewhere |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will you do this as part of this pr or create an issue for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets create an issue, it is out of scope
edit: #1567
@@ -211,7 +214,7 @@ export class PublicProcessor { | |||
const unencryptedLogsHash = to2Fields(result.unencryptedLogs.hash()); | |||
const unencryptedLogPreimagesLength = new Fr(result.unencryptedLogs.getSerializedLength()); | |||
|
|||
return PublicCircuitPublicInputs.from({ | |||
const pub = PublicCircuitPublicInputs.from({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like you printed pub
for debugging, but as not done anymore, you might as well return it directly here 👍.
open fn mint( | ||
_inputs: PublicContextInputs, | ||
inputs: PublicContextInputs, | ||
amount: Field, | ||
recipient: Field, | ||
) -> pub Field { | ||
) -> pub abi::PublicCircuitPublicInputs { | ||
let mut context = PublicContext::new(inputs, abi::hash_args([amount, recipient])); | ||
|
||
let storage = Storage::init(); | ||
let recipient_balance = storage.balances.at(recipient); | ||
let new_amount = recipient_balance.read() + amount; | ||
// TODO: Remove return value. | ||
let _hash = emit_unencrypted_log("Coins minted"); | ||
recipient_balance.write(new_amount); | ||
new_amount | ||
|
||
context.return_values.push(new_amount); | ||
|
||
context.finish() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Highlighting this diff, so I can link to it elsewhere, for a discussion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
…ts (#1571) Add a bit more consistency across the code base, I came into these issues when working on #1515. Running this in a separate pr as it is not directly related. And to minimise the diff between the two ## Overview Replaces 6 seperate roots with one single data structure that is used literally everywhere else
Metadata
fixes
Relevant discussions
PrivateContextInputs
as a required parameter to a private noir contract function #1358 (comment)Overview
This PR aims to align the implementations of Public and Private state.
Other work I am thinking of completing within this PR
Right now,
PublicCircuitPublicInputs
(The object which is fed to the public kernel after circuit completion) is not created within the application circuit. It is created within the sequencer. If we zoom out, this is not a direct security concern as execution is occuring within the sequencer, however it does break away from the pattern seen withinPrivateExecution
where the result of each execution is thePrivateCircuitPublicInputs
object.We could leave this as is, (alot of this code will be dumped when the vm arrives). However similar code paths will make building the library easier. For example, for some library methods we have two implementations, one for public and one for private. More and more standardisation would allow these methods to take in a generic context and utilise the same code paths. (A goal I think is worth pursuing).
Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge.