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

refactor: implementing deserialize() in Noir structs #4384

Merged
merged 8 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
67 changes: 6 additions & 61 deletions yarn-project/aztec-nr/aztec/src/context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -311,51 +311,8 @@ impl PrivateContext {

let item = PrivateCallStackItem {
contract_address: AztecAddress::from_field(reader.read()),
function_data: FunctionData {
selector: FunctionSelector::from_field(reader.read()),
is_internal: reader.read() as bool,
is_private: reader.read() as bool,
is_constructor: reader.read() as bool,
},
public_inputs: PrivateCircuitPublicInputs {
call_context: CallContext {
msg_sender : AztecAddress::from_field(reader.read()),
storage_contract_address : AztecAddress::from_field(reader.read()),
portal_contract_address : EthAddress::from_field(reader.read()),
function_selector: FunctionSelector::from_field(reader.read()), // practically same as fields[1]
is_delegate_call : reader.read() as bool,
is_static_call : reader.read() as bool,
is_contract_deployment: reader.read() as bool,
start_side_effect_counter: reader.read() as u32,
},
args_hash: reader.read(),
return_values: reader.read_array([0; RETURN_VALUES_LENGTH]), // +1
read_requests: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_READ_REQUESTS_PER_CALL]),
nullifier_key_validation_requests: reader.read_struct_array(NullifierKeyValidationRequest::deserialize, [NullifierKeyValidationRequest::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL]),
new_commitments: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_NEW_COMMITMENTS_PER_CALL]),
new_nullifiers: reader.read_struct_array(SideEffectLinkedToNoteHash::deserialize, [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),
private_call_stack_hashes: reader.read_array([0; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),
public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),
new_l2_to_l1_msgs: reader.read_array([0; MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),
end_side_effect_counter: reader.read() as u32,
encrypted_logs_hash: reader.read_array([0; NUM_FIELDS_PER_SHA256]),
unencrypted_logs_hash: reader.read_array([0; NUM_FIELDS_PER_SHA256]),
encrypted_log_preimages_length: reader.read(),
unencrypted_log_preimages_length: reader.read(),
historical_header: reader.read_struct(Header::deserialize),
contract_deployment_data: ContractDeploymentData {
public_key: GrumpkinPoint {
x: reader.read(),
y: reader.read()
},
initialization_hash : reader.read(),
contract_class_id : ContractClassId::from_field(reader.read()),
contract_address_salt : reader.read(),
portal_contract_address : EthAddress::from_field(reader.read()),
},
chain_id: reader.read(),
version: reader.read(),
},
function_data: reader.read_struct(FunctionData::deserialize),
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks sleek 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will make it even sleeker once I update the PrivateCallStackItem with deserialize 😊

public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),
is_execution_request: reader.read() as bool,
};

Expand Down Expand Up @@ -420,25 +377,13 @@ impl PrivateContext {

let mut reader = Reader::new(fields);

// Note: Not using PublicCirclePublicInputs::deserialize here, because everything bellow args_hash is 0 and
benesjan marked this conversation as resolved.
Show resolved Hide resolved
// there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!
let item = PublicCallStackItem {
contract_address: AztecAddress::from_field(reader.read()),
function_data: FunctionData {
selector: FunctionSelector::from_field(reader.read()),
is_internal: reader.read() as bool,
is_private: reader.read() as bool,
is_constructor: reader.read() as bool,
},
function_data: reader.read_struct(FunctionData::deserialize),
public_inputs: PublicCircuitPublicInputs {
call_context: CallContext {
msg_sender : AztecAddress::from_field(reader.read()),
storage_contract_address : AztecAddress::from_field(reader.read()),
portal_contract_address : EthAddress::from_field(reader.read()),
function_selector: FunctionSelector::from_field(reader.read()), // practically same as fields[1]
is_delegate_call : reader.read() as bool,
is_static_call : reader.read() as bool,
is_contract_deployment: reader.read() as bool,
start_side_effect_counter: reader.read() as u32,
},
call_context: reader.read_struct(CallContext::deserialize),
args_hash: reader.read(),
return_values: [0; RETURN_VALUES_LENGTH],
contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/aztec-nr/aztec/src/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {
rhs.lt(lhs)
}

// TODO(benesjan): also in circuits. NUKE THIS!
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a copy from aztec-nr. I will nuke the version in aztec-nr once I implement deserialize for callstack items as well which I didn't do in this PR because I already had #4381 open with a lot of changes there.

struct Reader<N> {
data: [Field; N],
offset: Field,
Expand All @@ -41,6 +42,7 @@ impl<N> Reader<N> {
result
}

// TODO(#4394)
pub fn read_struct<T, K>(&mut self, deserialise: fn([Field; K]) -> T) -> T {
let result = deserialise(self.read_array([0; K]));
result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ use crate::{
GENERATOR_INDEX__CALL_CONTEXT,
},
hash::pedersen_hash,
traits::{
Deserialize,
Hash,
Serialize,
},
};
use dep::std::cmp::Eq;
use crate::traits::{Hash, Serialize};

// docs:start:call-context
struct CallContext {
Expand Down Expand Up @@ -75,6 +79,21 @@ impl Serialize<CALL_CONTEXT_LENGTH> for CallContext {
}
}

impl Deserialize<CALL_CONTEXT_LENGTH> for CallContext {
fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {
CallContext {
msg_sender: AztecAddress::from_field(serialized[0]),
storage_contract_address: AztecAddress::from_field(serialized[1]),
portal_contract_address: EthAddress::from_field(serialized[2]),
function_selector: FunctionSelector::from_field(serialized[3]),
is_delegate_call: serialized[4] as bool,
is_static_call: serialized[5] as bool,
is_contract_deployment: serialized[6] as bool,
start_side_effect_counter: serialized[7] as u32,
}
}
}

#[test]
fn serialization_smoke() {
let context: CallContext = dep::std::unsafe::zeroed();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
use crate::abis::function_selector::FunctionSelector;
use crate::constants::GENERATOR_INDEX__FUNCTION_DATA;
use crate::{
abis::function_selector::FunctionSelector,
constants::{
GENERATOR_INDEX__FUNCTION_DATA,
FUNCTION_DATA_LENGTH,
},
hash::pedersen_hash,
traits::{
Serialize,
Hash,
Deserialize,
},
};

struct FunctionData {
// First four bytes of the abi encoding
Expand All @@ -10,16 +21,33 @@ struct FunctionData {
is_constructor : bool,
}

impl FunctionData {
impl Hash for FunctionData {
fn hash(self) -> Field {
pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)
}
}

impl Serialize<FUNCTION_DATA_LENGTH> for FunctionData {
// A field is ~256 bits
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,
// This method will simply return a bit packed Field instead of hashing
fn hash(self) -> Field {
dep::std::hash::pedersen_hash_with_separator([
fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {
[
self.selector.to_field(),
self.is_internal as Field,
self.is_private as Field,
self.is_constructor as Field,
], GENERATOR_INDEX__FUNCTION_DATA)
]
}
}

impl Deserialize<FUNCTION_DATA_LENGTH> for FunctionData {
fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {
Self {
selector: FunctionSelector::from_field(serialized[0]),
is_internal: serialized[1] as bool,
is_private: serialized[2] as bool,
is_constructor: serialized[3] as bool,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ use crate::{
abis::{
call_context::CallContext,
nullifier_key_validation_request::NullifierKeyValidationRequest,
side_effect::{SideEffect, SideEffectLinkedToNoteHash},
side_effect::{
SideEffect,
SideEffectLinkedToNoteHash,
},
},
contrakt::deployment_data::ContractDeploymentData,
hash::pedersen_hash,
header::Header,
};
use crate::constants::{
constants::{
MAX_READ_REQUESTS_PER_CALL,
MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL,
MAX_NEW_COMMITMENTS_PER_CALL,
Expand All @@ -20,8 +19,17 @@ use crate::constants::{
RETURN_VALUES_LENGTH,
PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,
GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS,
},
contrakt::deployment_data::ContractDeploymentData,
header::Header,
hash::pedersen_hash,
traits::{
Deserialize,
Hash,
Serialize,
},
utils::reader::Reader,
};
use crate::traits::{Hash, Serialize};

struct PrivateCircuitPublicInputs {
call_context: CallContext,
Expand Down Expand Up @@ -97,6 +105,37 @@ impl Serialize<PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH> for PrivateCircuitPublicInp
}
}

impl Deserialize<PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH> for PrivateCircuitPublicInputs {
fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {
// TODO(#4390): This should accept a reader ^ to avoid copying data.
let mut reader = Reader::new(serialized);
let inputs = Self {
call_context: reader.read_struct(CallContext::deserialize),
args_hash: reader.read(),
return_values: reader.read_array([0; RETURN_VALUES_LENGTH]),
read_requests: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_READ_REQUESTS_PER_CALL]),
nullifier_key_validation_requests: reader.read_struct_array(NullifierKeyValidationRequest::deserialize, [NullifierKeyValidationRequest::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL]),
new_commitments: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_NEW_COMMITMENTS_PER_CALL]),
new_nullifiers: reader.read_struct_array(SideEffectLinkedToNoteHash::deserialize, [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),
private_call_stack_hashes: reader.read_array([0; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),
public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),
new_l2_to_l1_msgs: reader.read_array([0; MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),
end_side_effect_counter: reader.read() as u32,
encrypted_logs_hash: reader.read_array([0; NUM_FIELDS_PER_SHA256]),
unencrypted_logs_hash: reader.read_array([0; NUM_FIELDS_PER_SHA256]),
encrypted_log_preimages_length: reader.read(),
unencrypted_log_preimages_length: reader.read(),
historical_header: reader.read_struct(Header::deserialize),
contract_deployment_data: reader.read_struct(ContractDeploymentData::deserialize),
chain_id: reader.read(),
version: reader.read(),
};

reader.finish();
inputs
}
}

impl Hash for PrivateCircuitPublicInputs {
fn hash(self) -> Field {
pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
use crate::constants::{
MAX_NEW_L2_TO_L1_MSGS_PER_CALL,
MAX_NEW_NULLIFIERS_PER_CALL,
MAX_NEW_COMMITMENTS_PER_CALL,
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
MAX_PUBLIC_DATA_READS_PER_CALL,
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
NUM_FIELDS_PER_SHA256,
RETURN_VALUES_LENGTH,
GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,
PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH,
};
use crate::{
abis::{
call_context::CallContext,
side_effect::{SideEffect, SideEffectLinkedToNoteHash},
},
address::AztecAddress,
constants::{
MAX_NEW_L2_TO_L1_MSGS_PER_CALL,
MAX_NEW_NULLIFIERS_PER_CALL,
MAX_NEW_COMMITMENTS_PER_CALL,
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
MAX_PUBLIC_DATA_READS_PER_CALL,
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
NUM_FIELDS_PER_SHA256,
RETURN_VALUES_LENGTH,
GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,
PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH,
},
contrakt::{
storage_read::StorageRead,
storage_update_request::StorageUpdateRequest,
},
hash::pedersen_hash,
header::Header,
traits::{
Hash,
Serialize,
Deserialize,
},
utils::reader::Reader,
};
use crate::traits::{Hash, Serialize, Deserialize};

struct PublicCircuitPublicInputs{
call_context: CallContext,
Expand Down Expand Up @@ -82,6 +87,31 @@ impl Serialize<PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH> for PublicCircuitPublicInput
}
}

impl Deserialize<PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH> for PublicCircuitPublicInputs {
fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {
// TODO(#4390): This should accept a reader ^ to avoid copying data.
let mut reader = Reader::new(serialized);
let inputs = PublicCircuitPublicInputs {
call_context: reader.read_struct(CallContext::deserialize),
args_hash: reader.read(),
return_values: reader.read_array([0; RETURN_VALUES_LENGTH]),
contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),
contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),
public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),
new_commitments: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_NEW_COMMITMENTS_PER_CALL]),
new_nullifiers: reader.read_struct_array(SideEffectLinkedToNoteHash::deserialize, [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),
new_l2_to_l1_msgs: reader.read_array([0; MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),
unencrypted_logs_hash: reader.read_array([0; NUM_FIELDS_PER_SHA256]),
unencrypted_log_preimages_length: reader.read(),
historical_header: reader.read_struct(Header::deserialize),
prover_address: reader.read_struct(AztecAddress::deserialize),
};

reader.finish();
inputs
}
}

impl Hash for PublicCircuitPublicInputs {
fn hash(self) -> Field {
pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)
Expand Down
Loading
Loading