Skip to content

Commit

Permalink
Merge e800e35 into 5d669b9
Browse files Browse the repository at this point in the history
  • Loading branch information
nventuro authored Mar 22, 2024
2 parents 5d669b9 + e800e35 commit e20278d
Show file tree
Hide file tree
Showing 55 changed files with 783 additions and 58 deletions.
12 changes: 12 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,18 @@ jobs:
aztec_manifest_key: end-to-end
<<: *defaults_e2e_test

e2e-max-block-number:
docker:
- image: aztecprotocol/alpine-build-image
resource_class: small
steps:
- *checkout
- *setup_env
- run:
name: "Test"
command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=e2e_max_block_number.test.ts
aztec_manifest_key: end-to-end

e2e-multiple-accounts-1-enc-key:
steps:
- *checkout
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Function Context
## title: Function Context
---

# The Function Context
Expand Down Expand Up @@ -94,6 +94,14 @@ The return values are a set of values that are returned from an applications exe

return_values : BoundedVec<Field, RETURN_VALUES_LENGTH>,

## Max Block Number

Some data structures impose time constraints, e.g. they may make it so that a value can only be changed after a certain delay. Interacting with these in private involves creating proofs that are only valid as long as they are included before a certain future point in time. To achieve this, the `request_max_block_number` function can be used to set this property:

#include_code max-block-number /noir-projects/aztec-nr/aztec/src/context/private_context.nr rust

A transaction that requests a maximum block number will never be included in a block with a block number larger than the requested value, since it would be considered invalid. This can also be used to make transactions automatically expire after some time if not included.

### Read Requests

<!-- TODO(maddiaa): leaving as todo until their is further clarification around their implementation in the protocol -->
Expand Down
5 changes: 3 additions & 2 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,12 @@ library Constants {
uint256 internal constant HEADER_LENGTH = 20;
uint256 internal constant L1_TO_L2_MESSAGE_LENGTH = 6;
uint256 internal constant L2_TO_L1_MESSAGE_LENGTH = 2;
uint256 internal constant MAX_BLOCK_NUMBER_LENGTH = 2;
uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4;
uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5;
uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6;
uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 208;
uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 205;
uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 210;
uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 207;
uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 198;
uint256 internal constant STATE_REFERENCE_LENGTH = 8;
uint256 internal constant TX_CONTEXT_DATA_LENGTH = 4;
Expand Down
12 changes: 11 additions & 1 deletion noir-projects/aztec-nr/aztec/src/context/private_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
use dep::protocol_types::{
abis::{
call_context::CallContext, function_data::FunctionData, function_selector::FunctionSelector,
nullifier_key_validation_request::NullifierKeyValidationRequest,
max_block_number::MaxBlockNumber, nullifier_key_validation_request::NullifierKeyValidationRequest,
private_call_stack_item::PrivateCallStackItem,
private_circuit_public_inputs::PrivateCircuitPublicInputs,
public_call_stack_item::PublicCallStackItem,
Expand Down Expand Up @@ -46,6 +46,8 @@ struct PrivateContext {
args_hash : Field,
return_values : BoundedVec<Field, RETURN_VALUES_LENGTH>,

max_block_number: MaxBlockNumber,

note_hash_read_requests: BoundedVec<SideEffect, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL>,
nullifier_read_requests: BoundedVec<ReadRequest, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,
nullifier_key_validation_requests: BoundedVec<NullifierKeyValidationRequest, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL>,
Expand Down Expand Up @@ -129,6 +131,7 @@ impl PrivateContext {
min_revertible_side_effect_counter,
args_hash,
return_values: BoundedVec::new(),
max_block_number: MaxBlockNumber::default(),
note_hash_read_requests: BoundedVec::new(),
nullifier_read_requests: BoundedVec::new(),
nullifier_key_validation_requests: BoundedVec::new(),
Expand Down Expand Up @@ -163,6 +166,7 @@ impl PrivateContext {
args_hash: self.args_hash,
return_values: self.return_values.storage,
min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,
max_block_number: self.max_block_number,
note_hash_read_requests: self.note_hash_read_requests.storage,
nullifier_read_requests: self.nullifier_read_requests.storage,
nullifier_key_validation_requests: self.nullifier_key_validation_requests.storage,
Expand All @@ -188,6 +192,12 @@ impl PrivateContext {
self.min_revertible_side_effect_counter = self.side_effect_counter;
}

// docs:start:max-block-number
pub fn request_max_block_number(&mut self, max_block_number: u32) {
// docs:end:max-block-number
self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);
}

pub fn push_note_hash_read_request(&mut self, note_hash: Field) {
let side_effect = SideEffect { value: note_hash, counter: self.side_effect_counter };
self.note_hash_read_requests.push(side_effect);
Expand Down
23 changes: 21 additions & 2 deletions noir-projects/noir-contracts/contracts/test_contract/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// A contract used for testing a random hodgepodge of small features from simulator and end-to-end tests.
contract Test {
use dep::aztec::prelude::{
AztecAddress, EthAddress, NoteHeader, NoteGetterOptions, NoteViewerOptions, PrivateContext,
PrivateImmutable, PrivateSet
AztecAddress, EthAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions,
PrivateContext, PrivateImmutable, PrivateSet
};

use dep::aztec::protocol_types::{
Expand Down Expand Up @@ -63,6 +63,25 @@ contract Test {
context.this_address()
}

#[aztec(private)]
fn request_max_block_number(max_block_number: u32, enqueue_public_call: bool) {
// docs:start:request-max-block-number
context.request_max_block_number(max_block_number);
// docs:end:request-max-block-number

if enqueue_public_call {
let _ = context.call_public_function(
context.this_address(),
FunctionSelector::from_signature("dummy_public_call()"),
[]
);
}
}

#[aztec(public)]
#[aztec(internal)]
fn dummy_public_call() {}

#[aztec(private)]
fn call_create_note(value: Field, owner: AztecAddress, storage_slot: Field) {
assert(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use dep::types::{
abis::{
call_request::CallRequest, accumulated_data::CombinedAccumulatedData,
kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputsBuilder,
membership_witness::NoteHashReadRequestMembershipWitness,
max_block_number::MaxBlockNumber, membership_witness::NoteHashReadRequestMembershipWitness,
private_circuit_public_inputs::PrivateCircuitPublicInputs,
private_kernel::private_call_data::PrivateCallData, kernel_data::{PrivateKernelInnerData},
private_kernel::private_call_data::PrivateCallData, kernel_data::PrivateKernelInnerData,
side_effect::{SideEffect, SideEffectLinkedToNoteHash}
},
address::{AztecAddress, EthAddress, PartialAddress, compute_initialization_hash},
Expand Down Expand Up @@ -92,6 +92,7 @@ pub fn initialize_end_values(
public_inputs.min_revertible_side_effect_counter = previous_kernel.public_inputs.min_revertible_side_effect_counter;

let start = previous_kernel.public_inputs.validation_requests;
public_inputs.validation_requests.max_block_number = start.for_rollup.max_block_number;
public_inputs.validation_requests.note_hash_read_requests = array_to_bounded_vec(start.note_hash_read_requests);
public_inputs.validation_requests.nullifier_read_requests = array_to_bounded_vec(start.nullifier_read_requests);
public_inputs.validation_requests.nullifier_key_validation_requests = array_to_bounded_vec(start.nullifier_key_validation_requests);
Expand Down Expand Up @@ -180,6 +181,9 @@ pub fn update_end_values(

let storage_contract_address = private_call_public_inputs.call_context.storage_contract_address;

// Update the max block number if the private call requested a lower one.
public_inputs.validation_requests.max_block_number = MaxBlockNumber::min(public_inputs.validation_requests.max_block_number, private_call_public_inputs.max_block_number);

// Transient read requests and witnesses are accumulated in public_inputs.end
// We silo the read requests (domain separation per contract address)
let read_requests = private_call_public_inputs.note_hash_read_requests;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,23 @@ mod tests {
builder.failed();
}

#[test]
fn default_max_block_number() {
let mut builder = PrivateKernelInitInputsBuilder::new();
let public_inputs = builder.execute();

assert(public_inputs.validation_requests.for_rollup.max_block_number.is_none());
}

#[test]
fn propagate_max_block_number_request() {
let mut builder = PrivateKernelInitInputsBuilder::new();
builder.private_call.request_max_block_number(42);
let public_inputs = builder.execute();

assert_eq(public_inputs.validation_requests.for_rollup.max_block_number.unwrap(), 42);
}

#[test]
fn native_no_note_hash_read_requests_works() {
let mut builder = PrivateKernelInitInputsBuilder::new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ mod tests {
use dep::types::{
abis::{
kernel_circuit_public_inputs::PrivateKernelInnerCircuitPublicInputs,
side_effect::{SideEffect, SideEffectLinkedToNoteHash}
max_block_number::MaxBlockNumber, side_effect::{SideEffect, SideEffectLinkedToNoteHash}
},
address::{AztecAddress, EthAddress}, hash::compute_logs_hash,
messaging::l2_to_l1_message::L2ToL1Message, utils::{arrays::array_length},
Expand Down Expand Up @@ -550,6 +550,36 @@ mod tests {
builder.failed();
}

#[test]
fn propagate_previous_kernel_max_block_number() {
let mut builder = PrivateKernelInnerInputsBuilder::new();
builder.previous_kernel.validation_requests.max_block_number = MaxBlockNumber::new(13);
let public_inputs = builder.execute();

assert_eq(public_inputs.validation_requests.for_rollup.max_block_number.unwrap(), 13);
}

#[test]
fn propagate_max_block_number_request() {
let mut builder = PrivateKernelInnerInputsBuilder::new();
builder.private_call.request_max_block_number(42);
let public_inputs = builder.execute();

assert_eq(public_inputs.validation_requests.for_rollup.max_block_number.unwrap(), 42);
}

#[test]
fn ignore_larger_max_block_number() {
let mut builder = PrivateKernelInnerInputsBuilder::new();
builder.previous_kernel.validation_requests.max_block_number = MaxBlockNumber::new(13);
// A private call requesting a larger max_block_number should not change the current one as that constraint is
// already satisfied.
builder.private_call.request_max_block_number(42);
let public_inputs = builder.execute();

assert_eq(public_inputs.validation_requests.for_rollup.max_block_number.unwrap(), 13);
}

#[test]
fn native_no_note_hash_read_requests_works() {
let mut builder = PrivateKernelInnerInputsBuilder::new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ mod tests {
use dep::types::{
abis::{
kernel_circuit_public_inputs::PrivateKernelTailCircuitPublicInputs,
side_effect::{SideEffect, SideEffectLinkedToNoteHash, Ordered}
max_block_number::MaxBlockNumber, side_effect::{SideEffect, SideEffectLinkedToNoteHash, Ordered}
},
hash::compute_unique_siloed_note_hashes, tests::kernel_data_builder::PreviousKernelDataBuilder,
utils::{arrays::{array_eq, array_length}}, traits::{Empty, is_empty, is_empty_array}
Expand Down Expand Up @@ -452,6 +452,15 @@ mod tests {
builder.failed();
}

#[test]
fn propagate_previous_kernel_max_block_number() {
let mut builder = PrivateKernelTailInputsBuilder::new();
builder.previous_kernel.validation_requests.max_block_number = MaxBlockNumber::new(13);
let public_inputs = builder.execute();

assert_eq(public_inputs.rollup_validation_requests.max_block_number.unwrap(), 13);
}

#[test]
unconstrained fn one_pending_nullifier_read_request() {
let mut builder = PrivateKernelTailInputsBuilder::new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ pub fn initialize_emitted_end_values(
circuit_outputs.end_non_revertible.new_nullifiers = array_to_bounded_vec(start_non_revertible.new_nullifiers);
circuit_outputs.end_non_revertible.public_data_update_requests = array_to_bounded_vec(start_non_revertible.public_data_update_requests);

// TODO - should be propagated only in initialize_end_values() and clear them in the tail circuit.
// TODO - should be propagated only in initialize_end_values() and clear them in the tail circuit. The
// max_block_number must be propagated to the rollup however as a RollupValidationRequest.
let start = previous_kernel.public_inputs.validation_requests;
circuit_outputs.validation_requests.max_block_number = start.for_rollup.max_block_number;
circuit_outputs.validation_requests.public_data_reads = array_to_bounded_vec(start.public_data_reads);
}

Expand All @@ -99,6 +101,7 @@ pub fn initialize_end_values(
circuit_outputs.end_non_revertible.public_call_stack = array_to_bounded_vec(start_non_revertible.public_call_stack);

let start = previous_kernel.public_inputs.validation_requests;
circuit_outputs.validation_requests.max_block_number = previous_kernel.public_inputs.validation_requests.for_rollup.max_block_number;
circuit_outputs.validation_requests.nullifier_read_requests = array_to_bounded_vec(start.nullifier_read_requests);
circuit_outputs.validation_requests.nullifier_non_existent_read_requests = array_to_bounded_vec(start.nullifier_non_existent_read_requests);
}
Expand Down Expand Up @@ -158,6 +161,7 @@ fn validate_call_requests<N>(
}

pub fn update_validation_requests(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) {
// Note that the public kernel cannot modify the max block number value - it simply forwards it to the rollup
propagate_nullifier_read_requests(public_call, circuit_outputs);
propagate_nullifier_non_existent_read_requests(public_call, circuit_outputs);
propagate_valid_public_data_reads(public_call, circuit_outputs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ mod tests {
use dep::types::{
abis::{
call_request::CallRequest, function_selector::FunctionSelector,
kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, public_data_read::PublicDataRead,
public_data_update_request::PublicDataUpdateRequest, public_call_data::PublicCallData,
read_request::ReadRequest
kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, max_block_number::MaxBlockNumber,
public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest,
public_call_data::PublicCallData, read_request::ReadRequest
},
address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId,
contrakt::storage_read::StorageRead, hash::compute_logs_hash,
Expand Down Expand Up @@ -357,6 +357,8 @@ mod tests {
fn circuit_outputs_should_be_correctly_populated_with_previous_private_kernel() {
let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new();

builder.previous_kernel.validation_requests.max_block_number = MaxBlockNumber::new(13);

builder.public_call.append_public_call_requests_for_regular_calls(2);
let storage = builder.public_call.public_call_stack.storage;

Expand Down Expand Up @@ -384,6 +386,7 @@ mod tests {

let public_inputs = kernel.public_kernel_setup();

assert_eq(public_inputs.validation_requests.for_rollup.max_block_number.unwrap(), 13);
assert_eq_call_requests(public_inputs.end.private_call_stack, []);
assert_eq_call_requests(
public_inputs.end_non_revertible.public_call_stack,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ impl BaseRollupInputs {
== self.constants.global_variables.version, "kernel version does not match the rollup version"
);

let rollup_validation_requests = self.kernel_data.public_inputs.rollup_validation_requests;

// Verify the max block number
// TODO #5345: why is block_number a Field and not u32?
if rollup_validation_requests.max_block_number.is_some() {
assert(
self.constants.global_variables.block_number as u32
<= rollup_validation_requests.max_block_number.unwrap_unchecked(), "kernel max_block_number is smaller than block number"
);
}

let commitments_tree_subroot = self.calculate_commitments_subtree();

let empty_commitments_subtree_root = calculate_empty_tree_root(NOTE_HASH_SUBTREE_HEIGHT);
Expand Down Expand Up @@ -1005,6 +1016,30 @@ mod tests {
builder.fails();
}

#[test(should_fail_with = "kernel max_block_number is smaller than block number")]
unconstrained fn constants_dont_satisfy_smaller_max_block_number() {
let mut builder = BaseRollupInputsBuilder::new();
builder.constants.global_variables.block_number = 42;
builder.kernel_data.set_max_block_number(5);
builder.fails();
}

#[test]
unconstrained fn constants_satisfy_equal_max_block_number() {
let mut builder = BaseRollupInputsBuilder::new();
builder.constants.global_variables.block_number = 42;
builder.kernel_data.set_max_block_number(42);
builder.succeeds();
}

#[test]
unconstrained fn constants_satisfy_larger_max_block_number() {
let mut builder = BaseRollupInputsBuilder::new();
builder.constants.global_variables.block_number = 42;
builder.kernel_data.set_max_block_number(4294967295);
builder.succeeds();
}

#[test]
unconstrained fn subtree_height_is_0() {
let outputs = BaseRollupInputsBuilder::new().execute();
Expand Down
2 changes: 2 additions & 0 deletions noir-projects/noir-protocol-circuits/crates/types/src/abis.nr
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ mod public_data_update_request;
mod accumulated_data;
mod validation_requests;

mod max_block_number;

mod private_kernel;
mod kernel_circuit_public_inputs;
mod kernel_data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl PrivateKernelCircuitPublicInputsBuilder {
end_non_revertible,
end,
constants: self.constants,
rollup_validation_requests: self.validation_requests.to_rollup(),
needs_setup: end_non_revertible.needs_setup(),
needs_app_logic: end.needs_app_logic(),
needs_teardown: end_non_revertible.needs_teardown()
Expand Down
Loading

0 comments on commit e20278d

Please sign in to comment.