Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Revert): "refactor: purge unconstrained functions where possible" #5911

Merged
merged 2 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading