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: using #[derive(Serialize)] more #11541

Merged
merged 5 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
28 changes: 9 additions & 19 deletions noir-projects/aztec-nr/authwit/src/entrypoint/app.nr
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
use dep::aztec::prelude::PrivateContext;
use dep::aztec::protocol_types::{
constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD,
hash::poseidon2_hash_with_separator,
traits::{Hash, Serialize},
use dep::aztec::{
prelude::PrivateContext,
protocol_types::{
constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD,
hash::poseidon2_hash_with_separator,
traits::{Hash, Serialize},
},
};
use std::meta::derive;

use crate::entrypoint::function_call::FunctionCall;

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

global ACCOUNT_MAX_CALLS: u32 = 4;

// Note: If you change the following struct you have to update default_entrypoint.ts
// docs:start:app-payload-struct
#[derive(Serialize)]
pub struct AppPayload {
function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],
nonce: Field,
}
// docs:end:app-payload-struct

impl Serialize<APP_PAYLOAD_SIZE> for AppPayload {
// Serializes the entrypoint struct
fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {
let mut fields: BoundedVec<Field, APP_PAYLOAD_SIZE> = BoundedVec::new();
for call in self.function_calls {
fields.extend_from_array(call.serialize());
}
fields.push(self.nonce);
fields.storage()
}
}

