Skip to content

Commit

Permalink
feat: View functions with static context enforcing (#6338)
Browse files Browse the repository at this point in the history
Closes #6078

Introduces the `#[aztec(view)]` (open to different naming, @spalladino
@rahul-kothari ) modifier to functions, that forces them to be executed
in an static context. It also forces generation of a "static only"
`CallInterface` for them, trying to spare users from making regular
calls to them.

~~Need input from the AVM team (@dbanks12 @fcarreiro) on how to
implement the concept in the AVMContext.~~

In order to support direct simulated calls to view functions, the
simulate method has been modified to go through the account entrypoint,
which has led to implementing retrieval of return values through the
whole callstack instead of just taking the latest one.

Also adds the ability to navigate from contract interfaces to their
implementations via LSP!

---------

Co-authored-by: dbanks12 <david@aztecprotocol.com>
  • Loading branch information
Thunkar and dbanks12 authored May 20, 2024
1 parent e5cc9dc commit 22ad5a5
Show file tree
Hide file tree
Showing 89 changed files with 1,391 additions and 493 deletions.
2 changes: 2 additions & 0 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ enum class OpCode : uint8_t {
// Gadgets
KECCAK,
POSEIDON2,
SHA256,
PEDERSEN,

// Conversions
TORADIXLE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const size_t CONTRACT_INSTANCE_LENGTH = 5;
const size_t CONTRACT_STORAGE_READ_LENGTH = 2;
const size_t CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2;
const size_t ETH_ADDRESS_LENGTH = 1;
const size_t FUNCTION_DATA_LENGTH = 2;
const size_t FUNCTION_DATA_LENGTH = 3;
const size_t FUNCTION_LEAF_PREIMAGE_LENGTH = 5;
const size_t GLOBAL_VARIABLES_LENGTH = 6 + GAS_FEES_LENGTH;
const size_t APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2;
Expand Down
48 changes: 42 additions & 6 deletions docs/docs/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,56 @@ keywords: [sandbox, cli, aztec, notes, migration, updating, upgrading]

Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them.

## 0.X.X

### [Aztec.nr] View functions and interface navigation

It is now possible to explicitly state a function doesn't perform any state alterations (including storage, logs, nullifiers and/or messages from L2 to L1) with the `#[aztec(view)]` attribute, similarly to solidity's `view` function modifier.

```diff
#[aztec(public)]
+ #[aztec(view)]
fn get_price(asset_id: Field) -> Asset {
storage.assets.at(asset_id).read()
}
```

View functions only generate a `StaticCallInterface` that doesn't include `.call` or `.enqueue` methods. Also, the denomination `static` has been completely removed from the interfaces, in favor of the more familiar `view`

```diff
+ let price = PriceFeed::at(asset.oracle).get_price(0).view(&mut context).price;
- let price = PriceFeed::at(asset.oracle).get_price(0).static_call(&mut context).price;
```

```diff
#[aztec(private)]
fn enqueue_public_get_value_from_child(target_contract: AztecAddress, value: Field) {
+ StaticChild::at(target_contract).pub_get_value(value).enqueue_view(&mut context);
- StaticChild::at(target_contract).pub_get_value(value).static_enqueue(&mut context);
}
```

Additionally, the Noir LSP will now honor "go to definitions" requests for contract interfaces (Ctrl+click), taking the user to the original function implementation.

### [Aztec.js] Simulate changes

* `.simulate()` now tracks closer the process performed by `.send().wait()`, specifically going through the account contract entrypoint instead of directly calling the intended function.
* `wallet.viewTx(...)` has been renamed to `wallet.simulateUnconstrained(...)` to better clarify what it does.

## 0.41.0

### [Aztec.nr] Keys: Token note now stores an owner master nullifying public key hash instead of an owner address

i.e.

struct TokenNote \{
```diff
struct TokenNote {
amount: U128,
```diff
- owner: AztecAddress,
+ npk_m_hash: Field,
```
- owner: AztecAddress,
+ npk_m_hash: Field,
randomness: Field,
\}
}
```

Computing the nullifier similarly changes to use this master nullifying public key hash.

Expand Down
2 changes: 1 addition & 1 deletion docs/static/img/sandbox_unconstrained_function.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ library Constants {
uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 2;
uint256 internal constant CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2;
uint256 internal constant ETH_ADDRESS_LENGTH = 1;
uint256 internal constant FUNCTION_DATA_LENGTH = 2;
uint256 internal constant FUNCTION_DATA_LENGTH = 3;
uint256 internal constant FUNCTION_LEAF_PREIMAGE_LENGTH = 5;
uint256 internal constant GLOBAL_VARIABLES_LENGTH = 6 + GAS_FEES_LENGTH;
uint256 internal constant APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2;
Expand Down
8 changes: 4 additions & 4 deletions noir-projects/aztec-nr/authwit/src/entrypoint/app.nr
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD,
use crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};

// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1
global APP_PAYLOAD_SIZE: u64 = 17;
global APP_PAYLOAD_SIZE: u64 = 21;
// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32
global APP_PAYLOAD_SIZE_IN_BYTES: u64 = 420;
global APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;

global ACCOUNT_MAX_CALLS: u64 = 4;

Expand Down Expand Up @@ -62,15 +62,15 @@ impl AppPayload {
call.target_address,
call.function_selector,
call.args_hash,
false,
call.is_static,
false
);
} else {
let _result = context.call_private_function_with_packed_args(
call.target_address,
call.function_selector,
call.args_hash,
false,
call.is_static,
false
);
}
Expand Down
12 changes: 6 additions & 6 deletions noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ use dep::aztec::prelude::PrivateContext;
use dep::aztec::protocol_types::{constants::GENERATOR_INDEX__FEE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};
use crate::entrypoint::function_call::FunctionCall;

// 2 * 4 (function call) + 1
global FEE_PAYLOAD_SIZE: Field = 9;
// 2 * 5 (FUNCTION_CALL_SIZE) + 1
global FEE_PAYLOAD_SIZE: Field = 11;

// 2*97 + 32
global FEE_PAYLOAD_SIZE_IN_BYTES: Field = 226;
// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32
global FEE_PAYLOAD_SIZE_IN_BYTES: Field = 228;

global MAX_FEE_FUNCTION_CALLS = 2;

Expand Down Expand Up @@ -58,15 +58,15 @@ impl FeePayload {
call.target_address,
call.function_selector,
call.args_hash,
false,
call.is_static,
false
);
} else {
let _result = context.call_private_function_with_packed_args(
call.target_address,
call.function_selector,
call.args_hash,
false,
call.is_static,
false
);
}
Expand Down
12 changes: 7 additions & 5 deletions noir-projects/aztec-nr/authwit/src/entrypoint/function_call.nr
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize};

