Skip to content

Commit

Permalink
feat: Sync from noir (#8237)
Browse files Browse the repository at this point in the history
Automated pull of development from the
[noir](https://github.com/noir-lang/noir) programming language, a
dependency of Aztec.
BEGIN_COMMIT_OVERRIDE
feat: add `Type::as_string`
(noir-lang/noir#5871)
feat: add `FunctionDef::has_named_attribute`
(noir-lang/noir#5870)
chore: introduce the Visitor pattern
(noir-lang/noir#5868)
fix(nargo): Resolve Brillig assertion payloads
(noir-lang/noir#5872)
feat(perf): Simplify poseidon2 cache zero-pad
(noir-lang/noir#5869)
feat: Sync from aztec-packages
(noir-lang/noir#5790)
feat: add `Expr::resolve` and `TypedExpr::as_function_definition`
(noir-lang/noir#5859)
feat: LSP signature help for assert and assert_eq
(noir-lang/noir#5862)
fix(sha256): Add extra checks against message size when constructing msg
blocks (noir-lang/noir#5861)
feat: show backtrace on comptime assertion failures
(noir-lang/noir#5842)
feat: add `Expr::as_assert`
(noir-lang/noir#5857)
chore: underconstrained check in parallel
(noir-lang/noir#5848)
feat(meta): Comptime keccak
(noir-lang/noir#5854)
feat(optimization): Avoid merging identical (by ID) arrays
(noir-lang/noir#5853)
feat: add `FunctionDef::body`
(noir-lang/noir#5825)
fix(sha256): Fix upper bound when building msg block and delay final
block compression under certain cases
(noir-lang/noir#5838)
feat: remove unnecessary copying of vector size during reversal
(noir-lang/noir#5852)
chore: Add missing cases to arithmetic generics
(noir-lang/noir#5841)
feat: warn on unused imports
(noir-lang/noir#5847)
chore: add documentation to `to_be_bytes`, etc.
(noir-lang/noir#5843)
feat: simplify constant calls to `poseidon2_permutation`,
`schnorr_verify` and `embedded_curve_add`
(noir-lang/noir#5140)
chore: don't require empty `Prover.toml` for programs with zero
arguments but a return value
(noir-lang/noir#5845)
fix!: Check unused generics are bound
(noir-lang/noir#5840)
chore(perf): Simplify poseidon2 algorithm
(noir-lang/noir#5811)
chore: redo typo PR by nnsW3
(noir-lang/noir#5834)
fix(sha256): Perform compression per block and utilize ROM instead of
RAM when setting up the message block
(noir-lang/noir#5760)
chore(perf): Update to stdlib keccak for reduced Brillig code size
(noir-lang/noir#5827)
END_COMMIT_OVERRIDE

---------

Co-authored-by: Tom French <[email protected]>
Co-authored-by: Tom French <[email protected]>
Co-authored-by: Maxim Vezenov <[email protected]>
  • Loading branch information
4 people authored Sep 1, 2024
1 parent fd61e44 commit cf5b667
Show file tree
Hide file tree
Showing 164 changed files with 7,178 additions and 2,700 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
86c151aa43ba990a0e900995064a88fc2ae6637d
e29d4b3646f0527fc01bc4584ee33616db922c72
136 changes: 68 additions & 68 deletions noir-projects/aztec-nr/authwit/src/auth.nr
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext,
/**
* Authenticaion witness helper library
*
* Authentication Witness is a scheme for authenticating actions on Aztec, so users can allow third-parties
* Authentication Witness is a scheme for authenticating actions on Aztec, so users can allow third-parties
* (e.g. protocols or other users) to execute an action on their behalf.
*
*
* This library provides helper functions to manage such witnesses.
* The authentication witness, is some "witness" (data) that authenticates a `message_hash`.
* The simplest example of an authentication witness, is a signature. The signature is the "evidence",
Expand All @@ -28,54 +28,54 @@ use dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext,
* - version: the version of the chain that the message is being consumed on,
* - inner_hash: the hash of the "inner" message that is being consumed, this is the "actual" message or action.
*
* While the `inner_hash` could be anything, such as showing you signed a specific message, it will often be
* a hash of the "action" to approve, along with who made the call. As part of this library, we provide a few
* While the `inner_hash` could be anything, such as showing you signed a specific message, it will often be
* a hash of the "action" to approve, along with who made the call. As part of this library, we provide a few
* helper functions to deal with such messages.
*
* For example, we provide helper function that is used for checking that the message is an encoding of the current call.
* This can be used to let some contract "allow" another contract to act on its behalf, as long as it can
* This can be used to let some contract "allow" another contract to act on its behalf, as long as it can
* show that it is acting on behalf of the contract.
*
* If we take a case of allowing a contract to transfer tokens on behalf of an account, the `inner_hash` can be
* If we take a case of allowing a contract to transfer tokens on behalf of an account, the `inner_hash` can be
* derived as:
* inner_hash = hash(caller, "transfer", hash(to, amount))
*
*
* Where the `caller` would be the address of the contract that is trying to transfer the tokens, and `to` and `amount`
* the arguments for the transfer.
*
* the arguments for the transfer.
*
* Note that we have both a `caller` and a `consumer`, the `consumer` will be the contract that is consuming the message,
* in the case of the transfer, it would be the `Token` contract itself, while the caller, will be the actor that is
* in the case of the transfer, it would be the `Token` contract itself, while the caller, will be the actor that is
* allowed to transfer the tokens.
*
*
* The authentication mechanism works differently in public and private contexts. In private, we recall that everything
* is executed on the user's device, so we can use `oracles` to "ask" the user (not contract) for information. In public
* we cannot do this, since it is executed by the sequencer (someone else). Therefore we can instead use a "registry"
* to store the messages that we have approved.
*
* A simple example would be a "token" that is being "pulled" from one account into another. We will first outline
* how this would look in private, and then in public later.
*
* Say that a user `Alice` wants to deposit some tokens into a DeFi protocol (say a DEX).
* `Alice` would make a `deposit` transaction, that she is executing using her account contract.
* The account would call the `DeFi` contract to execute `deposit`, which would try to pull funds from the `Token`
* contract. Since the `DeFi` contract is trying to pull funds from an account that is not its own, it needs to
* convince the `Token` contract that it is allowed to do so.
*
* This is where the authentication witness comes in The `Token` contract computes a `message_hash` from the
* `transfer` call, and then asks `Alice Account` contract to verify that the `DeFi` contract is allowed to
*
* A simple example would be a "token" that is being "pulled" from one account into another. We will first outline
* how this would look in private, and then in public later.
*
* Say that a user `Alice` wants to deposit some tokens into a DeFi protocol (say a DEX).
* `Alice` would make a `deposit` transaction, that she is executing using her account contract.
* The account would call the `DeFi` contract to execute `deposit`, which would try to pull funds from the `Token`
* contract. Since the `DeFi` contract is trying to pull funds from an account that is not its own, it needs to
* convince the `Token` contract that it is allowed to do so.
*
* This is where the authentication witness comes in The `Token` contract computes a `message_hash` from the
* `transfer` call, and then asks `Alice Account` contract to verify that the `DeFi` contract is allowed to
* execute that call.
*
* `Alice Account` contract can then ask `Alice` if she wants to allow the `DeFi` contract to pull funds from her
*
* `Alice Account` contract can then ask `Alice` if she wants to allow the `DeFi` contract to pull funds from her
* account. If she does, she will sign the `message_hash` and return the signature to the `Alice Account` which
* will validate it and return success to the `Token` contract which will then allow the `DeFi` contract to pull
* funds from `Alice`.
*
*
* To ensure that the same "approval" cannot be used multiple times, we also compute a `nullifier` for the
* authentication witness, and emit it from the `Token` contract (consumer).
*
* Note that we can do this flow as we are in private were we can do oracle calls out from contracts.
*
*
* Note that we can do this flow as we are in private were we can do oracle calls out from contracts.
*
*
* Person Contract Contract Contract
* Alice Alice Account Token DeFi
Expand Down Expand Up @@ -116,10 +116,10 @@ use dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext,
* | | | |
* | | | |
*
*
* If we instead were in public, we cannot do the same flow. Instead we would use an authentication registry to store
* the messages that we have approved.
*
*
* If we instead were in public, we cannot do the same flow. Instead we would use an authentication registry to store
* the messages that we have approved.
*
* To approve a message, `Alice Account` can make a `set_authorized` call to the registry, to set a `message_hash`
* as authorized. This is essentially a mapping from `message_hash` to `true` for `Alice Contract`. Every account
* has its own map in the registry, so `Alice` cannot approve a message for `Bob`.
Expand Down Expand Up @@ -172,31 +172,31 @@ use dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext,
* --- FAQ ---
* Q: Why are we using a success flag of `keccak256("IS_VALID()")` instead of just returning a boolean?
* A: We want to make sure that we don't accidentally return `true` if there is a collision in the function selector.
* By returning a hash of `IS_VALID()`, it becomes very unlikely that there is both a colission and we return
* By returning a hash of `IS_VALID()`, it becomes very unlikely that there is both a collision and we return
* a success flag.
*
*
* Q: Why are we using static calls?
* A: We are using static calls to ensure that the account contract cannot re-enter. If it was a normal call, it
* could make a new call and do a re-entry attack. Using a static ensures that it cannot update any state.
*
* Q: Would it not be cheaper to use a nullifier instead of updating state in public?
* A: At a quick glance, a public state update + nullifier is 96 bytes, but two state updates are 128, so it would be
* cheaper to use a nullifier, if this is the way it would always be done. However, if both the approval and the
* A: At a quick glance, a public state update + nullifier is 96 bytes, but two state updates are 128, so it would be
* cheaper to use a nullifier, if this is the way it would always be done. However, if both the approval and the
* consumption is done in the same transaction, then we will be able to squash the updates (only final tx state diff is posted to DA), and now it is cheaper.
*
*
* Q: Why is the chain id and the version part of the message hash?
* A: The chain id and the version is part of the message hash to ensure that the message is only valid on a specific
* chain to avoid a case where the same message could be used across multiple chains.
* chain to avoid a case where the same message could be used across multiple chains.
*/

global IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256("IS_VALID()")

/**
/**
* Assert that `on_behalf_of` have authorized the current call with a valid authentication witness
*
* Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the
*
* Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the
* `on_behalf_of` contract to verify that the `inner_hash` is valid.
*
*
* @param on_behalf_of The address that have authorized the current call
*/
// docs:start:assert_current_call_valid_authwit
Expand All @@ -206,14 +206,14 @@ pub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf
}
// docs:end:assert_current_call_valid_authwit

/**
/**
* Assert that a specific `inner_hash` is valid for the `on_behalf_of` address
*
*
* Used as an internal function for `assert_current_call_valid_authwit` and can be used as a standalone function when
* the `inner_hash` is from a different source, e.g., say a block of text etc.
*
*
* @param on_behalf_of The address that have authorized the current call
* @param inner_hash The hash of the message to authorize
* @param inner_hash The hash of the message to authorize
*/
pub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {
// We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.
Expand All @@ -229,15 +229,15 @@ pub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_o
context.push_nullifier(nullifier);
}

/**
/**
* Assert that `on_behalf_of` have authorized the current call in the authentication registry
*
* Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the
*
* Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the
* `on_behalf_of` contract to verify that the `inner_hash` is valid.
*
*
* Note that the authentication registry will take the `msg_sender` into account as the consumer, so this will only
* work if the `msg_sender` is the same as the `consumer` when the `message_hash` was inserted into the registry.
*
*
* @param on_behalf_of The address that have authorized the current call
*/
// docs:start:assert_current_call_valid_authwit_public
Expand All @@ -249,15 +249,15 @@ pub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_
}
// docs:end:assert_current_call_valid_authwit_public

/**
/**
* Assert that `on_behalf_of` have authorized a speicifc `inner_hash` in the authentication registry
*
* Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the
*
* Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the
* `on_behalf_of` contract to verify that the `inner_hash` is valid.
*
* Note that the authentication registry will take the `msg_sender` into account as the consumer, so this will only
* work if the `msg_sender` is the same as the `consumer` when the `message_hash` was inserted into the registry.
*
*
* @param on_behalf_of The address that have authorized the `inner_hash`
*/
pub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {
Expand All @@ -271,12 +271,12 @@ pub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_be
}

/**
* Compute the `message_hash` from a function call to be used by an authentication witness
*
* Compute the `message_hash` from a function call to be used by an authentication witness
*
* Useful for when you need a non-account contract to approve during execution. For example if you need a contract
* to make a call to nested contract, e.g., contract A wants to exit token T to L1 using bridge B, so it needs to allow
* B to transfer T on its behalf.
*
*
* @param caller The address of the contract that is calling the function, in the example above, this would be B
* @param consumer The address of the contract that is consuming the message, in the example above, this would be T
* @param chain_id The chain id of the chain that the message is being consumed on
Expand All @@ -301,21 +301,21 @@ pub fn compute_authwit_message_hash_from_call<let N: u32>(

/**
* Computes the `inner_hash` of the authentication witness
*
*
* This is used internally, but also useful in cases where you want to compute the `inner_hash` for a specific message
* that is not necessarily a call, but just some "bytes" or text.
*
*
* @param args The arguments to hash
*/
pub fn compute_inner_authwit_hash<let N: u32>(args: [Field; N]) -> Field {
poseidon2_hash_with_separator(args, GENERATOR_INDEX__AUTHWIT_INNER)
}

/**
/**
* Computs the `authwit_nullifier` for a specific `on_behalf_of` and `inner_hash`
*
*
* Using the `on_behalf_of` and the `inner_hash` to ensure that the nullifier is siloed for a specific `on_behalf_of`.
*
*
* @param on_behalf_of The address that have authorized the `inner_hash`
* @param inner_hash The hash of the message to authorize
*/
Expand All @@ -328,7 +328,7 @@ pub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field)

/**
* Computes the `message_hash` for the authentication witness
*
*
* @param consumer The address of the contract that is consuming the message
* @param chain_id The chain id of the chain that the message is being consumed on
* @param version The version of the chain that the message is being consumed on
Expand All @@ -348,9 +348,9 @@ pub fn compute_authwit_message_hash(consumer: AztecAddress, chain_id: Field, ver

/**
* Helper function to set the authorization status of a message hash
*
*
* Wraps a public call to the authentication registry to set the authorization status of a `message_hash`
*
*
* @param message_hash The hash of the message to authorize
* @param authorize True if the message should be authorized, false if it should be revoked
*/
Expand All @@ -365,10 +365,10 @@ pub fn set_authorized(context: &mut PublicContext, message_hash: Field, authoriz

/**
* Helper function to reject all authwits
*
*
* Wraps a public call to the authentication registry to set the `reject_all` flag
*
* @param reject True if all authwits should be rejected, false otherwise
* @param reject True if all authwits should be rejected, false otherwise
*/
pub fn set_reject_all(context: &mut PublicContext, reject: bool) {
context.call_public_function(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ impl<T, let INITIAL_DELAY: u32, Context> SharedMutable<T, INITIAL_DELAY, Context
}

impl<T, let INITIAL_DELAY: u32> SharedMutable<T, INITIAL_DELAY, &mut PublicContext> where T: ToField + FromField + Eq {

pub fn schedule_value_change(self, new_value: T) {
let mut value_change = self.read_value_change();
let delay_change = self.read_delay_change();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl TestEnvironment {
PackedReturns::new(public_inputs.returns_hash).unpack_into()
}

fn call_private_void<C, let M: u32, Env, let N: u32>(
fn call_private_void<C, let M: u32, Env>(
_self: Self,
call_interface: C
) where C: CallInterface<M, PrivateContextInputs, PrivateCircuitPublicInputs, Env> {
Expand All @@ -154,7 +154,7 @@ impl TestEnvironment {
PackedReturns::new(public_inputs.returns_hash).assert_empty();
}

fn call_public<C, let M: u32, T, Env, let N: u32>(
fn call_public<C, let M: u32, T, Env>(
_self: Self,
call_interface: C
) -> T where C: CallInterface<M, PublicContextInputs, T, Env> {
Expand All @@ -179,7 +179,7 @@ impl TestEnvironment {
result
}

fn assert_public_call_fails<C, let M: u32, T, Env, let N: u32>(
fn assert_public_call_fails<C, let M: u32, T, Env>(
_self: Self,
call_interface: C
) where C: CallInterface<M, PublicContextInputs, T, Env> {
Expand All @@ -190,7 +190,7 @@ impl TestEnvironment {
);
}

fn assert_private_call_fails<C, let M: u32, T, Env, let N: u32>(
fn assert_private_call_fails<C, let M: u32, T, Env>(
_self: Self,
call_interface: C
) where C: CallInterface<M, PrivateContextInputs, T, Env> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use dep::mock_types::{
PrivateKernelPublicInputs, PrivateKernelPublicInputsBuilder, MAX_COMMITMENT_READ_REQUESTS_PER_TX,
MAX_COMMITMENTS_PER_TX
};
use dep::mock_types::{PrivateKernelPublicInputs, MAX_COMMITMENT_READ_REQUESTS_PER_TX, MAX_COMMITMENTS_PER_TX};

// Mock reset kernel that reset read requests.
// It needs hints to locate the commitment that matches the read requests.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use dep::mock_types::{
PrivateKernelPublicInputs, PrivateKernelPublicInputsBuilder, KernelPublicInputs,
MAX_COMMITMENT_READ_REQUESTS_PER_TX
};
use dep::mock_types::{PrivateKernelPublicInputs, KernelPublicInputs, MAX_COMMITMENT_READ_REQUESTS_PER_TX};

// The tail kernel finishes the client IVC chain exposing the final public inputs with no remaining calls or unfulfilled read requests.
fn main(prev_kernel_public_inputs: PrivateKernelPublicInputs) -> pub KernelPublicInputs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct ResetOutputValidator<
let NH_RR_SETTLED: u32,
let NLL_RR_PENDING: u32,
let NLL_RR_SETTLED: u32,
let KEY_VALIDATION_REQUESTS: u32,
let KEY_VALIDATION_REQUESTS: u32,
let NUM_TRANSIENT_DATA_INDEX_HINTS: u32
> {
output: PrivateKernelCircuitPublicInputs,
Expand All @@ -33,7 +33,7 @@ impl<
let NH_RR_SETTLED: u32,
let NLL_RR_PENDING: u32,
let NLL_RR_SETTLED: u32,
let KEY_VALIDATION_REQUESTS: u32,
let KEY_VALIDATION_REQUESTS: u32,
let NUM_TRANSIENT_DATA_INDEX_HINTS: u32
> ResetOutputValidator<NH_RR_PENDING, NH_RR_SETTLED, NLL_RR_PENDING, NLL_RR_SETTLED, KEY_VALIDATION_REQUESTS, NUM_TRANSIENT_DATA_INDEX_HINTS> {
pub fn new(
Expand Down Expand Up @@ -182,9 +182,9 @@ impl<

fn validate_sorted_note_logs(self) {
// This will be called together with validate_sorted_siloed_note_hashes().
// Same as validate_sorted_siloed_note_hashes, it will only be run once.
// Same as validate_sorted_siloed_note_hashes, it will only be run once.
// This is fine because we don't allow emitting logs for notes emitted in another function at the moment.
// All the note logs emitted in a function call must link to note hashes emitted in the same call.
// All the note logs emitted in a function call must link to note hashes emitted in the same call.
// This is checked in PrivateCallDataValidator > validate_note_logs.

// note_hash_counter was used when squashing the note log along with its corresponding note hash.
Expand Down
Loading

0 comments on commit cf5b667

Please sign in to comment.