impl Hash for AppPayload {
fn hash(self) -> Field {
poseidon2_hash_with_separator(self.serialize(), GENERATOR_INDEX__SIGNATURE_PAYLOAD)
Expand Down
30 changes: 9 additions & 21 deletions noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr
Original file line number Diff line number Diff line change
@@ -1,40 +1,28 @@
use crate::entrypoint::function_call::FunctionCall;
use dep::aztec::prelude::PrivateContext;
use dep::aztec::protocol_types::{
constants::GENERATOR_INDEX__FEE_PAYLOAD,
hash::poseidon2_hash_with_separator,
traits::{Hash, Serialize},
use dep::aztec::{
prelude::PrivateContext,
protocol_types::{
constants::GENERATOR_INDEX__FEE_PAYLOAD,
hash::poseidon2_hash_with_separator,
traits::{Hash, Serialize},
},
};

// 2 * 5 (FUNCTION_CALL_SIZE) + 2
global FEE_PAYLOAD_SIZE: u32 = 12;
use std::meta::derive;

// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32
global FEE_PAYLOAD_SIZE_IN_BYTES: u32 = 228;

global MAX_FEE_FUNCTION_CALLS: u32 = 2;

// docs:start:fee-payload-struct
#[derive(Serialize)]
pub struct FeePayload {
function_calls: [FunctionCall; MAX_FEE_FUNCTION_CALLS],
nonce: Field,
is_fee_payer: bool,
}
// docs:end:fee-payload-struct

impl Serialize<FEE_PAYLOAD_SIZE> for FeePayload {
// Serializes the entrypoint struct
fn serialize(self) -> [Field; FEE_PAYLOAD_SIZE] {
let mut fields: BoundedVec<Field, FEE_PAYLOAD_SIZE> = BoundedVec::new();
for i in 0..MAX_FEE_FUNCTION_CALLS {
fields.extend_from_array(self.function_calls[i].serialize());
}
fields.push(self.nonce);
fields.push(self.is_fee_payer as Field);
fields.storage()
}
}

impl Hash for FeePayload {
fn hash(self) -> Field {
poseidon2_hash_with_separator(self.serialize(), GENERATOR_INDEX__FEE_PAYLOAD)
Expand Down
16 changes: 2 additions & 14 deletions noir-projects/aztec-nr/authwit/src/entrypoint/function_call.nr
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use dep::aztec::protocol_types::{
abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize,
};
use std::meta::derive;

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

#[derive(Serialize)]
pub struct FunctionCall {
pub args_hash: Field,
pub function_selector: FunctionSelector,
Expand All @@ -15,18 +15,6 @@ pub struct FunctionCall {
pub 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.is_static as Field,
]
}
}

impl FunctionCall {
fn to_be_bytes(self) -> [u8; FUNCTION_CALL_SIZE_IN_BYTES] {
let mut bytes: [u8; FUNCTION_CALL_SIZE_IN_BYTES] = [0; FUNCTION_CALL_SIZE_IN_BYTES];
Expand Down
30 changes: 2 additions & 28 deletions noir-projects/aztec-nr/aztec/src/note/note_header.nr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use dep::protocol_types::{address::AztecAddress, traits::{Empty, Serialize}};
use std::meta::derive;

global NOTE_HEADER_LENGTH: u32 = 4;

#[derive(Eq, Serialize)]
pub struct NoteHeader {
pub contract_address: AztecAddress,
pub nonce: Field,
Expand All @@ -20,34 +20,8 @@ impl Empty for NoteHeader {
}
}

impl Eq for NoteHeader {
fn eq(self, other: Self) -> bool {
(self.contract_address == other.contract_address)
& (self.nonce == other.nonce)
& (self.storage_slot == other.storage_slot)
& (self.note_hash_counter == other.note_hash_counter)
}
}

impl NoteHeader {
pub fn new(contract_address: AztecAddress, nonce: Field, storage_slot: Field) -> Self {
NoteHeader { contract_address, nonce, storage_slot, note_hash_counter: 0 }
}
}

impl Serialize<NOTE_HEADER_LENGTH> for NoteHeader {
/// The following method is used by implementations of the Serialize trait for notes --> the implementation
// of the Serialize trait for notes needs to be implemented when the note is passed as an argument to a contract
// function --> in that situation the serialize method is called by aztec-nr when computing an arguments hash.
fn serialize(self) -> [Field; NOTE_HEADER_LENGTH] {
// Note: If you change this function don't forget to update implementations of Serialize trait for notes.
// (Serialize trait needs to be implemented for a note when it's passed as an argument to a contract function
// --> then it's used when computing args hash.)
[
self.contract_address.to_field(),
self.nonce,
self.storage_slot,
self.note_hash_counter as Field,
]
}
}
37 changes: 7 additions & 30 deletions noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use dep::protocol_types::{
address::AztecAddress,
contract_instance::ContractInstance,
public_keys::{PUBLIC_KEYS_LENGTH, PublicKeys},
public_keys::PublicKeys,
traits::{Deserialize, Serialize},
};
use std::meta::derive;

// The following 2 lines have been added here because derivation of Serialize and Deserialize does not handle imports
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we want to spend time on tackling this or too low of a priority?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, it's good to tackle this. Very annoying that derive causes errors due to missing imports for things that are invisibly used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree, will try to tackle it today

use dep::protocol_types::public_keys::{IvpkM, NpkM, OvpkM, TpkM};
use std::embedded_curve_ops::EmbeddedCurvePoint;

use crate::context::call_interfaces::CallInterface;
use crate::context::{PrivateContext, PublicContext};
Expand Down Expand Up @@ -114,36 +119,8 @@ impl<let N: u32, let M: u32> Deployer<N, M> {
}
}

// Keys length + address
global TEST_ACCOUNT_LENGTH: u32 = PUBLIC_KEYS_LENGTH + 1;

#[derive(Deserialize, Serialize)]
pub struct TestAccount {
pub address: AztecAddress,
pub keys: PublicKeys,
}

impl Serialize<TEST_ACCOUNT_LENGTH> for TestAccount {
fn serialize(self) -> [Field; TEST_ACCOUNT_LENGTH] {
let mut output = [0; TEST_ACCOUNT_LENGTH];

output[0] = self.address.to_field();

for i in 0..PUBLIC_KEYS_LENGTH {
output[i + 1] = self.keys.serialize()[i];
}
output
}
}

impl Deserialize<TEST_ACCOUNT_LENGTH> for TestAccount {
fn deserialize(input: [Field; TEST_ACCOUNT_LENGTH]) -> Self {
let address = AztecAddress::from_field(input[0]);
let mut key_buffer = [0; PUBLIC_KEYS_LENGTH];
for i in 0..PUBLIC_KEYS_LENGTH {
key_buffer[i] = input[i + 1];
}
let keys = PublicKeys::deserialize(key_buffer);

Self { address, keys }
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
use dep::aztec::prelude::{AztecAddress, PrivateContext};
use dep::aztec::protocol_types::{
constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD,
hash::poseidon2_hash_with_separator,
traits::{Hash, Serialize},
use dep::aztec::{
prelude::{AztecAddress, PrivateContext},
protocol_types::{
constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD,
hash::poseidon2_hash_with_separator,
traits::{Hash, Serialize},
},
};
use std::meta::derive;

use dep::authwit::entrypoint::function_call::FunctionCall;

global DAPP_MAX_CALLS: u32 = 1;
// FUNCTION_CALL_SIZE * DAPP_MAX_CALLS + 1
global DAPP_PAYLOAD_SIZE: u32 = 6;
// FUNCTION_CALL_SIZE_IN_BYTES * DAPP_MAX_CALLS + 32
global DAPP_PAYLOAD_SIZE_IN_BYTES: u32 = 130;

// Note: If you change the following struct you have to update default_entrypoint.ts
// docs:start:app-payload-struct
#[derive(Serialize)]
pub struct DAppPayload {
function_calls: [FunctionCall; DAPP_MAX_CALLS],
nonce: Field,
}
// docs:end:app-payload-struct

impl Serialize<DAPP_PAYLOAD_SIZE> for DAppPayload {
// Serializes the entrypoint struct
fn serialize(self) -> [Field; DAPP_PAYLOAD_SIZE] {
let mut fields: BoundedVec<Field, DAPP_PAYLOAD_SIZE> = BoundedVec::new();
for call in self.function_calls {
fields.extend_from_array(call.serialize());
}
fields.push(self.nonce);
fields.storage()
}
}

impl Hash for DAppPayload {
fn hash(self) -> Field {
poseidon2_hash_with_separator(self.serialize(), GENERATOR_INDEX__SIGNATURE_PAYLOAD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use dep::aztec::{
state_vars::PrivateSet,
};
use dep::value_note::value_note::ValueNote;
use std::meta::derive;

#[derive(Serialize)]
pub struct Card {
// We use u32s since u16s are unsupported
strength: u32,
Expand All @@ -35,12 +37,6 @@ impl ToField for Card {
}
}

impl Serialize<2> for Card {
fn serialize(self) -> [Field; 2] {
[self.strength as Field, self.points as Field]
}
}

// docs:start:pure_noir_testing
#[test]
fn test_to_from_field() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use dep::aztec::protocol_types::{
MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE,
},
contract_class_id::ContractClassId,
traits::Serialize,
};

pub struct ContractClassRegistered {
Expand All @@ -14,9 +13,12 @@ pub struct ContractClassRegistered {
packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS],
}

impl Serialize<MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5> for ContractClassRegistered {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No longer using the Serialize trait here as it did not use intrinsic Noir serialization.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yea this seems to be some event serialization given how they are adding the magic value at the beginning. We'll likely eventually replace this with packed + some event handling that adds a selector

fn serialize(self: Self) -> [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5] {
impl ContractClassRegistered {
fn serialize_non_standard(
self: Self,
) -> [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5] {
let mut packed = [0; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5];
// Since we are not yet emitting selectors we'll use this magic value to identify events emitted by the ClassRegisterer.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copied this comment from constants.nr since I had no idea WTF is this.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's fine, it likely alludes to 'event emission' not really being a thing yet, and event selectors not being a formal concept.

packed[0] = REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE;
packed[1] = self.contract_class_id.to_field();
packed[2] = self.version;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,23 @@ use dep::aztec::protocol_types::{
contract_class_id::ContractClassId,
traits::Serialize,
};
use std::meta::derive;

#[derive(Serialize)]
pub struct InnerPrivateFunction {
selector: FunctionSelector,
metadata_hash: Field,
vk_hash: Field,
}

impl Serialize<3> for InnerPrivateFunction {
fn serialize(self: Self) -> [Field; 3] {
[self.selector.to_field(), self.metadata_hash, self.vk_hash]
}
}

#[derive(Serialize)]
pub struct PrivateFunction {
selector: FunctionSelector,
metadata_hash: Field,
vk_hash: Field,
bytecode: [Field; MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS],
}

impl Serialize<MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS + 3> for PrivateFunction {
fn serialize(
self: Self,
) -> [Field; MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS + 3] {
let mut packed = [0; MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS + 3];
packed[0] = self.selector.to_field();
packed[1] = self.metadata_hash;
packed[2] = self.vk_hash;
for i in 0..MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS {
packed[i + 3] = self.bytecode[i];
}
packed
}
}

// #[event]
pub struct ClassPrivateFunctionBroadcasted {
contract_class_id: ContractClassId,
Expand All @@ -56,14 +38,15 @@ pub struct ClassPrivateFunctionBroadcasted {
function: PrivateFunction,
}

impl Serialize<MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS + REGISTERER_PRIVATE_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS> for ClassPrivateFunctionBroadcasted {
fn serialize(
impl ClassPrivateFunctionBroadcasted {
fn serialize_non_standard(
self: Self,
) -> [Field; MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS + REGISTERER_PRIVATE_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS] {
let mut packed = [
0; MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS
+ REGISTERER_PRIVATE_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS
];
// Since we are not yet emitting selectors we'll use this magic value to identify events emitted by the ClassRegisterer.
packed[0] = REGISTERER_PRIVATE_FUNCTION_BROADCASTED_MAGIC_VALUE;
packed[1] = self.contract_class_id.to_field();
packed[2] = self.artifact_metadata_hash;
Expand Down
Loading