Skip to content

Commit

Permalink
fix: Sequencer times out L1 tx at end of L2 slot (#11112)
Browse files Browse the repository at this point in the history
Sets the L1 tx utils timeout to the end of the L2 slot.
  • Loading branch information
spalladino authored and benesjan committed Jan 13, 2025
1 parent 9ab4cee commit f10d88a
Show file tree
Hide file tree
Showing 44 changed files with 378 additions and 247 deletions.
7 changes: 4 additions & 3 deletions noir-projects/aztec-nr/aztec/src/context/packed_returns.nr
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ impl PackedReturns {
}

pub fn unpack<let N: u32>(self) -> [Field; N] {
// We verify that the value returned by `unpack_returns` is the preimage of `packed_returns`, fully constraining
// it.
let unpacked: [Field; N] = unsafe { unpack_returns(self.packed_returns) };
let unpacked: [Field; N] = unsafe {
//@safety We check `unpacked` against the hash below.
unpack_returns(self.packed_returns)
};
assert_eq(self.packed_returns, hash_args_array(unpacked));
unpacked
}
Expand Down
41 changes: 22 additions & 19 deletions noir-projects/aztec-nr/aztec/src/context/private_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,11 @@ impl PrivateContext {
// about secrets from other contracts. We therefore silo secret keys, and rely on the private kernel to
// validate that we siloed secret key corresponds to correct siloing of the master secret key that hashes
// to `pk_m_hash`.
let request = unsafe { get_key_validation_request(pk_m_hash, key_index) };
assert(request.pk_m.hash() == pk_m_hash);
let request = unsafe {
//@safety Kernels verify that the key validation request is valid and below we verify that a request
// for the correct public key has been received.
get_key_validation_request(pk_m_hash, key_index)
};

self.key_validation_requests_and_generators.push(
KeyValidationRequestAndGenerator {
Expand Down Expand Up @@ -385,12 +388,12 @@ impl PrivateContext {
let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;
let start_side_effect_counter = self.side_effect_counter;

// The oracle simulates the private call and returns the value of the side effects counter after execution of
// the call (which means that end_side_effect_counter - start_side_effect_counter is the number of side effects
// that took place), along with the hash of the return values. We validate these by requesting a private kernel
// iteration in which the return values are constrained to hash to `returns_hash` and the side effects counter
// to increment from start to end.
let (end_side_effect_counter, returns_hash) = unsafe {
//@safety The oracle simulates the private call and returns the value of the side effects counter after
// execution of the call (which means that end_side_effect_counter - start_side_effect_counter is
// the number of side effects that took place), along with the hash of the return values. We validate these
// by requesting a private kernel iteration in which the return values are constrained to hash
// to `returns_hash` and the side effects counter to increment from start to end.
call_private_function_internal(
contract_address,
function_selector,
Expand Down Expand Up @@ -488,13 +491,13 @@ impl PrivateContext {
let counter = self.next_counter();

let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this.
// WARNING: This is insecure and should be temporary!
// The oracle repacks the arguments and returns a new args_hash.
// new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
// We don't validate or compute it in the circuit because a) it's harder to do with slices, and
// b) this is only temporary.
let args_hash = unsafe {
//@safety TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this.
// WARNING: This is insecure and should be temporary!
// The oracle repacks the arguments and returns a new args_hash.
// new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
// We don't validate or compute it in the circuit because a) it's harder to do with slices, and
// b) this is only temporary.
enqueue_public_function_call_internal(
contract_address,
function_selector,
Expand Down Expand Up @@ -544,13 +547,13 @@ impl PrivateContext {
let counter = self.next_counter();

let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this.
// WARNING: This is insecure and should be temporary!
// The oracle repacks the arguments and returns a new args_hash.
// new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
// We don't validate or compute it in the circuit because a) it's harder to do with slices, and
// b) this is only temporary.
let args_hash = unsafe {
//@safety TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this.
// WARNING: This is insecure and should be temporary!
// The oracle repacks the arguments and returns a new args_hash.
// new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
// We don't validate or compute it in the circuit because a) it's harder to do with slices, and
// b) this is only temporary.
set_public_teardown_function_call_internal(
contract_address,
function_selector,
Expand Down
92 changes: 59 additions & 33 deletions noir-projects/aztec-nr/aztec/src/context/public_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,34 @@ impl PublicContext {
where
T: Serialize<N>,
{
// AVM opcodes are constrained by the AVM itself
unsafe { emit_unencrypted_log(Serialize::serialize(log).as_slice()) };
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
emit_unencrypted_log(Serialize::serialize(log).as_slice())
};
}

pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: Field) -> bool {
// AVM opcodes are constrained by the AVM itself
unsafe { note_hash_exists(note_hash, leaf_index) } == 1
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
note_hash_exists(note_hash, leaf_index)
}
== 1
}

pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {
// AVM opcodes are constrained by the AVM itself
unsafe { l1_to_l2_msg_exists(msg_hash, msg_leaf_index) } == 1
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
l1_to_l2_msg_exists(msg_hash, msg_leaf_index)
}
== 1
}

pub fn nullifier_exists(_self: Self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {
// AVM opcodes are constrained by the AVM itself
unsafe { nullifier_exists(unsiloed_nullifier, address.to_field()) } == 1
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
nullifier_exists(unsiloed_nullifier, address.to_field())
}
== 1
}

pub fn consume_l1_to_l2_message(
Expand Down Expand Up @@ -73,8 +84,10 @@ impl PublicContext {
}

pub fn message_portal(_self: &mut Self, recipient: EthAddress, content: Field) {
// AVM opcodes are constrained by the AVM itself
unsafe { send_l2_to_l1_msg(recipient, content) };
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
send_l2_to_l1_msg(recipient, content)
};
}

pub unconstrained fn call_public_function(
Expand Down Expand Up @@ -114,30 +127,36 @@ impl PublicContext {
}

pub fn push_note_hash(_self: &mut Self, note_hash: Field) {
// AVM opcodes are constrained by the AVM itself
unsafe { emit_note_hash(note_hash) };
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
emit_note_hash(note_hash)
};
}
pub fn push_nullifier(_self: &mut Self, nullifier: Field) {
// AVM opcodes are constrained by the AVM itself
unsafe { emit_nullifier(nullifier) };
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
emit_nullifier(nullifier)
};
}

pub fn this_address(_self: Self) -> AztecAddress {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
address()
}
}
pub fn msg_sender(_self: Self) -> AztecAddress {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
sender()
}
}
pub fn selector(_self: Self) -> FunctionSelector {
// The selector is the first element of the calldata when calling a public function through dispatch.
// AVM opcodes are constrained by the AVM itself.
let raw_selector: [Field; 1] = unsafe { calldata_copy(0, 1) };
let raw_selector: [Field; 1] = unsafe {
//@safety AVM opcodes are constrained by the AVM itself
calldata_copy(0, 1)
};
FunctionSelector::from_field(raw_selector[0])
}
pub fn get_args_hash(mut self) -> Field {
Expand All @@ -148,71 +167,76 @@ impl PublicContext {
self.args_hash.unwrap_unchecked()
}
pub fn transaction_fee(_self: Self) -> Field {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
transaction_fee()
}
}

pub fn chain_id(_self: Self) -> Field {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
chain_id()
}
}
pub fn version(_self: Self) -> Field {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
version()
}
}
pub fn block_number(_self: Self) -> Field {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
block_number()
}
}
pub fn timestamp(_self: Self) -> u64 {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
timestamp()
}
}
pub fn fee_per_l2_gas(_self: Self) -> Field {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
fee_per_l2_gas()
}
}
pub fn fee_per_da_gas(_self: Self) -> Field {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
fee_per_da_gas()
}
}

pub fn l2_gas_left(_self: Self) -> Field {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
l2_gas_left()
}
}
pub fn da_gas_left(_self: Self) -> Field {
// AVM opcodes are constrained by the AVM itself
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
da_gas_left()
}
}
pub fn is_static_call(_self: Self) -> bool {
// AVM opcodes are constrained by the AVM itself
unsafe { is_static_call() } == 1
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
is_static_call()
}
== 1
}

pub fn raw_storage_read<let N: u32>(_self: Self, storage_slot: Field) -> [Field; N] {
let mut out = [0; N];
for i in 0..N {
// AVM opcodes are constrained by the AVM itself
out[i] = unsafe { storage_read(storage_slot + i as Field) };
out[i] = unsafe {
//@safety AVM opcodes are constrained by the AVM itself
storage_read(storage_slot + i as Field)
};
}
out
}
Expand All @@ -226,8 +250,10 @@ impl PublicContext {

pub fn raw_storage_write<let N: u32>(_self: Self, storage_slot: Field, values: [Field; N]) {
for i in 0..N {
// AVM opcodes are constrained by the AVM itself
unsafe { storage_write(storage_slot + i as Field, values[i]) };
unsafe {
//@safety AVM opcodes are constrained by the AVM itself
storage_write(storage_slot + i as Field, values[i])
};
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ where
Event: EventInterface<N>,
{
|e: Event| {
// Unconstrained logs have both their content and encryption unconstrained - it could occur that the
// recipient is unable to decrypt the payload.
let encrypted_log =
unsafe { compute_payload_unconstrained(*context, e, recipient, sender) };
let encrypted_log = unsafe {
//@safety Unconstrained logs have both their content and encryption unconstrained - it could occur that the
// recipient is unable to decrypt the payload.
compute_payload_unconstrained(*context, e, recipient, sender)
};
context.emit_private_log(encrypted_log);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,18 @@ where
Note: NoteInterface<N>,
{
|e: NoteEmission<Note>| {
// Unconstrained logs have both their content and encryption unconstrained - it could occur that the
// recipient is unable to decrypt the payload.
// Regarding the note hash counter, this is used for squashing. The kernel assumes that a given note can have
// more than one log and removes all of the matching ones, so all a malicious sender could do is either: cause
// for the log to be deleted when it shouldn't have (which is fine - they can already make the content be
// whatever), or cause for the log to not be deleted when it should have (which is also fine - it'll be a log
// for a note that doesn't exist).
// It's important here that we do not
// return the log from this function to the app, otherwise it could try to do stuff with it and then that might
// be wrong.
let (encrypted_log, note_hash_counter) =
unsafe { compute_payload_unconstrained(*context, e.note, recipient, sender) };
let (encrypted_log, note_hash_counter) = unsafe {
//@safety Unconstrained logs have both their content and encryption unconstrained - it could occur that
// the recipient is unable to decrypt the payload.
// Regarding the note hash counter, this is used for squashing. The kernel assumes that a given note can
// have more than one log and removes all of the matching ones, so all a malicious sender could do is
// either: cause for the log to be deleted when it shouldn't have (which is fine - they can already make
// the content be whatever), or cause for the log to not be deleted when it should have (which is also fine
// - it'll be a log for a note that doesn't exist).
// It's important here that we do not return the log from this function to the app, otherwise it could
// try to do stuff with it and then that might be wrong.
compute_payload_unconstrained(*context, e.note, recipient, sender)
};
context.emit_raw_note_log(encrypted_log, note_hash_counter);
}
}
Loading

0 comments on commit f10d88a

Please sign in to comment.