// 1 (ARGS_HASH) + 1 (FUNCTION_SELECTOR) + 1 (TARGET_ADDRESS) + 1 (IS_PUBLIC)
global FUNCTION_CALL_SIZE: Field = 4;
// 3 * 32 + 1
global FUNCTION_CALL_SIZE_IN_BYTES: Field = 97;
// 1 (ARGS_HASH) + 1 (FUNCTION_SELECTOR) + 1 (TARGET_ADDRESS) + 1 (IS_PUBLIC) + 1 (IS_STATIC)
global FUNCTION_CALL_SIZE: Field = 5;
// 3 * 32 + 2
global FUNCTION_CALL_SIZE_IN_BYTES: Field = 98;

struct FunctionCall {
args_hash: Field,
function_selector: FunctionSelector,
target_address: AztecAddress,
is_public: bool,
is_static: bool,
}

impl Serialize<FUNCTION_CALL_SIZE> for FunctionCall {
fn serialize(self) -> [Field; FUNCTION_CALL_SIZE] {
[self.args_hash, self.function_selector.to_field(), self.target_address.to_field(), self.is_public as Field]
[self.args_hash, self.function_selector.to_field(), self.target_address.to_field(), self.is_public as Field, self.is_static as Field]
}
}

Expand All @@ -34,6 +35,7 @@ impl FunctionCall {
bytes[i + 64] = target_address_bytes[i];
}
bytes[96] = self.is_public as u8;
bytes[97] = self.is_static as u8;
bytes
}
}
10 changes: 7 additions & 3 deletions noir-projects/aztec-nr/aztec/src/context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ mod private_context;
mod public_context;
mod avm_context;
mod interface;
mod call_interfaces;
mod gas;

use interface::{
ContextInterface, PrivateCallInterface, PublicCallInterface, PrivateVoidCallInterface,
PublicVoidCallInterface, AvmCallInterface, AvmVoidCallInterface
use interface::ContextInterface;
use call_interfaces::{
PrivateCallInterface, PrivateStaticCallInterface, PublicCallInterface, PublicStaticCallInterface,
PrivateVoidCallInterface, PrivateStaticVoidCallInterface, PublicVoidCallInterface,
PublicStaticVoidCallInterface, AvmCallInterface, AvmStaticCallInterface, AvmVoidCallInterface,
AvmStaticVoidCallInterface
};
use private_context::PrivateContext;
use private_context::PackedReturns;
Expand Down
Loading

0 comments on commit 22ad5a5

Please sign in to comment.