diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index f8a4865b6c5..76a979de32f 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -6,6 +6,31 @@ keywords: [sandbox, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. +## TBD + +### [Aztec.nr] Introduction of `Packable` trait +We have introduced a `Packable` trait that allows types to be serialized and deserialized with a focus on minimizing the size of the resulting Field array. +This is in contrast to the `Serialize` and `Deserialize` traits, which follows Noir's intrinsic serialization format. +This is a breaking change because we now require `Packable` trait implementation for any type that is to be stored in contract storage. + +Example implementation of Packable trait for `U128` type from `noir::std`: + +``` +use crate::traits::{Packable, ToField}; + +let U128_PACKED_LEN: u32 = 1; + +impl Packable for U128 { + fn pack(self) -> [Field; U128_PACKED_LEN] { + [self.to_field()] + } + + fn unpack(fields: [Field; U128_PACKED_LEN]) -> Self { + U128::from_integer(fields[0]) + } +} +``` + ## 0.72.0 ### Some functions in `aztec.js` and `@aztec/accounts` are now async In our efforts to make libraries more browser-friendly and providing with more bundling options for `bb.js` (like a non top-level-await version), some functions are being made async, in particular those that access our cryptographic functions. diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index a763ce4ea30..54402ea44be 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -5,7 +5,7 @@ use crate::hash::{ use dep::protocol_types::abis::function_selector::FunctionSelector; use dep::protocol_types::address::{AztecAddress, EthAddress}; use dep::protocol_types::constants::MAX_FIELD_VALUE; -use dep::protocol_types::traits::{Deserialize, Empty, Serialize}; +use dep::protocol_types::traits::{Empty, Packable, Serialize}; pub struct PublicContext { pub args_hash: Option, @@ -219,9 +219,9 @@ impl PublicContext { pub fn storage_read(self, storage_slot: Field) -> T where - T: Deserialize, + T: Packable, { - T::deserialize(self.raw_storage_read(storage_slot)) + T::unpack(self.raw_storage_read(storage_slot)) } pub fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) { @@ -233,9 +233,9 @@ impl PublicContext { pub fn storage_write(self, storage_slot: Field, value: T) where - T: Serialize, + T: Packable, { - self.raw_storage_write(storage_slot, value.serialize()); + self.raw_storage_write(storage_slot, value.pack()); } } diff --git a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr index 5a2c5f765ab..a50105824fa 100644 --- a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr @@ -2,7 +2,7 @@ use crate::oracle::{ execution::{get_block_number, get_chain_id, get_contract_address, get_version}, storage::storage_read, }; -use dep::protocol_types::{address::AztecAddress, traits::Deserialize}; +use dep::protocol_types::{address::AztecAddress, traits::Packable}; pub struct UnconstrainedContext { block_number: u32, @@ -62,8 +62,8 @@ impl UnconstrainedContext { pub unconstrained fn storage_read(self, storage_slot: Field) -> T where - T: Deserialize, + T: Packable, { - T::deserialize(self.raw_storage_read(storage_slot)) + T::unpack(self.raw_storage_read(storage_slot)) } } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/pxe_db.nr b/noir-projects/aztec-nr/aztec/src/oracle/pxe_db.nr index df96b00a9b0..acaa7d1673c 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/pxe_db.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/pxe_db.nr @@ -1,7 +1,7 @@ use protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}}; /// Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `load`. If -/// data was already stored at this slot, it is overwrriten. +/// data was already stored at this slot, it is overwritten. pub unconstrained fn store(contract_address: AztecAddress, slot: Field, value: T) where T: Serialize, diff --git a/noir-projects/aztec-nr/aztec/src/oracle/storage.nr b/noir-projects/aztec-nr/aztec/src/oracle/storage.nr index 67e86790e43..d17b1301585 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/storage.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/storage.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{address::AztecAddress, traits::Deserialize}; +use dep::protocol_types::{address::AztecAddress, traits::Packable}; #[oracle(storageRead)] unconstrained fn storage_read_oracle( @@ -27,14 +27,14 @@ pub unconstrained fn storage_read( block_number: u32, ) -> T where - T: Deserialize, + T: Packable, { - T::deserialize(raw_storage_read(address, storage_slot, block_number)) + T::unpack(raw_storage_read(address, storage_slot, block_number)) } mod tests { use crate::oracle::storage::{raw_storage_read, storage_read}; - use dep::protocol_types::address::AztecAddress; + use dep::protocol_types::{address::AztecAddress, traits::{FromField, Packable}}; use crate::test::mocks::mock_struct::MockStruct; use std::test::OracleMock; @@ -47,7 +47,7 @@ mod tests { unconstrained fn test_raw_storage_read() { let written = MockStruct { a: 13, b: 42 }; - let _ = OracleMock::mock("storageRead").returns(written.serialize()); + let _ = OracleMock::mock("storageRead").returns(written.pack()); let read: [Field; 2] = raw_storage_read(address, slot, block_number); assert_eq(read[0], 13); @@ -58,7 +58,7 @@ mod tests { unconstrained fn test_storage_read() { let written = MockStruct { a: 13, b: 42 }; - let _ = OracleMock::mock("storageRead").returns(written.serialize()); + let _ = OracleMock::mock("storageRead").returns(written.pack()); let read: MockStruct = storage_read(address, slot, block_number); assert_eq(read.a, 13); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/map.nr b/noir-projects/aztec-nr/aztec/src/state_vars/map.nr index 367f7eea984..4e4844c7cb9 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/map.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/map.nr @@ -1,8 +1,5 @@ use crate::state_vars::storage::Storage; -use dep::protocol_types::{ - storage::map::derive_storage_slot_in_map, - traits::{Deserialize, Serialize, ToField}, -}; +use dep::protocol_types::{storage::map::derive_storage_slot_in_map, traits::{Packable, ToField}}; // docs:start:map pub struct Map { @@ -14,7 +11,7 @@ pub struct Map { impl Storage for Map where - T: Serialize + Deserialize, + T: Packable, { fn get_storage_slot(self) -> Field { self.storage_slot diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index 662f4274f37..7da9bef3035 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -1,7 +1,6 @@ use dep::protocol_types::{ - constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, - hash::poseidon2_hash_with_separator, - traits::{Deserialize, Serialize}, + constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::poseidon2_hash_with_separator, + traits::Packable, }; use crate::context::{PrivateContext, UnconstrainedContext}; @@ -24,7 +23,7 @@ pub struct PrivateImmutable { impl Storage for PrivateImmutable where - T: Serialize + Deserialize, + T: Packable, { fn get_storage_slot(self) -> Field { self.storage_slot diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index 44a757b5b5b..c5cf98a31b1 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -1,7 +1,6 @@ use dep::protocol_types::{ - constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, - hash::poseidon2_hash_with_separator, - traits::{Deserialize, Serialize}, + constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::poseidon2_hash_with_separator, + traits::Packable, }; use crate::context::{PrivateContext, UnconstrainedContext}; @@ -26,7 +25,7 @@ mod test; impl Storage for PrivateMutable where - T: Serialize + Deserialize, + T: Packable, { fn get_storage_slot(self) -> Field { self.storage_slot diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index 008c0c215cf..fd7a6d36cc2 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -11,9 +11,8 @@ use crate::note::{ }; use crate::state_vars::storage::Storage; use dep::protocol_types::{ - abis::read_request::ReadRequest, - constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - traits::{Deserialize, Serialize}, + abis::read_request::ReadRequest, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + traits::Packable, }; // docs:start:struct @@ -25,7 +24,7 @@ pub struct PrivateSet { impl Storage for PrivateSet where - T: Serialize + Deserialize, + T: Packable, { fn get_storage_slot(self) -> Field { self.storage_slot diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr index 96809aa8686..af8402a86c2 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr @@ -1,11 +1,9 @@ use crate::{ context::{PrivateContext, PublicContext, UnconstrainedContext}, + history::public_storage::PublicStorageHistoricalRead, state_vars::storage::Storage, }; -use dep::protocol_types::{ - constants::INITIALIZATION_SLOT_SEPARATOR, - traits::{Deserialize, Serialize}, -}; +use dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::Packable}; /// Stores an immutable value in public state which can be read from public, private and unconstrained execution /// contexts. @@ -18,7 +16,7 @@ pub struct PublicImmutable { impl Storage for PublicImmutable where - T: Serialize + Deserialize, + T: Packable, { fn get_storage_slot(self) -> Field { self.storage_slot @@ -38,9 +36,9 @@ impl PublicImmutable { // docs:end:public_immutable_struct_new } -impl PublicImmutable +impl PublicImmutable where - T: Serialize + Deserialize, + T: Packable, { // docs:start:public_immutable_struct_write pub fn initialize(self, value: T) { @@ -63,22 +61,22 @@ where // docs:end:public_immutable_struct_read } -impl PublicImmutable +impl PublicImmutable where - T: Serialize + Deserialize, + T: Packable, { pub unconstrained fn read(self) -> T { self.context.storage_read(self.storage_slot) } } -impl PublicImmutable +impl PublicImmutable where - T: Serialize + Deserialize, + T: Packable, { pub fn read(self) -> T { let header = self.context.get_block_header(); - let mut fields = [0; T_SERIALIZED_LEN]; + let mut fields = [0; T_PACKED_LEN]; for i in 0..fields.len() { fields[i] = header.public_storage_historical_read( @@ -86,6 +84,6 @@ where (*self.context).this_address(), ); } - T::deserialize(fields) + T::unpack(fields) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr index cf9bf589040..f2890f27f64 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr @@ -1,6 +1,6 @@ use crate::context::{PublicContext, UnconstrainedContext}; use crate::state_vars::storage::Storage; -use dep::protocol_types::traits::{Deserialize, Serialize}; +use dep::protocol_types::traits::Packable; // docs:start:public_mutable_struct pub struct PublicMutable { @@ -11,7 +11,7 @@ pub struct PublicMutable { impl Storage for PublicMutable where - T: Serialize + Deserialize, + T: Packable, { fn get_storage_slot(self) -> Field { self.storage_slot @@ -31,9 +31,9 @@ impl PublicMutable { // docs:end:public_mutable_struct_new } -impl PublicMutable +impl PublicMutable where - T: Serialize + Deserialize, + T: Packable, { // docs:start:public_mutable_struct_read pub fn read(self) -> T { @@ -48,9 +48,9 @@ where // docs:end:public_mutable_struct_write } -impl PublicMutable +impl PublicMutable where - T: Deserialize, + T: Packable, { pub unconstrained fn read(self) -> T { self.context.storage_read(self.storage_slot) diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr index 34ace291116..5c080c55ae1 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr @@ -1,7 +1,7 @@ use dep::protocol_types::{ address::AztecAddress, hash::{poseidon2_hash, poseidon2_hash_with_separator}, - traits::{Deserialize, FromField, Serialize, ToField}, + traits::{FromField, Packable, ToField}, utils::arrays::array_concat, }; @@ -38,7 +38,7 @@ global HASH_SEPARATOR: u32 = 2; // can actually use it here impl Storage for SharedMutable where - T: Serialize + Deserialize, + T: Packable, { fn get_storage_slot(self) -> Field { self.storage_slot @@ -225,12 +225,12 @@ where // scheduled. Therefore, the hints must then correspond to uninitialized scheduled changes. assert_eq( value_change_hint, - ScheduledValueChange::deserialize(zeroed()), + ScheduledValueChange::unpack(zeroed()), "Non-zero value change for zero hash", ); assert_eq( delay_change_hint, - ScheduledDelayChange::deserialize(zeroed()), + ScheduledDelayChange::unpack(zeroed()), "Non-zero delay change for zero hash", ); }; @@ -242,8 +242,7 @@ where value_change: ScheduledValueChange, delay_change: ScheduledDelayChange, ) -> Field { - let concatenated: [Field; 4] = - array_concat(value_change.serialize(), delay_change.serialize()); + let concatenated: [Field; 4] = array_concat(value_change.pack(), delay_change.pack()); poseidon2_hash(concatenated) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr index 29808aef30a..d325dbd0a0f 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::traits::{Deserialize, Serialize}; +use dep::protocol_types::traits::Packable; use std::cmp::min; mod test; @@ -125,8 +125,8 @@ impl ScheduledDelayChange { } } -impl Serialize<1> for ScheduledDelayChange { - fn serialize(self) -> [Field; 1] { +impl Packable<1> for ScheduledDelayChange { + fn pack(self) -> [Field; 1] { // We pack all three u32 values into a single U128, which is made up of two u64 limbs. // Low limb: [ pre_inner: u32 | post_inner: u32 ] // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ] @@ -141,10 +141,8 @@ impl Serialize<1> for ScheduledDelayChange Deserialize<1> for ScheduledDelayChange { - fn deserialize(input: [Field; 1]) -> Self { + fn unpack(input: [Field; 1]) -> Self { let packed = U128::from_integer(input[0]); // We use division and modulo to clear the bits that correspond to other values when unpacking. diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr index 17a9e5e94e6..ff83d72da6c 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr @@ -6,7 +6,7 @@ unconstrained fn assert_equal_after_conversion(original: ScheduledDelayChange = - ScheduledDelayChange::deserialize((original).serialize()); + ScheduledDelayChange::unpack(original.pack()); assert_eq(original, converted); // This also tests the Eq impl assert_eq(original.pre, converted.pre); @@ -15,7 +15,7 @@ unconstrained fn assert_equal_after_conversion(original: ScheduledDelayChange ScheduledDelayChange { - ScheduledDelayChange::deserialize([0]) + ScheduledDelayChange::unpack([0]) } #[test] diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr index 2bc6a252798..eeb55c46e76 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::traits::{Deserialize, FromField, Serialize, ToField}; +use dep::protocol_types::traits::{FromField, Packable, ToField}; use std::cmp::min; mod test; @@ -133,20 +133,15 @@ impl ScheduledValueChange { } } -impl Serialize<3> for ScheduledValueChange +impl Packable<3> for ScheduledValueChange where - T: ToField, + T: ToField + FromField, { - fn serialize(self) -> [Field; 3] { + fn pack(self) -> [Field; 3] { [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()] } -} -impl Deserialize<3> for ScheduledValueChange -where - T: FromField, -{ - fn deserialize(input: [Field; 3]) -> Self { + fn unpack(input: [Field; 3]) -> Self { Self { pre: FromField::from_field(input[0]), post: FromField::from_field(input[1]), diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr index 4677830d013..179089945ab 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr @@ -3,13 +3,13 @@ use crate::state_vars::shared_mutable::scheduled_value_change::ScheduledValueCha global TEST_DELAY: u32 = 200; #[test] -unconstrained fn test_serde() { +unconstrained fn test_packable() { let pre = 1; let post = 2; let block_of_change = 50; let original = ScheduledValueChange::new(pre, post, block_of_change); - let converted = ScheduledValueChange::deserialize((original).serialize()); + let converted = ScheduledValueChange::unpack((original).pack()); assert_eq(original, converted); // This also tests the Eq impl assert_eq(original.pre, converted.pre); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr index f3ec3434abf..8983b35e44a 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr @@ -296,7 +296,7 @@ unconstrained fn test_get_current_value_in_private_bad_value_hints() { env.contract_address().to_field(), private_state_var.get_value_change_storage_slot(), schedule_block_number, 3, )) - .returns(mocked.serialize()) + .returns(mocked.pack()) .times(1); let _ = private_state_var.get_current_value(); @@ -319,7 +319,7 @@ unconstrained fn test_get_current_value_in_private_bad_delay_hints() { env.contract_address().to_field(), private_state_var.get_delay_change_storage_slot(), schedule_block_number, 1, )) - .returns(mocked.serialize()) + .returns(mocked.pack()) .times(1); let _ = private_state_var.get_current_value(); @@ -338,7 +338,7 @@ unconstrained fn test_get_current_value_in_private_bad_zero_hash_value_hints() { env.contract_address().to_field(), state_var.get_value_change_storage_slot(), historical_block_number, 3, )) - .returns(mocked.serialize()) + .returns(mocked.pack()) .times(1); let _ = state_var.get_current_value(); @@ -358,7 +358,7 @@ unconstrained fn test_get_current_value_in_private_bad_zero_hash_delay_hints() { env.contract_address().to_field(), state_var.get_delay_change_storage_slot(), historical_block_number, 1, )) - .returns(mocked.serialize()) + .returns(mocked.pack()) .times(1); let _ = state_var.get_current_value(); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr b/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr index 3539ce0c78c..3ea02e3ad88 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr @@ -1,8 +1,8 @@ -use dep::protocol_types::traits::{Deserialize, Serialize}; +use dep::protocol_types::traits::Packable; pub trait Storage where - T: Serialize + Deserialize, + T: Packable, { fn get_storage_slot(self) -> Field; } diff --git a/noir-projects/aztec-nr/aztec/src/test/mocks/mock_struct.nr b/noir-projects/aztec-nr/aztec/src/test/mocks/mock_struct.nr index 2adfcda5a5b..4677b23fb14 100644 --- a/noir-projects/aztec-nr/aztec/src/test/mocks/mock_struct.nr +++ b/noir-projects/aztec-nr/aztec/src/test/mocks/mock_struct.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::traits::{Deserialize, Serialize}; +use dep::protocol_types::traits::{Deserialize, Packable, Serialize}; pub(crate) struct MockStruct { pub(crate) a: Field, @@ -29,8 +29,24 @@ impl Deserialize<2> for MockStruct { } } +impl Packable<2> for MockStruct { + fn pack(self) -> [Field; 2] { + [self.a, self.b] + } + + fn unpack(fields: [Field; 2]) -> Self { + Self { a: fields[0], b: fields[1] } + } +} + #[test] unconstrained fn test_serde() { let val = MockStruct::new(5, 6); assert_eq(val, MockStruct::deserialize(val.serialize())); } + +#[test] +unconstrained fn test_packable() { + let val = MockStruct::new(5, 6); + assert_eq(val, MockStruct::unpack(val.pack())); +} diff --git a/noir-projects/aztec-nr/compressed-string/src/field_compressed_string.nr b/noir-projects/aztec-nr/compressed-string/src/field_compressed_string.nr index 41b391c260c..0356b2501af 100644 --- a/noir-projects/aztec-nr/compressed-string/src/field_compressed_string.nr +++ b/noir-projects/aztec-nr/compressed-string/src/field_compressed_string.nr @@ -1,20 +1,25 @@ -use dep::aztec::protocol_types::{traits::{Deserialize, Serialize}, utils::field::field_from_bytes}; +use dep::aztec::protocol_types::{ + traits::{Deserialize, Packable, Serialize}, + utils::field::field_from_bytes, +}; +use std::meta::derive; // A Fixedsize Compressed String. // Essentially a special version of Compressed String for practical use. +#[derive(Serialize, Deserialize)] pub struct FieldCompressedString { value: Field, } -impl Serialize<1> for FieldCompressedString { - fn serialize(self) -> [Field; 1] { - [self.value] +/// 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() } -} -impl Deserialize<1> for FieldCompressedString { - fn deserialize(input: [Field; 1]) -> Self { - Self { value: input[0] } + fn unpack(input: [Field; 1]) -> Self { + Self::deserialize(input) } } diff --git a/noir-projects/noir-contracts/contracts/amm_contract/src/config.nr b/noir-projects/noir-contracts/contracts/amm_contract/src/config.nr index c83648c4a39..e56f3160aa1 100644 --- a/noir-projects/noir-contracts/contracts/amm_contract/src/config.nr +++ b/noir-projects/noir-contracts/contracts/amm_contract/src/config.nr @@ -1,29 +1,26 @@ -use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}}; +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)] pub struct Config { pub token0: AztecAddress, pub token1: AztecAddress, pub liquidity_token: AztecAddress, } -// Note: I could not get #[derive(Serialize)] to work so I had to implement it manually. -impl Serialize for Config { - fn serialize(self: Self) -> [Field; CONFIG_LENGTH] { - [self.token0.to_field(), self.token1.to_field(), self.liquidity_token.to_field()] +/// 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 for Config { + fn pack(self: Self) -> [Field; CONFIG_LENGTH] { + self.serialize() } -} -impl Deserialize for Config { - fn deserialize(fields: [Field; CONFIG_LENGTH]) -> Self { - Self { - token0: AztecAddress::from_field(fields[0]), - token1: AztecAddress::from_field(fields[1]), - liquidity_token: AztecAddress::from_field(fields[2]), - } + fn unpack(fields: [Field; CONFIG_LENGTH]) -> Self { + Self::deserialize(fields) } } diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index c5520df3f19..581d4827c8b 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -1,5 +1,6 @@ -use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; +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 { a: Field, b: Field, @@ -17,7 +18,17 @@ impl Deserialize<2> for Note { } } -use dep::aztec::macros::aztec; +/// 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) + } +} #[aztec] contract AvmTest { diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/game.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/game.nr index 436e102d6d5..9113b14ec8f 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/game.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/game.nr @@ -1,5 +1,5 @@ use crate::cards::Card; -use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}}; +use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Packable}}; global NUMBER_OF_PLAYERS: u32 = 2; global NUMBER_OF_CARDS_DECK: u32 = 2; @@ -50,8 +50,8 @@ pub struct Game { global GAME_SERIALIZED_LEN: u32 = 15; -impl Serialize for Game { - fn serialize(game: Game) -> [Field; GAME_SERIALIZED_LEN] { +impl Packable for Game { + fn pack(game: Game) -> [Field; GAME_SERIALIZED_LEN] { [ game.players[0].address.to_field(), game.players[0].deck_strength as Field, @@ -70,10 +70,8 @@ impl Serialize for Game { game.current_round as Field, ] } -} -impl Deserialize for Game { - fn deserialize(fields: [Field; GAME_SERIALIZED_LEN]) -> Game { + 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]]); diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/leader.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/leader.nr index 485ccf634c2..0c356228d1f 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/leader.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/leader.nr @@ -1,4 +1,4 @@ -use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}}; +use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Packable, Serialize}}; // Shows how to create a custom struct in Public pub struct Leader { @@ -19,3 +19,13 @@ impl Serialize for Leader { [self.account.to_field(), self.points as Field] } } + +impl Packable for Leader { + fn pack(self) -> [Field; LEADER_SERIALIZED_LEN] { + self.serialize() + } + + fn unpack(fields: [Field; LEADER_SERIALIZED_LEN]) -> Self { + Self::deserialize(fields) + } +} diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/config.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/config.nr index 00c1473d34b..9b91358594d 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/config.nr +++ b/noir-projects/noir-contracts/contracts/fpc_contract/src/config.nr @@ -1,4 +1,4 @@ -use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}}; +use dep::aztec::protocol_types::{address::AztecAddress, traits::{Deserialize, Packable, Serialize}}; global CONFIG_LENGTH: u32 = 2; @@ -21,3 +21,13 @@ impl Deserialize for Config { } } } + +impl Packable for Config { + fn pack(self) -> [Field; CONFIG_LENGTH] { + self.serialize() + } + + fn unpack(fields: [Field; CONFIG_LENGTH]) -> Self { + Self::deserialize(fields) + } +} diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr index e8ec7af56aa..2b0f7d57ef3 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr @@ -1,5 +1,5 @@ use dep::aztec::prelude::AztecAddress; -use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; +use dep::aztec::protocol_types::traits::{Deserialize, Packable, Serialize}; // 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 @@ -40,3 +40,13 @@ impl Deserialize for Asset { Asset { interest_accumulator, last_updated_ts, loan_to_value, oracle } } } + +impl Packable for Asset { + fn pack(self) -> [Field; SERIALIZED_LEN] { + self.serialize() + } + + fn unpack(fields: [Field; SERIALIZED_LEN]) -> Self { + Self::deserialize(fields) + } +} diff --git a/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr b/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr index 86c7b11c198..60c3c14c563 100644 --- a/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr +++ b/noir-projects/noir-contracts/contracts/price_feed_contract/src/asset.nr @@ -1,4 +1,4 @@ -use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; +use dep::aztec::protocol_types::traits::{Deserialize, Packable, Serialize}; pub struct Asset { price: U128, @@ -18,3 +18,15 @@ impl Deserialize for Asset { Asset { price } } } + +global ASSET_PACKED_LEN: u32 = 1; + +impl Packable for Asset { + fn pack(self) -> [Field; ASSET_PACKED_LEN] { + self.price.pack() + } + + fn unpack(fields: [Field; ASSET_PACKED_LEN]) -> Self { + Self { price: U128::unpack(fields) } + } +} diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr index 477a58bea0c..6425daaffb8 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr @@ -2,7 +2,7 @@ use dep::aztec::{ context::PrivateContext, macros::notes::note, note::{note_header::NoteHeader, note_interface::NullifiableNote}, - protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}}, + protocol_types::{address::AztecAddress, traits::{Deserialize, Packable, Serialize}}, }; // A note which stores a field and is expected to be passed around using the `addNote` function. @@ -43,3 +43,13 @@ impl Eq for TestNote { self.value == other.value } } + +impl Packable<1> for TestNote { + fn pack(self) -> [Field; 1] { + [self.value] + } + + fn unpack(fields: [Field; 1]) -> Self { + TestNote { value: fields[0], header: NoteHeader::empty() } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr index 0ad080aaeeb..2d7250d531c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr @@ -11,7 +11,7 @@ use crate::{ hash::{poseidon2_hash_with_separator, private_functions_root_from_siblings}, merkle_tree::membership::MembershipWitness, public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM}, - traits::{Deserialize, Empty, FromField, Serialize, ToField}, + traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField}, }; // We do below because `use crate::point::Point;` does not work @@ -65,6 +65,18 @@ impl Deserialize for AztecAddress { } } +/// We implement the Packable trait for AztecAddress because it can be stored in contract's storage (and there +/// the implementation of Packable is required). +impl Packable for AztecAddress { + fn pack(self) -> [Field; AZTEC_ADDRESS_LENGTH] { + self.serialize() + } + + fn unpack(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self { + Self::deserialize(fields) + } +} + impl AztecAddress { pub fn zero() -> Self { Self { inner: 0 } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr index 56b8e2d7d91..f50aab7ff93 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr @@ -1,4 +1,7 @@ -use crate::{constants::ETH_ADDRESS_LENGTH, traits::{Deserialize, Empty, Serialize, ToField}}; +use crate::{ + constants::ETH_ADDRESS_LENGTH, + traits::{Deserialize, Empty, Packable, Serialize, ToField}, +}; pub struct EthAddress { inner: Field, @@ -34,6 +37,16 @@ impl Deserialize for EthAddress { } } +impl Packable for EthAddress { + fn pack(self) -> [Field; ETH_ADDRESS_LENGTH] { + self.serialize() + } + + fn unpack(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self { + Self::deserialize(fields) + } +} + impl EthAddress { pub fn zero() -> Self { Self { inner: 0 } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr index 4a3ccfc32d0..c5c37d539cb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr @@ -16,6 +16,7 @@ pub mod hash; pub mod poseidon2; pub mod traits; pub mod type_serialization; +pub mod type_packing; pub mod content_commitment; pub mod block_header; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/point.nr b/noir-projects/noir-protocol-circuits/crates/types/src/point.nr index eaa7bdd2c2a..589bf00114e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/point.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/point.nr @@ -1,5 +1,5 @@ pub use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point; -use crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Serialize}}; +use crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Packable, Serialize}}; pub global POINT_LENGTH: u32 = 3; @@ -28,3 +28,13 @@ impl Deserialize for Point { Point { x: serialized[0], y: serialized[1], is_infinite: serialized[2] as bool } } } +// TODO(#11356): use compact representation here. +impl Packable for Point { + fn pack(self) -> [Field; POINT_LENGTH] { + self.serialize() + } + + fn unpack(packed: [Field; POINT_LENGTH]) -> Self { + Self::deserialize(packed) + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr b/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr index 4034448eda5..2c7f7882e9a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr @@ -155,6 +155,36 @@ impl FromField for U128 { } // docs:start:serialize +/// Trait for serializing Noir types into arrays of Fields. +/// +/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct +/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are +/// typically used to communicate between Noir and TypeScript (via oracles and function arguments). +/// +/// # On Following Noir's Intrinsic Serialization +/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array +/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used +/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait +/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization, +/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls +/// fail with an arguments hash mismatch error message. +/// +/// # Type Parameters +/// * `N` - The length of the output Field array, known at compile time +/// +/// # Example +/// ``` +/// impl Serialize for str { +/// fn serialize(self) -> [Field; N] { +/// let bytes = self.as_bytes(); +/// let mut fields = [0; N]; +/// for i in 0..bytes.len() { +/// fields[i] = bytes[i] as Field; // Each byte gets its own Field +/// } +/// fields +/// } +/// } +/// ``` #[derive_via(derive_serialize)] pub trait Serialize { fn serialize(self) -> [Field; N]; @@ -173,6 +203,24 @@ impl Serialize for str { } // docs:start:deserialize +/// Trait for deserializing Noir types from arrays of Fields. +/// +/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct +/// converted directly into one or more Fields without any packing or compression). This trait is typically used when +/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript +/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2. +/// +/// # Type Parameters +/// * `N` - The length of the input Field array, known at compile time +/// +/// # Example +/// ``` +/// impl Deserialize for str { +/// fn deserialize(fields: [Field; N]) -> Self { +/// str::from(fields.map(|value| value as u8)) +/// } +/// } +/// ``` #[derive_via(derive_deserialize)] pub trait Deserialize { fn deserialize(fields: [Field; N]) -> Self; @@ -184,3 +232,19 @@ impl Deserialize for str { str::from(fields.map(|value| value as u8)) } } + +/// Trait for efficiently packing and unpacking Noir types into and from arrays of Fields. +/// +/// The `Packable` trait allows types to be serialized and deserialized with a focus on minimizing the size of +/// the resulting Field array. This trait is used when storage efficiency is critical (e.g. when storing data +/// in the contract's public storage). +/// +/// # Type Parameters +/// * `N` - The length of the Field array, known at compile time. +pub trait Packable { + /// Packs the current value into a compact array of `Field` elements. + fn pack(self) -> [Field; N]; + + /// Unpacks a compact array of `Field` elements into the original value. + fn unpack(fields: [Field; N]) -> Self; +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr b/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr new file mode 100644 index 00000000000..56486e92e5d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr @@ -0,0 +1,176 @@ +use crate::traits::{Packable, ToField}; + +global BOOL_PACKED_LEN: u32 = 1; +global U8_PACKED_LEN: u32 = 1; +global U16_PACKED_LEN: u32 = 1; +global U32_PACKED_LEN: u32 = 1; +global U64_PACKED_LEN: u32 = 1; +global U128_PACKED_LEN: u32 = 1; +global FIELD_PACKED_LEN: u32 = 1; +global I8_PACKED_LEN: u32 = 1; +global I16_PACKED_LEN: u32 = 1; +global I32_PACKED_LEN: u32 = 1; +global I64_PACKED_LEN: u32 = 1; + +impl Packable for bool { + fn pack(self) -> [Field; BOOL_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; BOOL_PACKED_LEN]) -> bool { + fields[0] as bool + } +} + +impl Packable for u8 { + fn pack(self) -> [Field; U8_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; U8_PACKED_LEN]) -> Self { + fields[0] as u8 + } +} + +impl Packable for u16 { + fn pack(self) -> [Field; U16_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; U16_PACKED_LEN]) -> Self { + fields[0] as u16 + } +} + +impl Packable for u32 { + fn pack(self) -> [Field; U32_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; U32_PACKED_LEN]) -> Self { + fields[0] as u32 + } +} + +impl Packable for u64 { + fn pack(self) -> [Field; U64_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; U64_PACKED_LEN]) -> Self { + fields[0] as u64 + } +} + +impl Packable for U128 { + fn pack(self) -> [Field; U128_PACKED_LEN] { + [self.to_field()] + } + + fn unpack(fields: [Field; U128_PACKED_LEN]) -> Self { + U128::from_integer(fields[0]) + } +} + +impl Packable for Field { + fn pack(self) -> [Field; FIELD_PACKED_LEN] { + [self] + } + + fn unpack(fields: [Field; FIELD_PACKED_LEN]) -> Self { + fields[0] + } +} + +impl Packable for i8 { + fn pack(self) -> [Field; I8_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; I8_PACKED_LEN]) -> Self { + fields[0] as i8 + } +} + +impl Packable for i16 { + fn pack(self) -> [Field; I16_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; I16_PACKED_LEN]) -> Self { + fields[0] as i16 + } +} + +impl Packable for i32 { + fn pack(self) -> [Field; I32_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; I32_PACKED_LEN]) -> Self { + fields[0] as i32 + } +} + +impl Packable for i64 { + fn pack(self) -> [Field; I64_PACKED_LEN] { + [self as Field] + } + + fn unpack(fields: [Field; I64_PACKED_LEN]) -> Self { + fields[0] as i64 + } +} + +impl Packable for [T; N] +where + T: Packable, +{ + fn pack(self) -> [Field; N * M] { + let mut result: [Field; N * M] = std::mem::zeroed(); + let mut serialized: [Field; M] = std::mem::zeroed(); + for i in 0..N { + serialized = self[i].pack(); + for j in 0..M { + result[i * M + j] = serialized[j]; + } + } + result + } + + fn unpack(fields: [Field; N * M]) -> Self { + let mut reader = crate::utils::reader::Reader::new(fields); + let mut result: [T; N] = std::mem::zeroed(); + reader.read_struct_array::(Packable::unpack, result) + } +} + +#[test] +fn test_u16_packing() { + let a: u16 = 10; + assert_eq(a, u16::unpack(a.pack())); +} + +#[test] +fn test_i8_packing() { + let a: i8 = -10; + assert_eq(a, i8::unpack(a.pack())); +} + +#[test] +fn test_i16_packing() { + let a: i16 = -10; + assert_eq(a, i16::unpack(a.pack())); +} + +#[test] +fn test_i32_packing() { + let a: i32 = -10; + assert_eq(a, i32::unpack(a.pack())); +} + +#[test] +fn test_i64_packing() { + let a: i64 = -10; + assert_eq(a, i64::unpack(a.pack())); +} diff --git a/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts b/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts index fce94fc5c86..d0fb0c3b644 100644 --- a/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/gas_estimation.test.ts @@ -96,7 +96,7 @@ describe('e2e_fees gas_estimation', () => { it('estimates gas with public payment method', async () => { // TODO(#11324): Reset this value back to zero. - const estimatedGasPadding = 0.00068359375; + const estimatedGasPadding = 0.1; const teardownFixedFee = gasSettings.teardownGasLimits.computeFee(gasSettings.maxFeesPerGas).toBigInt(); const paymentMethod = new PublicFeePaymentMethod(bananaFPC.address, aliceWallet); @@ -125,7 +125,7 @@ describe('e2e_fees gas_estimation', () => { it('estimates gas for public contract initialization with Fee Juice payment method', async () => { // TODO(#11324): Reset this value back to zero. - const estimatedGasPadding = 0.00068359375; + const estimatedGasPadding = 0.1; const paymentMethod = new FeeJuicePaymentMethod(aliceAddress); const deployMethod = () => BananaCoin.deploy(aliceWallet, aliceAddress, 'TKN', 'TKN', 8); diff --git a/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts b/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts index 127a74f4286..b00cb451e07 100644 --- a/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts +++ b/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts @@ -72,26 +72,10 @@ export class GasTxValidator implements TxValidator { const feeLimit = tx.data.constants.txContext.gasSettings.getFeeLimit(); // Read current balance of the feePayer - // TODO(#11285): Remove the 2 reads below with the commented out code. - // Uncomment below ###################### - // const initialBalance = await this.#publicDataSource.storageRead( - // this.#feeJuiceAddress, - // computeFeePayerBalanceStorageSlot(feePayer), - // ); - // Uncomment above ###################### - // Remove the following ###################### - const initialBalanceLowLimb = await this.#publicDataSource.storageRead( + const initialBalance = await this.#publicDataSource.storageRead( this.#feeJuiceAddress, computeFeePayerBalanceStorageSlot(feePayer), ); - const initialBalanceHighLimb = await this.#publicDataSource.storageRead( - this.#feeJuiceAddress, - new Fr(computeFeePayerBalanceStorageSlot(feePayer).toBigInt() + 1n), - ); - const initialBalance = new Fr( - U128.fromU64sLE(initialBalanceLowLimb.toBigInt(), initialBalanceHighLimb.toBigInt()).toInteger(), - ); - // Remove the above ###################### // If there is a claim in this tx that increases the fee payer balance in Fee Juice, add it to balance const setupFns = getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP);