From 5b54279d383016e66b3d06c69dfbea617c772181 Mon Sep 17 00:00:00 2001 From: superstar0402 Date: Fri, 22 Mar 2024 15:26:39 -0300 Subject: [PATCH] feat: introduce max_block_number (#5251) Part of #4761. This adds a new validity condition to transactions called `max_block_number`, causing them to fail if the current block is larger than a requested max block. This can be used to construct proofs that are only valid if included before a certain block (which is exactly how SharedMutableStorage/SlowJoe/SlowUpdatesTree2.0 works). --- I made `max_block_number` an `Option` both to not have to include a initial value equal to the largest block, and also to avoid issues that arise from abuse of `std::unsafe::zeroed`. Many parts of the stack assume a (mostly) zeroed transaction is a valid one, but a `max_block_number` value of 0 is not useful. With `Option`, a zeroed value means no max block number was requested (`is_none()` returns true), and this entire issue is avoided. This property is initially set to `is_none()`, meaning there's no max block number constraint. The `PrivateContext` now has a `request_max_block_number` function that can be used to add constraints. Each time a lower max block number is seen it replaces the current one. The private kernel aggregates these across private calls and ends up with the smallest one. This value is stored in a new struct called `RollupValidationRequests`, an extension from @LeilaWang's work in https://github.com/AztecProtocol/aztec-packages/pull/5236. These are validation requests accumulated during private and public execution that are forwarded to the rollup for it to check. Currently we only have `max_block_number`, but there may be more. Note that we currently have a slight duplication in the public kernal tail public inputs, but this is expected to be sorted out very soon as this struct is refactored. --- Note that in the end to end tests we're only testing that the sequencer drops the transaction, but not that the base rollup rejects this transaction (this is only tested in the rollup circuit unit tests). Testing this would require bypassing the sequencer tx validation logic and manually building a block, but this is a fairly involved endeavor and one that our infrastructure does not currently easily support. I'm still looking into a way to add this test. --- aztec/src/context/private_context.nr | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/aztec/src/context/private_context.nr b/aztec/src/context/private_context.nr index e81ec72..4b70bfd 100644 --- a/aztec/src/context/private_context.nr +++ b/aztec/src/context/private_context.nr @@ -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, @@ -46,6 +46,8 @@ struct PrivateContext { args_hash : Field, return_values : BoundedVec, + max_block_number: MaxBlockNumber, + note_hash_read_requests: BoundedVec, nullifier_read_requests: BoundedVec, nullifier_key_validation_requests: BoundedVec, @@ -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(), @@ -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, @@ -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);