Skip to content

Commit

Permalink
fix(Revert): "refactor: purge unconstrained functions where possible" (
Browse files Browse the repository at this point in the history
…#5911)

Reverts #5819. The use of constrained
functions made the writing of tests etc nicer, but the testing time
absolutely exploded as an effect 💀

Co-authored-by: ludamad <[email protected]>
  • Loading branch information
LHerskind and ludamad authored Apr 22, 2024
1 parent 2e55713 commit c36246b
Show file tree
Hide file tree
Showing 18 changed files with 250 additions and 112 deletions.
1 change: 1 addition & 0 deletions noir-projects/noir-contracts/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ members = [
"contracts/token_blacklist_contract",
"contracts/token_bridge_contract",
"contracts/uniswap_contract",
"contracts/reader_contract",
"contracts/multi_call_entrypoint_contract",
]
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ contract AvmTest {
/************************************************************************
* Storage
************************************************************************/
unconstrained fn view_storage_single() -> pub Field {
storage.single.read()
}

unconstrained fn view_storage_list() -> pub [Field; 2] {
storage.list.read().serialize()
}

unconstrained fn view_storage_map(address: AztecAddress) -> pub u32 {
storage.map.at(address).read()
}

#[aztec(public-vm)]
fn set_storage_single(a: Field) {
storage.single.write(a);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ contract GasToken {
rebate.to_field()
}

#[aztec(public)]
fn balance_of_public(owner: AztecAddress) -> pub Field {
// utility function for testing
unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field {
storage.balances.at(owner).read().to_field()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,14 @@ struct Asset {
oracle: AztecAddress,
}

global SERIALIZED_LEN: Field = 6;
global SERIALIZED_LEN: Field = 4;

impl Serialize<SERIALIZED_LEN> for Asset {
fn serialize(Asset: Asset) -> [Field; SERIALIZED_LEN] {
[
Asset.interest_accumulator.lo as Field,
Asset.interest_accumulator.hi as Field,
Asset.interest_accumulator.to_integer(),
Asset.last_updated_ts as Field,
Asset.loan_to_value.lo as Field,
Asset.loan_to_value.hi as Field,
Asset.loan_to_value.to_integer(),
Asset.oracle.to_field()
]
}
Expand All @@ -32,10 +30,10 @@ impl Deserialize<SERIALIZED_LEN> for Asset {
// Right now we are wasting so many writes. If changing last_updated_ts
// we will end up rewriting all of them, wasting writes.
fn deserialize(fields: [Field; SERIALIZED_LEN]) -> Asset {
let interest_accumulator = U128 {lo: fields[0], hi: fields[1]};
let last_updated_ts = fields[2] as u64;
let loan_to_value = U128 {lo: fields[3], hi: fields[4]};
let oracle = AztecAddress::from_field(fields[5]);
let interest_accumulator = U128::from_integer(fields[0]);
let last_updated_ts = fields[1] as u64;
let loan_to_value = U128::from_integer(fields[2]);
let oracle = AztecAddress::from_field(fields[3]);

Asset {
interest_accumulator,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
mod asset;
mod position;
mod interest_math;
mod helpers;

Expand All @@ -15,7 +14,6 @@ contract Lending {
use dep::aztec::context::{PublicContext, Context, gas::GasOpts};

use crate::asset::Asset;
use crate::position::Position;
use crate::interest_math::compute_multiplier;
use crate::helpers::{covered_by_collateral, DebtReturn, debt_updates, debt_value, compute_identifier};
use dep::token::Token;
Expand All @@ -31,6 +29,12 @@ contract Lending {
static_debt: Map<AztecAddress, PublicMutable<Field>>, // abusing keys very heavily
}

struct Position {
collateral: Field,
static_debt: Field,
debt: Field,
}

// Constructs the contract.
#[aztec(private)]
#[aztec(initializer)]
Expand Down Expand Up @@ -261,13 +265,11 @@ contract Lending {
storage.static_debt.at(owner).write(debt_returns.static_debt.to_integer());
}

#[aztec(public)]
fn get_asset(asset_id: Field) -> pub Asset {
unconstrained fn get_asset(asset_id: Field) -> pub Asset {
storage.assets.at(asset_id).read()
}

#[aztec(public)]
fn get_position(owner: AztecAddress) -> pub Position {
unconstrained fn get_position(owner: AztecAddress) -> pub Position {
let collateral = storage.collateral.at(owner).read();
let static_debt = storage.static_debt.at(owner).read();
let asset: Asset = storage.assets.at(0).read();
Expand All @@ -278,8 +280,7 @@ contract Lending {
Position { collateral, static_debt, debt }
}

#[aztec(public)]
fn get_assets() -> pub [AztecAddress; 2] {
unconstrained fn get_assets() -> pub [AztecAddress; 2] {
[storage.collateral_asset.read(), storage.stable_coin.read()]
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ global ASSET_SERIALIZED_LEN: Field = 1;

impl Serialize<ASSET_SERIALIZED_LEN> for Asset {
fn serialize(asset: Asset) -> [Field; ASSET_SERIALIZED_LEN] {
[asset.price.to_field()]
[asset.price.to_integer()]
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ contract PriceFeed {
fn get_price(asset_id: Field) -> Asset {
storage.assets.at(asset_id).read()
}

unconstrained fn fetch_price(asset_id: Field) -> pub Asset {
storage.assets.at(asset_id).read()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "reader_contract"
authors = [""]
compiler_version = ">=0.25.0"
type = "contract"

[dependencies]
aztec = { path = "../../../aztec-nr/aztec" }
compressed_string = { path = "../../../aztec-nr/compressed-string" }
69 changes: 69 additions & 0 deletions noir-projects/noir-contracts/contracts/reader_contract/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
contract Reader {
use dep::aztec::prelude::{AztecAddress, FunctionSelector, Deserialize};

use dep::compressed_string::FieldCompressedString;

#[aztec(private)]
fn constructor() {}

#[aztec(public)]
fn check_name_public(who: AztecAddress, what: str<31>) {
let selector = FunctionSelector::from_signature("public_get_name()");
let name: FieldCompressedString = context.call_public_function_no_args(who, selector).deserialize_into();
let _what = FieldCompressedString::from_string(what);
assert(name.is_eq(_what));
}

#[aztec(private)]
fn check_name_private(who: AztecAddress, what: str<31>) {
let selector = FunctionSelector::from_signature("private_get_name()");
let name: FieldCompressedString = context.call_private_function_no_args(who, selector).unpack_into();
let _what = FieldCompressedString::from_string(what);
assert(name.is_eq(_what));
}

unconstrained fn get_name(who: AztecAddress) -> pub str<6> {
// We cannot yet call an unconstrained function from another
"Reader"
}

#[aztec(public)]
fn check_symbol_public(who: AztecAddress, what: str<31>) {
let selector = FunctionSelector::from_signature("public_get_symbol()");
let symbol: FieldCompressedString = context.call_public_function_no_args(who, selector).deserialize_into();
let _what = FieldCompressedString::from_string(what);
assert(symbol.is_eq(_what));
}

#[aztec(private)]
fn check_symbol_private(who: AztecAddress, what: str<31>) {
let selector = FunctionSelector::from_signature("private_get_symbol()");
let symbol: FieldCompressedString = context.call_private_function_no_args(who, selector).unpack_into();
let _what = FieldCompressedString::from_string(what);
assert(symbol.is_eq(_what));
}

unconstrained fn get_symbol(who: AztecAddress) -> pub str<3> {
// We cannot yet call an unconstrained function from another
"RDR"
}

#[aztec(public)]
fn check_decimals_public(who: AztecAddress, what: u8) {
let selector = FunctionSelector::from_signature("public_get_decimals()");
let ret: u8 = context.call_public_function_no_args(who, selector).deserialize_into();
assert(ret == what);
}

#[aztec(private)]
fn check_decimals_private(who: AztecAddress, what: u8) {
let selector = FunctionSelector::from_signature("private_get_decimals()");
let result: u8 = context.call_private_function_no_args(who, selector).unpack_into();
assert(result == what);
}

unconstrained fn get_decimals(who: AztecAddress) -> pub u8 {
// We cannot yet call an unconstrained function from another
18
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ contract StatefulTest {
balance_utils::get_balance(owner_balance)
}

#[aztec(public)]
fn get_public_value(owner: AztecAddress) -> pub Field {
unconstrained fn get_public_value(owner: AztecAddress) -> pub Field {
storage.public_values.at(owner).read()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,6 @@ contract TokenBlacklist {
slow_update: SharedImmutable<AztecAddress>,
}

#[aztec(public)]
fn total_supply() -> pub Field {
storage.total_supply.read().to_field()
}

#[aztec(public)]
fn balance_of_public(owner: AztecAddress) -> pub Field {
storage.public_balances.at(owner).read().to_field()
}

// docs:start:constructor
#[aztec(public)]
#[aztec(initializer)]
Expand Down Expand Up @@ -237,7 +227,8 @@ contract TokenBlacklist {

storage.balances.sub(from, U128::from_integer(amount));

TokenBlacklist::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context);
let selector = FunctionSelector::from_signature("_increase_public_balance((Field),Field)");
context.call_public_function(context.this_address(), selector, [to.to_field(), amount]);
}

// docs:start:transfer_private
Expand Down Expand Up @@ -275,7 +266,8 @@ contract TokenBlacklist {

storage.balances.sub(from, U128::from_integer(amount));

TokenBlacklist::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context);
let selector = FunctionSelector::from_signature("_reduce_total_supply(Field)");
context.call_public_function(context.this_address(), selector, [amount]);
}

/// Internal ///
Expand All @@ -297,7 +289,15 @@ contract TokenBlacklist {

/// Unconstrained ///
unconstrained fn total_supply() -> pub Field {
storage.total_supply.read().to_field()
}

unconstrained fn balance_of_private(owner: AztecAddress) -> pub Field {
storage.balances.balance_of(owner).to_field()
}

unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field {
storage.public_balances.at(owner).read().to_field()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ contract TokenBridge {
#[aztec(private)]
#[aztec(initializer)]
fn constructor(token: AztecAddress) {
TokenBridge::at(context.this_address())._initialize(token).enqueue(&mut context);
let selector = FunctionSelector::from_signature("_initialize((Field))");
context.call_public_function(context.this_address(), selector, [token.to_field()]);
}
// docs:end:token_bridge_storage_and_constructor

Expand Down Expand Up @@ -98,7 +99,11 @@ contract TokenBridge {
// `mint_private` on token is public. So we call an internal public function
// which then calls the public method on the token contract.
// Since the secret_hash is passed, no secret is leaked.
TokenBridge::at(context.this_address())._call_mint_on_token(amount, secret_hash_for_redeeming_minted_notes).enqueue(&mut context);
context.call_public_function(
context.this_address(),
FunctionSelector::from_signature("_call_mint_on_token(Field,Field)"),
[amount, secret_hash_for_redeeming_minted_notes]
);
}
// docs:end:claim_private

Expand All @@ -119,19 +124,31 @@ contract TokenBridge {

// docs:start:call_assert_token_is_same
// Assert that user provided token address is same as seen in storage.
TokenBridge::at(context.this_address())._assert_token_is_same(token).enqueue(&mut context);
context.call_public_function(
context.this_address(),
FunctionSelector::from_signature("_assert_token_is_same((Field))"),
[token.to_field()]
);
// docs:end:call_assert_token_is_same

// Burn tokens
Token::at(token).burn(context.msg_sender(), amount, nonce).call(&mut context);
}
/// docs:end:exit_to_l1_private
// docs:start:read_token
// View function that is callable by other contracts.
// Unconstrained can't be called by others since it isn't safe.
#[aztec(public)]
fn get_token() -> AztecAddress {
storage.token.read()
}

// /// Unconstrained ///

// docs:start:read_token
unconstrained fn token() -> pub AztecAddress {
storage.token.read()
}
// docs:end:read_token

#[aztec(public)]
Expand Down
Loading

0 comments on commit c36246b

Please sign in to comment.