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

feat: #[derive(Packable)] #11531

Merged
merged 9 commits into from
Jan 29, 2025
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
6 changes: 4 additions & 2 deletions noir-projects/aztec-nr/address-note/src/address_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ use dep::aztec::{
},
oracle::random::random,
protocol_types::{
address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator, traits::Serialize,
address::AztecAddress,
constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator,
traits::{Packable, Serialize},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the files with notes now generally need to import Packable as because of the change in noir-projects/noir-protocol-circuits/crates/types/src/meta/mod.nr.

See comment in that file for details.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the serialize pr, it'd be good for derive to not require extra imports from the caller. We can either autoimport, or just use fully qualified paths in the derived impl.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,11 @@ use std::meta::derive;

// A Fixedsize Compressed String.
// Essentially a special version of Compressed String for practical use.
#[derive(Serialize, Deserialize)]
#[derive(Deserialize, Packable, Serialize)]
pub struct FieldCompressedString {
value: Field,
}

/// We implement the Packable trait for FieldCompressedString because it can be stored in contract's storage
/// (and there the implementation of Packable is required).
impl Packable<1> for FieldCompressedString {
fn pack(self) -> [Field; 1] {
self.serialize()
}

fn unpack(input: [Field; 1]) -> Self {
Self::deserialize(input)
}
}

impl FieldCompressedString {
pub fn is_eq(self, other: FieldCompressedString) -> bool {
self.value == other.value
Expand Down
6 changes: 4 additions & 2 deletions noir-projects/aztec-nr/uint-note/src/uint_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ use dep::aztec::{
oracle::random::random,
prelude::{NoteHeader, NullifiableNote, PrivateContext},
protocol_types::{
address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator, traits::Serialize,
address::AztecAddress,
constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator,
traits::{Packable, Serialize},
},
};

Expand Down
6 changes: 4 additions & 2 deletions noir-projects/aztec-nr/value-note/src/value_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ use dep::aztec::{
},
oracle::random::random,
protocol_types::{
address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator, traits::Serialize,
address::AztecAddress,
constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator,
traits::{Packable, Serialize},
},
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,12 @@
use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Packable, Serialize}};
use std::meta::derive;

global CONFIG_LENGTH: u32 = 3;

/// We store the tokens of the pool in a struct such that to load it from SharedImmutable asserts only a single
/// merkle proof.
/// (Once we actually do the optimization. WIP in https://github.com/AztecProtocol/aztec-packages/pull/8022).
#[derive(Serialize, Deserialize)]
#[derive(Deserialize, Packable, Serialize)]
pub struct Config {
pub token0: AztecAddress,
pub token1: AztecAddress,
pub liquidity_token: AztecAddress,
}

/// We implement the Packable trait for Config because it can be stored in contract's storage (and there
/// the implementation of Packable is required).
impl Packable<CONFIG_LENGTH> for Config {
fn pack(self: Self) -> [Field; CONFIG_LENGTH] {
self.serialize()
}

fn unpack(fields: [Field; CONFIG_LENGTH]) -> Self {
Self::deserialize(fields)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use dep::aztec::{
note::utils::compute_note_hash_for_nullify,
oracle::random::random,
prelude::{NoteHeader, NullifiableNote, PrivateContext},
protocol_types::{address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER},
protocol_types::{
address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, traits::Packable,
},
};

#[note]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,9 @@
use dep::aztec::{macros::aztec, protocol_types::traits::{Deserialize, Packable, Serialize}};

// I tried using #[derive(Serialize, Deserialize)] macro here but for whatever reason it fails to compile.
pub struct Note {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the note to a separate file because then the derivation works.

I find it quite weird to have the note defined in the same file as the contract.

Do we find this bug worthy of trying to fix?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, definitely

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a: Field,
b: Field,
}

impl Serialize<2> for Note {
fn serialize(self) -> [Field; 2] {
[self.a, self.b]
}
}

impl Deserialize<2> for Note {
fn deserialize(wire: [Field; 2]) -> Note {
Note { a: wire[0], b: wire[1] }
}
}

/// We implement the Packable trait for Note because it can be stored in contract's storage (and there
/// the implementation of Packable is required).
impl Packable<2> for Note {
fn pack(self) -> [Field; 2] {
self.serialize()
}

fn unpack(fields: [Field; 2]) -> Self {
Self::deserialize(fields)
}
}
mod note;
use dep::aztec::macros::aztec;

#[aztec]
contract AvmTest {
use crate::Note;
use crate::note::Note;

global big_field_128_bits: Field = 0x001234567890abcdef1234567890abcdef;
global big_field_136_bits: Field = 0x991234567890abcdef1234567890abcdef;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use dep::aztec::protocol_types::traits::{Deserialize, Packable, Serialize};
use std::meta::derive;

#[derive(Deserialize, Packable, Serialize)]
pub struct Note {
a: Field,
b: Field,
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::cards::Card;
use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Packable}};
use std::meta::derive;

global NUMBER_OF_PLAYERS: u32 = 2;
global NUMBER_OF_CARDS_DECK: u32 = 2;

#[derive(Deserialize, Eq)]
pub struct PlayerEntry {
address: AztecAddress,
deck_strength: u32,
Expand All @@ -16,28 +18,9 @@ impl PlayerEntry {
}
}

global PLAYER_SERIALIZED_LEN: u32 = 3;

impl Deserialize<PLAYER_SERIALIZED_LEN> for PlayerEntry {
fn deserialize(fields: [Field; PLAYER_SERIALIZED_LEN]) -> PlayerEntry {
let address = AztecAddress::from_field(fields[0]);
let deck_strength = fields[1] as u32;
let points = fields[2] as u64;

PlayerEntry { address, deck_strength, points }
}
}

impl Eq for PlayerEntry {
fn eq(self, other: PlayerEntry) -> bool {
self.address.eq(other.address)
& self.deck_strength.eq(other.deck_strength)
& self.points.eq(other.points)
}
}

global PLAYABLE_CARDS: u32 = 4;

#[derive(Packable)]
pub struct Game {
players: [PlayerEntry; NUMBER_OF_PLAYERS],
rounds_cards: [Card; PLAYABLE_CARDS],
Expand All @@ -48,52 +31,6 @@ pub struct Game {
current_round: u32,
}

global GAME_SERIALIZED_LEN: u32 = 15;

impl Packable<GAME_SERIALIZED_LEN> for Game {
fn pack(game: Game) -> [Field; GAME_SERIALIZED_LEN] {
[
game.players[0].address.to_field(),
game.players[0].deck_strength as Field,
game.players[0].points as Field,
game.players[1].address.to_field(),
game.players[1].deck_strength as Field,
game.players[1].points as Field,
game.rounds_cards[0].to_field(),
game.rounds_cards[1].to_field(),
game.rounds_cards[2].to_field(),
game.rounds_cards[3].to_field(),
game.started as Field,
game.finished as Field,
game.claimed as Field,
game.current_player as Field,
game.current_round as Field,
]
}

fn unpack(fields: [Field; GAME_SERIALIZED_LEN]) -> Game {
let player1 = PlayerEntry::deserialize([fields[0], fields[1], fields[2]]);
let player2 = PlayerEntry::deserialize([fields[3], fields[4], fields[5]]);

let players = [player1, player2];
let rounds_cards = [
Card::from_field(fields[6]),
Card::from_field(fields[7]),
Card::from_field(fields[8]),
Card::from_field(fields[9]),
];
Game {
players,
rounds_cards,
started: fields[10] as bool,
finished: fields[11] as bool,
claimed: fields[12] as bool,
current_player: fields[13] as u32,
current_round: fields[14] as u32,
}
}
}

impl Game {
pub fn add_player(&mut self, player_entry: PlayerEntry) -> bool {
let mut added = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use dep::aztec::{
macros::notes::note,
note::utils::compute_note_hash_for_nullify,
protocol_types::{
address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator, traits::Serialize,
address::AztecAddress,
constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator,
traits::{Packable, Serialize},
},
};
use dep::aztec::prelude::{NoteHeader, NullifiableNote, PrivateContext};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,9 @@
use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Packable, Serialize}};
use std::meta::derive;

// Shows how to create a custom struct in Public
#[derive(Deserialize, Packable, Serialize)]
pub struct Leader {
account: AztecAddress,
points: u8,
}

global LEADER_SERIALIZED_LEN: u32 = 2;

impl Deserialize<LEADER_SERIALIZED_LEN> for Leader {
fn deserialize(fields: [Field; LEADER_SERIALIZED_LEN]) -> Self {
Leader { account: AztecAddress::from_field(fields[0]), points: fields[1] as u8 }
}
}

impl Serialize<LEADER_SERIALIZED_LEN> for Leader {
fn serialize(self) -> [Field; LEADER_SERIALIZED_LEN] {
[self.account.to_field(), self.points as Field]
}
}

impl Packable<LEADER_SERIALIZED_LEN> for Leader {
fn pack(self) -> [Field; LEADER_SERIALIZED_LEN] {
self.serialize()
}

fn unpack(fields: [Field; LEADER_SERIALIZED_LEN]) -> Self {
Self::deserialize(fields)
}
}
29 changes: 2 additions & 27 deletions noir-projects/noir-contracts/contracts/fpc_contract/src/config.nr
Original file line number Diff line number Diff line change
@@ -1,33 +1,8 @@
use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Packable, Serialize}};
use std::meta::derive;

global CONFIG_LENGTH: u32 = 2;

#[derive(Deserialize, Packable, Serialize)]
pub struct Config {
pub accepted_asset: AztecAddress, // Asset the FPC accepts (denoted as AA below)
pub admin: AztecAddress, // Address to which AA is sent during the private fee payment flow
}

impl Serialize<CONFIG_LENGTH> for Config {
fn serialize(self: Self) -> [Field; CONFIG_LENGTH] {
[self.accepted_asset.to_field(), self.admin.to_field()]
}
}

impl Deserialize<CONFIG_LENGTH> for Config {
fn deserialize(fields: [Field; CONFIG_LENGTH]) -> Self {
Config {
accepted_asset: AztecAddress::from_field(fields[0]),
admin: AztecAddress::from_field(fields[1]),
}
}
}

impl Packable<CONFIG_LENGTH> for Config {
fn pack(self) -> [Field; CONFIG_LENGTH] {
self.serialize()
}

fn unpack(fields: [Field; CONFIG_LENGTH]) -> Self {
Self::deserialize(fields)
}
}
Original file line number Diff line number Diff line change
@@ -1,52 +1,18 @@
use dep::aztec::prelude::AztecAddress;
use dep::aztec::protocol_types::traits::{Deserialize, Packable, Serialize};
use dep::aztec::{prelude::AztecAddress, protocol_types::traits::{Deserialize, Packable, Serialize}};
use std::meta::derive;

// Struct to be used to represent "totals". Generally, there should be one per Asset.
// It stores the global values that are shared among all users, such as an accumulator
// and last time it was updated.
// In practice, it should also point to an oracle and have more fields related to
// loan to value ratios and other things, but we did not have enough reads/writes for this.
/// Struct to be used to represent "totals". Generally, there should be one per Asset.
/// It stores the global values that are shared among all users, such as an accumulator
/// and last time it was updated.
/// In practice, it should also point to an oracle and have more fields related to
/// loan to value ratios and other things, but we did not have enough reads/writes for this.
///
/// Note: Right now we are wasting so many writes. If changing last_updated_ts we will end
/// up rewriting all the values.
#[derive(Deserialize, Packable, Serialize)]
pub struct Asset {
interest_accumulator: U128,
last_updated_ts: u64,
loan_to_value: U128,
oracle: AztecAddress,
}

global SERIALIZED_LEN: u32 = 6;

impl Serialize<SERIALIZED_LEN> for Asset {
fn serialize(Asset: Asset) -> [Field; SERIALIZED_LEN] {
[
Asset.interest_accumulator.lo,
Asset.interest_accumulator.hi,
Asset.last_updated_ts as Field,
Asset.loan_to_value.lo,
Asset.loan_to_value.hi,
Asset.oracle.to_field(),
]
}
}

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.
benesjan marked this conversation as resolved.
Show resolved Hide resolved
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]);

Asset { interest_accumulator, last_updated_ts, loan_to_value, oracle }
}
}

impl Packable<SERIALIZED_LEN> for Asset {
fn pack(self) -> [Field; SERIALIZED_LEN] {
self.serialize()
}

fn unpack(fields: [Field; SERIALIZED_LEN]) -> Self {
Self::deserialize(fields)
}
}
Loading
Loading