From c149e2cb5738c35db5edd2824bb9d03057c6611b Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Thu, 11 Apr 2024 12:01:02 +0000 Subject: [PATCH 01/31] initial test --- .../key_registry_contract/Nargo.toml | 8 + .../key_registry_contract/src/main.nr | 140 ++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml create mode 100644 noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml new file mode 100644 index 00000000000..22f4236171f --- /dev/null +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "key_registry_contract" +authors = [""] +compiler_version = ">=0.25.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr new file mode 100644 index 00000000000..7cb6d386455 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -0,0 +1,140 @@ +contract KeyRegistry { + use dep::aztec::{ + context::gas::GasOpts, + log::{ + emit_unencrypted_log, + emit_unencrypted_log_from_private + }, + state_vars::{ + PublicImmutable, + SharedMutable, + Map + }, + protocol_types::{ + abis::function_selector::FunctionSelector, + contract_class_id::ContractClassId, + hash::pedersen_hash, + address::{ + AztecAddress, + EthAddress, + PublicKeysHash, + PartialAddress, + }, + constants::{ + DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, + GENERATOR_INDEX__CONTRACT_ADDRESS + }, + traits::{ + Serialize, + Deserialize, + }, + }, + }; + + global KEY_ROTATION_DELAY = 5; + + #[aztec(storage)] + struct Storage { + nullifier_public_key_registry: Map>, + incoming_public_key_registry: Map>, + outgoing_public_key_registry: Map>, + tagging_public_key_registry: Map>, + } + + #[aztec(public)] + fn register( + nullifier_public_key: Field, + incoming_public_key: Field, + outgoing_public_key: Field, + tagging_public_key: Field, + ) { + let nullifier_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); + let incoming_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); + let outgoing_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); + let tagging_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); + + nullifier_entry.schedule_value_change(nullifier_public_key); + incoming_entry.schedule_value_change(incoming_public_key); + outgoing_entry.schedule_value_change(outgoing_public_key); + tagging_entry.schedule_value_change(tagging_public_key); + } + + #[aztec(public)] + fn register_from_preimage( + address: AztecAddress, + contract_class_id: ContractClassId, + initialization_hash: Field, + salt: Field, + deployer: AztecAddress, + portal_contract_address: EthAddress, + nullifier_public_key: Field, + incoming_public_key: Field, + outgoing_public_key: Field, + tagging_public_key: Field, + ) { + context.call_public_function( + context.this_address(), + FunctionSelector::from_signature("assert_non_membership_public((Field))"), + [address.to_field()], + GasOpts::default() + ); + + let partial_address = PartialAddress::compute( + contract_class_id, + salt, + initialization_hash, + portal_contract_address, + deployer + ); + + let public_keys_hash = pedersen_hash([ + nullifier_public_key, + tagging_public_key, + incoming_public_key, + outgoing_public_key + ], + 0 + ); + + // Do it below after refactoring all public_keys_hash_elemtns + // let address = AztecAddress::compute(public_keys_hash, partial_address); + let computed_address = AztecAddress::from_field( + pedersen_hash( + [public_keys_hash.to_field(), partial_address.to_field()], + GENERATOR_INDEX__CONTRACT_ADDRESS + ) + ); + + assert(computed_address.eq(address)); + + let nullifier_entry = storage.nullifier_public_key_registry.at(address); + let incoming_entry = storage.nullifier_public_key_registry.at(address); + let outgoing_entry = storage.nullifier_public_key_registry.at(address); + let tagging_entry = storage.nullifier_public_key_registry.at(address); + + nullifier_entry.schedule_value_change(nullifier_public_key); + incoming_entry.schedule_value_change(incoming_public_key); + outgoing_entry.schedule_value_change(outgoing_public_key); + tagging_entry.schedule_value_change(tagging_public_key); + } + + #[aztec(public)] + fn assert_non_membership_public( + address: AztecAddress + ) { + let registry_entry = storage.nullifier_public_key_registry.at(address); + let nullifier_key = registry_entry.get_current_value_in_public(); + + assert(nullifier_key == 0); + } + + #[aztec(private)] + fn assert_non_membership_private( + address: AztecAddress + ) { + let registry_entry = storage.nullifier_public_key_registry.at(address); + let nullifier_key = registry_entry.get_current_value_in_private(); + + assert(nullifier_key == 0); + } +} From 7365b175b43bd1aa705a345eae6cbbc10acf0740 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 12 Apr 2024 09:53:08 +0000 Subject: [PATCH 02/31] test --- .../key_registry_contract/src/main.nr | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 7cb6d386455..088d4567262 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -1,12 +1,7 @@ contract KeyRegistry { use dep::aztec::{ context::gas::GasOpts, - log::{ - emit_unencrypted_log, - emit_unencrypted_log_from_private - }, state_vars::{ - PublicImmutable, SharedMutable, Map }, @@ -21,13 +16,9 @@ contract KeyRegistry { PartialAddress, }, constants::{ - DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, - GENERATOR_INDEX__CONTRACT_ADDRESS + GENERATOR_INDEX__CONTRACT_ADDRESS, + GENERATOR_INDEX__PARTIAL_ADDRESS }, - traits::{ - Serialize, - Deserialize, - }, }, }; @@ -48,6 +39,7 @@ contract KeyRegistry { outgoing_public_key: Field, tagging_public_key: Field, ) { + assert((nullifier_public_key != 0) & (incoming_public_key != 0) & (outgoing_public_key != 0) & (tagging_public_key != 0)); let nullifier_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); let incoming_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); let outgoing_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); @@ -72,6 +64,7 @@ contract KeyRegistry { outgoing_public_key: Field, tagging_public_key: Field, ) { + assert((nullifier_public_key != 0) & (incoming_public_key != 0) & (outgoing_public_key != 0) & (tagging_public_key != 0)); context.call_public_function( context.this_address(), FunctionSelector::from_signature("assert_non_membership_public((Field))"), @@ -87,17 +80,18 @@ contract KeyRegistry { deployer ); + // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns + // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); + // let address = AztecAddress::compute(public_keys_hash, partial_address); let public_keys_hash = pedersen_hash([ nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key ], - 0 + GENERATOR_INDEX__PARTIAL_ADDRESS ); - // Do it below after refactoring all public_keys_hash_elemtns - // let address = AztecAddress::compute(public_keys_hash, partial_address); let computed_address = AztecAddress::from_field( pedersen_hash( [public_keys_hash.to_field(), partial_address.to_field()], @@ -137,4 +131,12 @@ contract KeyRegistry { assert(nullifier_key == 0); } + + #[aztec(public)] + fn get_nullifying_public_key( + address: AztecAddress + ) { + let registry_entry = storage.nullifier_public_key_registry.at(address); + registry_entry.get_current_value_in_public() + } } From a1907b0b07b8eb492d46f75eb916a24b9acd6770 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 12 Apr 2024 11:35:52 +0000 Subject: [PATCH 03/31] go asdf --- noir-projects/noir-contracts/Nargo.toml | 1 + .../key_registry_contract/src/main.nr | 18 ++--- yarn-project/end-to-end/src/e2e_keys.test.ts | 68 +++++++++++++++++++ 3 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 yarn-project/end-to-end/src/e2e_keys.test.ts diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index 73e8bb9295e..b3d1c57c752 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -24,6 +24,7 @@ members = [ "contracts/escrow_contract", "contracts/gas_token_contract", "contracts/import_test_contract", + "contracts/key_registry_contract", "contracts/inclusion_proofs_contract", "contracts/lending_contract", "contracts/parent_contract", diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 088d4567262..14981a12ca6 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -1,5 +1,6 @@ contract KeyRegistry { use dep::aztec::{ + avm::hash::poseidon, context::gas::GasOpts, state_vars::{ SharedMutable, @@ -8,7 +9,6 @@ contract KeyRegistry { protocol_types::{ abis::function_selector::FunctionSelector, contract_class_id::ContractClassId, - hash::pedersen_hash, address::{ AztecAddress, EthAddress, @@ -70,7 +70,7 @@ contract KeyRegistry { FunctionSelector::from_signature("assert_non_membership_public((Field))"), [address.to_field()], GasOpts::default() - ); + ).assert_empty(); let partial_address = PartialAddress::compute( contract_class_id, @@ -83,19 +83,21 @@ contract KeyRegistry { // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); // let address = AztecAddress::compute(public_keys_hash, partial_address); - let public_keys_hash = pedersen_hash([ + let public_keys_hash = poseidon([ nullifier_public_key, tagging_public_key, incoming_public_key, - outgoing_public_key + outgoing_public_key, + GENERATOR_INDEX__PARTIAL_ADDRESS as Field, ], - GENERATOR_INDEX__PARTIAL_ADDRESS ); let computed_address = AztecAddress::from_field( - pedersen_hash( - [public_keys_hash.to_field(), partial_address.to_field()], - GENERATOR_INDEX__CONTRACT_ADDRESS + poseidon([ + public_keys_hash.to_field(), + partial_address.to_field(), + GENERATOR_INDEX__CONTRACT_ADDRESS as Field, + ], ) ); diff --git a/yarn-project/end-to-end/src/e2e_keys.test.ts b/yarn-project/end-to-end/src/e2e_keys.test.ts new file mode 100644 index 00000000000..32773abd09c --- /dev/null +++ b/yarn-project/end-to-end/src/e2e_keys.test.ts @@ -0,0 +1,68 @@ +import { + type AccountWallet, + type AztecAddress, + BatchCall, + type DebugLogger, + ExtendedNote, + Fr, + type FunctionCall, + FunctionSelector, + Note, + PrivateFeePaymentMethod, + PublicFeePaymentMethod, + type TxHash, + TxStatus, + type Wallet, + computeAuthWitMessageHash, + computeMessageSecretHash, +} from '@aztec/aztec.js'; +import { FunctionData } from '@aztec/circuits.js'; +import { type ContractArtifact, decodeFunctionSignature } from '@aztec/foundation/abi'; +import { + TokenContract as BananaCoin, + FPCContract, + GasTokenContract, + SchnorrAccountContract, +} from '@aztec/noir-contracts.js'; + +import { jest } from '@jest/globals'; + +import { type BalancesFn, expectMapping, getBalancesFn, publicDeployAccounts, setup } from './fixtures/utils.js'; +import { GasPortalTestingHarnessFactory, type IGasBridgingTestHarness } from './shared/gas_portal_test_harness.js'; + +jest.setTimeout(1_000_000_000); + +describe('e2e_fees', () => { + let wallets: AccountWallet[]; + let aliceWallet: Wallet; + let aliceAddress: AztecAddress; + let bobAddress: AztecAddress; + let sequencerAddress: AztecAddress; + let gasTokenContract: GasTokenContract; + let bananaCoin: BananaCoin; + let bananaFPC: FPCContract; + + let gasBridgeTestHarness: IGasBridgingTestHarness; + + let gasBalances: BalancesFn; + let bananaPublicBalances: BalancesFn; + let bananaPrivateBalances: BalancesFn; + + beforeAll(async () => { + const { wallets: _wallets, aztecNode, deployL1ContractsValues, logger, pxe } = await setup(3); + wallets = _wallets; + + await aztecNode.setConfig({ + feeRecipient: wallets.at(-1)!.getAddress(), + }); + + aliceWallet = wallets[0]; + aliceAddress = wallets[0].getAddress(); + bobAddress = wallets[1].getAddress(); + sequencerAddress = wallets[2].getAddress(); + + gasTokenContract = gasBridgeTestHarness.l2Token; + }); + + +}); From 01bbd3b7d1c8711dc9f0141b7ada62e207f95c17 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 12 Apr 2024 12:42:08 +0000 Subject: [PATCH 04/31] sadf --- yarn-project/end-to-end/src/e2e_keys.test.ts | 59 +++++--------------- 1 file changed, 15 insertions(+), 44 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_keys.test.ts b/yarn-project/end-to-end/src/e2e_keys.test.ts index 32773abd09c..82313bca914 100644 --- a/yarn-project/end-to-end/src/e2e_keys.test.ts +++ b/yarn-project/end-to-end/src/e2e_keys.test.ts @@ -1,68 +1,39 @@ import { type AccountWallet, type AztecAddress, - BatchCall, - type DebugLogger, - ExtendedNote, - Fr, - type FunctionCall, - FunctionSelector, - Note, - PrivateFeePaymentMethod, - PublicFeePaymentMethod, - type TxHash, - TxStatus, type Wallet, - computeAuthWitMessageHash, - computeMessageSecretHash, } from '@aztec/aztec.js'; -import { FunctionData } from '@aztec/circuits.js'; -import { type ContractArtifact, decodeFunctionSignature } from '@aztec/foundation/abi'; + import { - TokenContract as BananaCoin, - FPCContract, - GasTokenContract, - SchnorrAccountContract, + KeyRegistryContract, } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; -import { type BalancesFn, expectMapping, getBalancesFn, publicDeployAccounts, setup } from './fixtures/utils.js'; -import { GasPortalTestingHarnessFactory, type IGasBridgingTestHarness } from './shared/gas_portal_test_harness.js'; +import { type BalancesFn, setup } from './fixtures/utils.js'; +import { type IGasBridgingTestHarness } from './shared/gas_portal_test_harness.js'; jest.setTimeout(1_000_000_000); describe('e2e_fees', () => { let wallets: AccountWallet[]; - let aliceWallet: Wallet; - let aliceAddress: AztecAddress; - let bobAddress: AztecAddress; - let sequencerAddress: AztecAddress; - let gasTokenContract: GasTokenContract; - let bananaCoin: BananaCoin; - let bananaFPC: FPCContract; - - let gasBridgeTestHarness: IGasBridgingTestHarness; - - let gasBalances: BalancesFn; - let bananaPublicBalances: BalancesFn; - let bananaPrivateBalances: BalancesFn; + let keyRegistry: KeyRegistryContract; + let deployL1ContractsValues; + let logger; + let pxe; beforeAll(async () => { const { wallets: _wallets, aztecNode, deployL1ContractsValues, logger, pxe } = await setup(3); wallets = _wallets; - await aztecNode.setConfig({ - feeRecipient: wallets.at(-1)!.getAddress(), - }); + // await aztecNode.setConfig({ + // feeRecipient: wallets.at(-1)!.getAddress(), + // }); - aliceWallet = wallets[0]; - aliceAddress = wallets[0].getAddress(); - bobAddress = wallets[1].getAddress(); - sequencerAddress = wallets[2].getAddress(); - - gasTokenContract = gasBridgeTestHarness.l2Token; + keyRegistry = await KeyRegistryContract.deploy(wallets[0]) + .send() + .deployed(); }); - + }); From f976ac044ae67dfb5e23606d05b7732f9550f495 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 12 Apr 2024 12:42:21 +0000 Subject: [PATCH 05/31] adf --- yarn-project/end-to-end/src/e2e_keys.test.ts | 39 -------------------- 1 file changed, 39 deletions(-) delete mode 100644 yarn-project/end-to-end/src/e2e_keys.test.ts diff --git a/yarn-project/end-to-end/src/e2e_keys.test.ts b/yarn-project/end-to-end/src/e2e_keys.test.ts deleted file mode 100644 index 82313bca914..00000000000 --- a/yarn-project/end-to-end/src/e2e_keys.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - type AccountWallet, - type AztecAddress, - type Wallet, -} from '@aztec/aztec.js'; - -import { - KeyRegistryContract, -} from '@aztec/noir-contracts.js'; - -import { jest } from '@jest/globals'; - -import { type BalancesFn, setup } from './fixtures/utils.js'; -import { type IGasBridgingTestHarness } from './shared/gas_portal_test_harness.js'; - -jest.setTimeout(1_000_000_000); - -describe('e2e_fees', () => { - let wallets: AccountWallet[]; - let keyRegistry: KeyRegistryContract; - let deployL1ContractsValues; - let logger; - let pxe; - - beforeAll(async () => { - const { wallets: _wallets, aztecNode, deployL1ContractsValues, logger, pxe } = await setup(3); - wallets = _wallets; - - // await aztecNode.setConfig({ - // feeRecipient: wallets.at(-1)!.getAddress(), - // }); - - keyRegistry = await KeyRegistryContract.deploy(wallets[0]) - .send() - .deployed(); - }); - - -}); From f742400b6308701b6d40b74cfe58d4046304034c Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 12 Apr 2024 14:21:37 +0000 Subject: [PATCH 06/31] test --- .../key_registry_contract/src/main.nr | 107 ++++++------------ .../types/src/address/partial_address.nr | 22 +++- 2 files changed, 57 insertions(+), 72 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 14981a12ca6..d616415dbfb 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -19,11 +19,39 @@ contract KeyRegistry { GENERATOR_INDEX__CONTRACT_ADDRESS, GENERATOR_INDEX__PARTIAL_ADDRESS }, + traits::{ + Serialize, + Deserialize, + } }, }; global KEY_ROTATION_DELAY = 5; + struct PublicKeys { + nullifier_public_key: Field, + incoming_public_key: Field, + outgoing_public_key: Field, + tagging_public_key: Field, + } + + impl Serialize<4> for PublicKeys { + fn serialize(self: Self) -> [Field; 4] { + [self.nullifier_public_key, self.incoming_public_key, self.outgoing_public_key, self.tagging_public_key] + } + } + + impl Deserialize<4> for PublicKeys { + fn deserialize(fields: [Field; 4]) -> Self { + PublicKeys { + nullifier_public_key: fields[0], + incoming_public_key: fields[1], + outgoing_public_key: fields[2], + tagging_public_key: fields[3], + } + } + } + #[aztec(storage)] struct Storage { nullifier_public_key_registry: Map>, @@ -34,51 +62,18 @@ contract KeyRegistry { #[aztec(public)] fn register( - nullifier_public_key: Field, - incoming_public_key: Field, - outgoing_public_key: Field, - tagging_public_key: Field, - ) { - assert((nullifier_public_key != 0) & (incoming_public_key != 0) & (outgoing_public_key != 0) & (tagging_public_key != 0)); - let nullifier_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); - let incoming_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); - let outgoing_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); - let tagging_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); - - nullifier_entry.schedule_value_change(nullifier_public_key); - incoming_entry.schedule_value_change(incoming_public_key); - outgoing_entry.schedule_value_change(outgoing_public_key); - tagging_entry.schedule_value_change(tagging_public_key); - } - - #[aztec(public)] - fn register_from_preimage( address: AztecAddress, - contract_class_id: ContractClassId, - initialization_hash: Field, - salt: Field, - deployer: AztecAddress, - portal_contract_address: EthAddress, - nullifier_public_key: Field, - incoming_public_key: Field, - outgoing_public_key: Field, - tagging_public_key: Field, + partial_address: PartialAddress, + public_keys: PublicKeys, ) { - assert((nullifier_public_key != 0) & (incoming_public_key != 0) & (outgoing_public_key != 0) & (tagging_public_key != 0)); - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("assert_non_membership_public((Field))"), - [address.to_field()], - GasOpts::default() - ).assert_empty(); + let PublicKeys { + nullifier_public_key, + incoming_public_key, + outgoing_public_key, + tagging_public_key + } = public_keys; - let partial_address = PartialAddress::compute( - contract_class_id, - salt, - initialization_hash, - portal_contract_address, - deployer - ); + assert((nullifier_public_key != 0) & (incoming_public_key != 0) & (outgoing_public_key != 0) & (tagging_public_key != 0)); // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); @@ -113,32 +108,4 @@ contract KeyRegistry { outgoing_entry.schedule_value_change(outgoing_public_key); tagging_entry.schedule_value_change(tagging_public_key); } - - #[aztec(public)] - fn assert_non_membership_public( - address: AztecAddress - ) { - let registry_entry = storage.nullifier_public_key_registry.at(address); - let nullifier_key = registry_entry.get_current_value_in_public(); - - assert(nullifier_key == 0); - } - - #[aztec(private)] - fn assert_non_membership_private( - address: AztecAddress - ) { - let registry_entry = storage.nullifier_public_key_registry.at(address); - let nullifier_key = registry_entry.get_current_value_in_private(); - - assert(nullifier_key == 0); - } - - #[aztec(public)] - fn get_nullifying_public_key( - address: AztecAddress - ) { - let registry_entry = storage.nullifier_public_key_registry.at(address); - registry_entry.get_current_value_in_public() - } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index df67b7f6dc2..57473162e8c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -3,8 +3,8 @@ use crate::{ eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash, aztec_address::AztecAddress }, - constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId, - hash::pedersen_hash, traits::ToField + constants::{GENERATOR_INDEX__PARTIAL_ADDRESS, AZTEC_ADDRESS_LENGTH}, contract_class_id::ContractClassId, + hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize} }; // Partial address @@ -18,6 +18,24 @@ impl ToField for PartialAddress { } } +impl FromField for PartialAddress { + fn from_field(value: Field) -> Self { + PartialAddress { inner: value } + } +} + +impl Serialize for PartialAddress { + fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] { + [self.to_field()] + } +} + +impl Deserialize for PartialAddress { + fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self { + FromField::from_field(fields[0]) + } +} + impl PartialAddress { pub fn from_field(field: Field) -> Self { Self { inner: field } From 6a86b9ded07d7ed780584e5eb94da71ff84f4df9 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 12 Apr 2024 14:26:33 +0000 Subject: [PATCH 07/31] fix --- .../contracts/key_registry_contract/src/main.nr | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index d616415dbfb..506b4e1ddc6 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -1,6 +1,6 @@ contract KeyRegistry { + use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; use dep::aztec::{ - avm::hash::poseidon, context::gas::GasOpts, state_vars::{ SharedMutable, @@ -16,8 +16,8 @@ contract KeyRegistry { PartialAddress, }, constants::{ - GENERATOR_INDEX__CONTRACT_ADDRESS, - GENERATOR_INDEX__PARTIAL_ADDRESS + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + GENERATOR_INDEX__PUBLIC_KEYS_HASH }, traits::{ Serialize, @@ -78,21 +78,23 @@ contract KeyRegistry { // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); // let address = AztecAddress::compute(public_keys_hash, partial_address); - let public_keys_hash = poseidon([ + let public_keys_hash = poseidon2_hash([ nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key, - GENERATOR_INDEX__PARTIAL_ADDRESS as Field, + GENERATOR_INDEX__PUBLIC_KEYS_HASH, ], + 5 ); let computed_address = AztecAddress::from_field( - poseidon([ + poseidon2_hash([ public_keys_hash.to_field(), partial_address.to_field(), - GENERATOR_INDEX__CONTRACT_ADDRESS as Field, + GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field, ], + 3 ) ); From b58da6419ee00ecdee2c7ff1e1d57d87b98e4783 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 12 Apr 2024 14:33:13 +0000 Subject: [PATCH 08/31] fix --- .../crates/types/src/address/partial_address.nr | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index 57473162e8c..ec4a1882ccc 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -18,12 +18,6 @@ impl ToField for PartialAddress { } } -impl FromField for PartialAddress { - fn from_field(value: Field) -> Self { - PartialAddress { inner: value } - } -} - impl Serialize for PartialAddress { fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] { [self.to_field()] @@ -32,7 +26,7 @@ impl Serialize for PartialAddress { impl Deserialize for PartialAddress { fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self { - FromField::from_field(fields[0]) + PartialAddress { inner: fields[0] } } } From 32a24e81c1e1468d3b5c5c4b4110d2fe75fede2b Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Fri, 12 Apr 2024 15:24:43 +0000 Subject: [PATCH 09/31] fix ci --- yarn-project/end-to-end/src/cli_docs_sandbox.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn-project/end-to-end/src/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/cli_docs_sandbox.test.ts index 3b0a8e20400..446330a461e 100644 --- a/yarn-project/end-to-end/src/cli_docs_sandbox.test.ts +++ b/yarn-project/end-to-end/src/cli_docs_sandbox.test.ts @@ -117,6 +117,7 @@ FPCContractArtifact GasTokenContractArtifact ImportTestContractArtifact InclusionProofsContractArtifact +KeyRegistryContractArtifact LendingContractArtifact MultiCallEntrypointContractArtifact ParentContractArtifact From 6032daa4faa4bae20432150d8487b270ab2c376b Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 15 Apr 2024 15:47:31 +0000 Subject: [PATCH 10/31] addressing changes --- .../key_registry_contract/src/main.nr | 26 +++++++++---------- .../types/src/address/partial_address.nr | 12 +++++---- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 506b4e1ddc6..b99736be0c7 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -55,9 +55,9 @@ contract KeyRegistry { #[aztec(storage)] struct Storage { nullifier_public_key_registry: Map>, - incoming_public_key_registry: Map>, - outgoing_public_key_registry: Map>, - tagging_public_key_registry: Map>, + // incoming_public_key_registry: Map>, + // outgoing_public_key_registry: Map>, + // tagging_public_key_registry: Map>, } #[aztec(public)] @@ -73,7 +73,7 @@ contract KeyRegistry { tagging_public_key } = public_keys; - assert((nullifier_public_key != 0) & (incoming_public_key != 0) & (outgoing_public_key != 0) & (tagging_public_key != 0)); + assert((nullifier_public_key != 0) & (incoming_public_key != 0) & (outgoing_public_key != 0) & (tagging_public_key != 0), "All keys must be non-zero"); // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); @@ -98,16 +98,16 @@ contract KeyRegistry { ) ); - assert(computed_address.eq(address)); + assert(computed_address.eq(address), "Computed address does not match supplied address"); - let nullifier_entry = storage.nullifier_public_key_registry.at(address); - let incoming_entry = storage.nullifier_public_key_registry.at(address); - let outgoing_entry = storage.nullifier_public_key_registry.at(address); - let tagging_entry = storage.nullifier_public_key_registry.at(address); + let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); + // let incoming_entry = storage.nullifier_public_key_registry.at(address); + // let outgoing_entry = storage.nullifier_public_key_registry.at(address); + // let tagging_entry = storage.nullifier_public_key_registry.at(address); - nullifier_entry.schedule_value_change(nullifier_public_key); - incoming_entry.schedule_value_change(incoming_public_key); - outgoing_entry.schedule_value_change(outgoing_public_key); - tagging_entry.schedule_value_change(tagging_public_key); + nullifier_key_registry.schedule_value_change(nullifier_public_key); + // incoming_entry.schedule_value_change(incoming_public_key); + // outgoing_entry.schedule_value_change(outgoing_public_key); + // tagging_entry.schedule_value_change(tagging_public_key); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index ec4a1882ccc..359fae794ba 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -3,10 +3,12 @@ use crate::{ eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash, aztec_address::AztecAddress }, - constants::{GENERATOR_INDEX__PARTIAL_ADDRESS, AZTEC_ADDRESS_LENGTH}, contract_class_id::ContractClassId, + constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId, hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize} }; +global PARTIAL_ADDRESS_LENGTH = 1; + // Partial address struct PartialAddress { inner : Field @@ -18,14 +20,14 @@ impl ToField for PartialAddress { } } -impl Serialize for PartialAddress { - fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] { +impl Serialize for PartialAddress { + fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] { [self.to_field()] } } -impl Deserialize for PartialAddress { - fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self { +impl Deserialize for PartialAddress { + fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self { PartialAddress { inner: fields[0] } } } From cbda43949e52e82861ac45cddf62b146ef0722a5 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Mon, 15 Apr 2024 18:32:36 +0200 Subject: [PATCH 11/31] feat: add shared mutable access from external contract #5689 (#5758) Resolves #5689 --- .../aztec/src/state_vars/shared_mutable.nr | 2 + .../shared_mutable_private_getter.nr | 68 +++++++++++++++++++ noir-projects/noir-contracts/Nargo.toml | 1 + .../contracts/state_vars_contract/Nargo.toml | 9 +++ .../contracts/state_vars_contract/src/main.nr | 26 +++++++ .../end-to-end/src/e2e_state_vars.test.ts | 43 +++++++++++- 6 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr create mode 100644 noir-projects/noir-contracts/contracts/state_vars_contract/Nargo.toml create mode 100644 noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr 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 fa61113bc78..533639390d8 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,4 +1,6 @@ mod shared_mutable; mod scheduled_value_change; +mod shared_mutable_private_getter; use shared_mutable::SharedMutable; +use shared_mutable_private_getter::SharedMutablePrivateGetter; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr new file mode 100644 index 00000000000..ac49f207c85 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr @@ -0,0 +1,68 @@ +use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress}; + +use crate::context::{PrivateContext, Context}; +use crate::history::public_storage::public_storage_historical_read; +use crate::public_storage; +use crate::state_vars::{storage::Storage, shared_mutable::scheduled_value_change::ScheduledValueChange}; + +struct SharedMutablePrivateGetter { + context: PrivateContext, + // The contract address of the contract we want to read from + contract_address: AztecAddress, + // The storage slot where the SharedMutable is stored on the other contract + storage_slot: Field, +} + +impl SharedMutablePrivateGetter { + pub fn new( + context: PrivateContext, + contract_address: AztecAddress, + storage_slot: Field, + ) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + assert(contract_address.to_field() != 0, "Contract address cannot be 0"); + Self { context, contract_address, storage_slot } + } + + pub fn get_current_value_in_private(self) -> T where T: FromField { + let mut context = self.context; + + let (scheduled_value_change, historical_block_number) = self.historical_read_from_public_storage(context); + let block_horizon = scheduled_value_change.get_block_horizon(historical_block_number); + + // We prevent this transaction from being included in any block after the block horizon, ensuring that the + // historical public value matches the current one, since it can only change after the horizon. + context.set_tx_max_block_number(block_horizon); + scheduled_value_change.get_current_at(historical_block_number) + } + + fn historical_read_from_public_storage( + self, + context: PrivateContext + ) -> (ScheduledValueChange, u32) where T: FromField { + let derived_slot = self.get_derived_storage_slot(); + + // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. + let mut raw_fields = [0; 3]; + for i in 0..3 { + raw_fields[i] = public_storage_historical_read( + context, + derived_slot + i as Field, + self.contract_address + ); + } + + let scheduled_value: ScheduledValueChange = ScheduledValueChange::deserialize(raw_fields); + let historical_block_number = context.historical_header.global_variables.block_number as u32; + + (scheduled_value, historical_block_number) + } + + fn get_derived_storage_slot(self) -> Field { + // Since we're actually storing three values (a ScheduledValueChange struct), we hash the storage slot to get a + // unique location in which we can safely store as much data as we need. This could be removed if we informed + // the slot allocator of how much space we need so that proper padding could be added. + // See https://github.com/AztecProtocol/aztec-packages/issues/5492 + pedersen_hash([self.storage_slot, 0], 0) + } +} diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index b3d1c57c752..7cf2286b66e 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -34,6 +34,7 @@ members = [ "contracts/schnorr_hardcoded_account_contract", "contracts/schnorr_single_key_account_contract", "contracts/slow_tree_contract", + "contracts/state_vars_contract", "contracts/stateful_test_contract", "contracts/test_contract", "contracts/token_contract", diff --git a/noir-projects/noir-contracts/contracts/state_vars_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/state_vars_contract/Nargo.toml new file mode 100644 index 00000000000..7bcf33b2ecf --- /dev/null +++ b/noir-projects/noir-contracts/contracts/state_vars_contract/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "state_vars_contract" +authors = [""] +compiler_version = ">=0.25.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } +authwit = { path = "../../../aztec-nr/authwit" } diff --git a/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr b/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr new file mode 100644 index 00000000000..7cbf988006b --- /dev/null +++ b/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr @@ -0,0 +1,26 @@ +contract StateVars { + use dep::aztec::prelude::{ + AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, + PrivateContext, Map, PublicMutable, PublicImmutable, PrivateMutable, PrivateImmutable, + PrivateSet, SharedImmutable + }; + use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; + + use dep::aztec::{ + state_vars::shared_mutable::SharedMutablePrivateGetter, + context::{PublicContext, Context}, + log::{emit_unencrypted_log_from_private}, + }; + + #[aztec(private)] + fn test_shared_mutable_private_getter( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field, + ) { + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, storage_slot_of_shared_mutable); + let authorized = test.get_current_value_in_private(); + + emit_unencrypted_log_from_private(&mut context, authorized); + } +} diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 56783ceee2e..03ca49a0771 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -1,5 +1,5 @@ -import { type Wallet } from '@aztec/aztec.js'; -import { DocsExampleContract } from '@aztec/noir-contracts.js'; +import { AztecAddress, Fr, type PXE, type Wallet } from '@aztec/aztec.js'; +import { AuthContract, DocsExampleContract, StateVarsContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -8,6 +8,7 @@ import { setup } from './fixtures/utils.js'; const TIMEOUT = 100_000; describe('e2e_state_vars', () => { + let pxe: PXE; jest.setTimeout(TIMEOUT); let wallet: Wallet; @@ -19,7 +20,7 @@ describe('e2e_state_vars', () => { const RANDOMNESS = 2n; beforeAll(async () => { - ({ teardown, wallet } = await setup()); + ({ teardown, wallet, pxe } = await setup(2)); contract = await DocsExampleContract.deploy(wallet).send().deployed(); }, 30_000); @@ -217,4 +218,40 @@ describe('e2e_state_vars', () => { expect(randomness).toEqual(RANDOMNESS); }); }); + + describe('SharedMutablePrivateGetter', () => { + let authContract: AuthContract; + let stateVarsContract: StateVarsContract; + + const delay = async (blocks: number) => { + for (let i = 0; i < blocks; i++) { + await authContract.methods.get_authorized().send().wait(); + } + }; + + beforeAll(async () => { + stateVarsContract = await StateVarsContract.deploy(wallet).send().deployed(); + authContract = await AuthContract.deploy(wallet, wallet.getAddress()).send().deployed(); + }, 30_000); + + it('should set authorized in auth contract', async () => { + await authContract + .withWallet(wallet) + .methods.set_authorized(AztecAddress.fromField(new Fr(6969696969))) + .send() + .wait(); + }); + + it('checks authorized from auth contract from state vars contract', async () => { + await delay(5); + + const { txHash } = await stateVarsContract.methods + .test_shared_mutable_private_getter(authContract.address, 2) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(6969696969)); + }); + }); }); From 8270e0443479f325e6095c9e84923b5133e113e7 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 15 Apr 2024 19:27:08 +0000 Subject: [PATCH 12/31] fix --- .../key_registry_contract/src/main.nr | 4 +- .../end-to-end/src/e2e_key_registry.test.ts | 80 +++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 yarn-project/end-to-end/src/e2e_key_registry.test.ts diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index b99736be0c7..063d1ffc70b 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -80,9 +80,9 @@ contract KeyRegistry { // let address = AztecAddress::compute(public_keys_hash, partial_address); let public_keys_hash = poseidon2_hash([ nullifier_public_key, - tagging_public_key, incoming_public_key, outgoing_public_key, + tagging_public_key, GENERATOR_INDEX__PUBLIC_KEYS_HASH, ], 5 @@ -90,8 +90,8 @@ contract KeyRegistry { let computed_address = AztecAddress::from_field( poseidon2_hash([ - public_keys_hash.to_field(), partial_address.to_field(), + public_keys_hash.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field, ], 3 diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts new file mode 100644 index 00000000000..da176527688 --- /dev/null +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -0,0 +1,80 @@ +import { AztecAddress, Fr, type PXE, type Wallet } from '@aztec/aztec.js'; +import { AuthContract, DocsExampleContract, KeyRegistryContract, StateVarsContract } from '@aztec/noir-contracts.js'; + +import { jest } from '@jest/globals'; + +import { setup } from './fixtures/utils.js'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { GeneratorIndex } from '@aztec/circuits.js'; + +const TIMEOUT = 100_000; + +describe('SharedMutablePrivateGetter', () => { + let keyRegistry: KeyRegistryContract; + let stateVarsContract: StateVarsContract; + let pxe: PXE; + jest.setTimeout(TIMEOUT); + + let wallet: Wallet; + + let teardown: () => Promise; + + // const delay = async (blocks: number) => { + // for (let i = 0; i < blocks; i++) { + // await authContract.methods.get_authorized().send().wait(); + // } + // }; + + beforeAll(async () => { + ({ teardown, wallet, pxe } = await setup(2)); + stateVarsContract = await StateVarsContract.deploy(wallet).send().deployed(); + keyRegistry = await KeyRegistryContract.deploy(wallet).send().deployed(); + }, 30_000); + + afterAll(() => teardown()); + + it('should generate keys', async () => { + const partialAddress = new Fr(69); + + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? + // TODO(#5726): Move the following line to AztecAddress class? + const accountAddressFr = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + await keyRegistry + .withWallet(wallet) + .methods.register(AztecAddress.fromField(accountAddressFr), partialAddress, { + nullifier_public_key: masterNullifierPublicKey, + incoming_public_key: masterIncomingViewingPublicKey, + outgoing_public_key: masterOutgoingViewingPublicKey, + tagging_public_key: masterTaggingPublicKey, + }) + .send() + .wait(); + }); + + // it('checks authorized from auth contract from state vars contract', async () => { + // await delay(5); + + // const { txHash } = await stateVarsContract.methods + // .test_shared_mutable_private_getter(authContract.address, 2) + // .send() + // .wait(); + + // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(6969696969)); + // }); +}); \ No newline at end of file From a84c9bd5d0cb04018b8b78ae2ad9d745571d331c Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Mon, 15 Apr 2024 19:40:20 +0000 Subject: [PATCH 13/31] fix --- .../key_registry_contract/src/main.nr | 6 ++ .../end-to-end/src/e2e_key_registry.test.ts | 72 +++++++++---------- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 063d1ffc70b..807cc56dac3 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -88,6 +88,12 @@ contract KeyRegistry { 5 ); + dep::aztec::oracle::debug_log::debug_log_array_with_prefix("public keys hash", [public_keys_hash]); + dep::aztec::oracle::debug_log::debug_log_array_with_prefix("nullifier", [nullifier_public_key]); + dep::aztec::oracle::debug_log::debug_log_array_with_prefix("incoming", [incoming_public_key]); + dep::aztec::oracle::debug_log::debug_log_array_with_prefix("outgoing", [outgoing_public_key]); + dep::aztec::oracle::debug_log::debug_log_array_with_prefix("tagging", [tagging_public_key]); + let computed_address = AztecAddress::from_field( poseidon2_hash([ partial_address.to_field(), diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index da176527688..78ee1b8afe7 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -19,12 +19,6 @@ describe('SharedMutablePrivateGetter', () => { let teardown: () => Promise; - // const delay = async (blocks: number) => { - // for (let i = 0; i < blocks; i++) { - // await authContract.methods.get_authorized().send().wait(); - // } - // }; - beforeAll(async () => { ({ teardown, wallet, pxe } = await setup(2)); stateVarsContract = await StateVarsContract.deploy(wallet).send().deployed(); @@ -33,38 +27,44 @@ describe('SharedMutablePrivateGetter', () => { afterAll(() => teardown()); - it('should generate keys', async () => { - const partialAddress = new Fr(69); - - const masterNullifierPublicKey = new Fr(12); - const masterIncomingViewingPublicKey = new Fr(34); - const masterOutgoingViewingPublicKey = new Fr(56); - const masterTaggingPublicKey = new Fr(78); + describe('normal flow', () => { + it('should generate keys', async () => { + const partialAddress = new Fr(69); + + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + console.log(publicKeysHash); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? + // TODO(#5726): Move the following line to AztecAddress class? + const accountAddressFr = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + await keyRegistry + .withWallet(wallet) + .methods.register(AztecAddress.fromField(accountAddressFr), partialAddress, { + nullifier_public_key: masterNullifierPublicKey, + incoming_public_key: masterIncomingViewingPublicKey, + outgoing_public_key: masterOutgoingViewingPublicKey, + tagging_public_key: masterTaggingPublicKey, + }) + .send() + .wait(); + }); + }); - const publicKeysHash = poseidon2Hash([ - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - GeneratorIndex.PUBLIC_KEYS_HASH, - ]); - // We hash the partial address and the public keys hash to get the account address - // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? - // TODO(#5726): Move the following line to AztecAddress class? - const accountAddressFr = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); - - await keyRegistry - .withWallet(wallet) - .methods.register(AztecAddress.fromField(accountAddressFr), partialAddress, { - nullifier_public_key: masterNullifierPublicKey, - incoming_public_key: masterIncomingViewingPublicKey, - outgoing_public_key: masterOutgoingViewingPublicKey, - tagging_public_key: masterTaggingPublicKey, - }) - .send() - .wait(); - }); // it('checks authorized from auth contract from state vars contract', async () => { // await delay(5); From ed2466da0664abfd10d4490e0f4e9dc67c94ff9d Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 16 Apr 2024 13:37:57 +0000 Subject: [PATCH 14/31] fix all --- .../shared_mutable_private_getter.nr | 88 +++---- .../key_registry_contract/src/main.nr | 82 +++---- .../contracts/state_vars_contract/src/main.nr | 24 ++ .../noir_js_backend_barretenberg/package.json | 2 +- .../end-to-end/src/e2e_key_registry.test.ts | 221 +++++++++++++++--- 5 files changed, 294 insertions(+), 123 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr index ac49f207c85..e76b215a377 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr @@ -13,56 +13,58 @@ struct SharedMutablePrivateGetter { storage_slot: Field, } +// We have this as a view-only interface to reading Shared Mutables in other contracts. +// Currently the Shared Mutable does not support this. We can adapt SharedMutable at a later date impl SharedMutablePrivateGetter { - pub fn new( - context: PrivateContext, - contract_address: AztecAddress, - storage_slot: Field, - ) -> Self { - assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - assert(contract_address.to_field() != 0, "Contract address cannot be 0"); - Self { context, contract_address, storage_slot } - } + pub fn new( + context: PrivateContext, + contract_address: AztecAddress, + storage_slot: Field, + ) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + assert(contract_address.to_field() != 0, "Contract address cannot be 0"); + Self { context, contract_address, storage_slot } + } - pub fn get_current_value_in_private(self) -> T where T: FromField { - let mut context = self.context; + pub fn get_current_value_in_private(self) -> T where T: FromField { + let mut context = self.context; - let (scheduled_value_change, historical_block_number) = self.historical_read_from_public_storage(context); - let block_horizon = scheduled_value_change.get_block_horizon(historical_block_number); + let (scheduled_value_change, historical_block_number) = self.historical_read_from_public_storage(context); + let block_horizon = scheduled_value_change.get_block_horizon(historical_block_number); - // We prevent this transaction from being included in any block after the block horizon, ensuring that the - // historical public value matches the current one, since it can only change after the horizon. - context.set_tx_max_block_number(block_horizon); - scheduled_value_change.get_current_at(historical_block_number) - } + // We prevent this transaction from being included in any block after the block horizon, ensuring that the + // historical public value matches the current one, since it can only change after the horizon. + context.set_tx_max_block_number(block_horizon); + scheduled_value_change.get_current_at(historical_block_number) + } - fn historical_read_from_public_storage( - self, - context: PrivateContext - ) -> (ScheduledValueChange, u32) where T: FromField { - let derived_slot = self.get_derived_storage_slot(); + fn historical_read_from_public_storage( + self, + context: PrivateContext + ) -> (ScheduledValueChange, u32) where T: FromField { + let derived_slot = self.get_derived_storage_slot(); - // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. - let mut raw_fields = [0; 3]; - for i in 0..3 { - raw_fields[i] = public_storage_historical_read( - context, - derived_slot + i as Field, - self.contract_address - ); - } + // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. + let mut raw_fields = [0; 3]; + for i in 0..3 { + raw_fields[i] = public_storage_historical_read( + context, + derived_slot + i as Field, + self.contract_address + ); + } - let scheduled_value: ScheduledValueChange = ScheduledValueChange::deserialize(raw_fields); - let historical_block_number = context.historical_header.global_variables.block_number as u32; + let scheduled_value: ScheduledValueChange = ScheduledValueChange::deserialize(raw_fields); + let historical_block_number = context.historical_header.global_variables.block_number as u32; - (scheduled_value, historical_block_number) - } + (scheduled_value, historical_block_number) + } - fn get_derived_storage_slot(self) -> Field { - // Since we're actually storing three values (a ScheduledValueChange struct), we hash the storage slot to get a - // unique location in which we can safely store as much data as we need. This could be removed if we informed - // the slot allocator of how much space we need so that proper padding could be added. - // See https://github.com/AztecProtocol/aztec-packages/issues/5492 - pedersen_hash([self.storage_slot, 0], 0) - } + fn get_derived_storage_slot(self) -> Field { + // Since we're actually storing three values (a ScheduledValueChange struct), we hash the storage slot to get a + // unique location in which we can safely store as much data as we need. This could be removed if we informed + // the slot allocator of how much space we need so that proper padding could be added. + // See https://github.com/AztecProtocol/aztec-packages/issues/5492 + pedersen_hash([self.storage_slot, 0], 0) + } } diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 807cc56dac3..1e9a02cf3a7 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -28,32 +28,9 @@ contract KeyRegistry { global KEY_ROTATION_DELAY = 5; - struct PublicKeys { - nullifier_public_key: Field, - incoming_public_key: Field, - outgoing_public_key: Field, - tagging_public_key: Field, - } - - impl Serialize<4> for PublicKeys { - fn serialize(self: Self) -> [Field; 4] { - [self.nullifier_public_key, self.incoming_public_key, self.outgoing_public_key, self.tagging_public_key] - } - } - - impl Deserialize<4> for PublicKeys { - fn deserialize(fields: [Field; 4]) -> Self { - PublicKeys { - nullifier_public_key: fields[0], - incoming_public_key: fields[1], - outgoing_public_key: fields[2], - tagging_public_key: fields[3], - } - } - } - #[aztec(storage)] struct Storage { + // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. nullifier_public_key_registry: Map>, // incoming_public_key_registry: Map>, // outgoing_public_key_registry: Map>, @@ -64,36 +41,39 @@ contract KeyRegistry { fn register( address: AztecAddress, partial_address: PartialAddress, - public_keys: PublicKeys, + original_nullifier_public_key: Field, + original_incoming_public_key: Field, + original_outgoing_public_key: Field, + original_tagging_public_key: Field, + new_nullifier_public_key: Field, + // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. + // new_incoming_public_key: FIeld, + // new_outgoing_public_key: FIeld, + // new_tagging_public_key: FIeld, ) { - let PublicKeys { - nullifier_public_key, - incoming_public_key, - outgoing_public_key, - tagging_public_key - } = public_keys; - - assert((nullifier_public_key != 0) & (incoming_public_key != 0) & (outgoing_public_key != 0) & (tagging_public_key != 0), "All keys must be non-zero"); + assert( + (new_nullifier_public_key != 0), + // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. + // (new_incoming_public_key != 0) & + // (new_outgoing_public_key != 0) & + // (new_tagging_public_key != 0), + "New nullifier public key must be non-zero" + ); // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); // let address = AztecAddress::compute(public_keys_hash, partial_address); + // We could also pass in original_public_keys_hash instead of computing it here, if all we need the original one is for being able to prove ownership of address let public_keys_hash = poseidon2_hash([ - nullifier_public_key, - incoming_public_key, - outgoing_public_key, - tagging_public_key, + original_nullifier_public_key, + original_incoming_public_key, + original_outgoing_public_key, + original_tagging_public_key, GENERATOR_INDEX__PUBLIC_KEYS_HASH, ], 5 ); - dep::aztec::oracle::debug_log::debug_log_array_with_prefix("public keys hash", [public_keys_hash]); - dep::aztec::oracle::debug_log::debug_log_array_with_prefix("nullifier", [nullifier_public_key]); - dep::aztec::oracle::debug_log::debug_log_array_with_prefix("incoming", [incoming_public_key]); - dep::aztec::oracle::debug_log::debug_log_array_with_prefix("outgoing", [outgoing_public_key]); - dep::aztec::oracle::debug_log::debug_log_array_with_prefix("tagging", [tagging_public_key]); - let computed_address = AztecAddress::from_field( poseidon2_hash([ partial_address.to_field(), @@ -107,13 +87,15 @@ contract KeyRegistry { assert(computed_address.eq(address), "Computed address does not match supplied address"); let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); - // let incoming_entry = storage.nullifier_public_key_registry.at(address); - // let outgoing_entry = storage.nullifier_public_key_registry.at(address); - // let tagging_entry = storage.nullifier_public_key_registry.at(address); + // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. + // let incoming_key_registry = storage.incoming_public_key_registry.at(address); + // let outgoing_key_registry = storage.outgoing_public_key_registry.at(address); + // let tagging_key_registry = storage.taggin_public_key_registry.at(address); - nullifier_key_registry.schedule_value_change(nullifier_public_key); - // incoming_entry.schedule_value_change(incoming_public_key); - // outgoing_entry.schedule_value_change(outgoing_public_key); - // tagging_entry.schedule_value_change(tagging_public_key); + nullifier_key_registry.schedule_value_change(new_nullifier_public_key); + // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. + // incoming_key_registry.schedule_value_change(new_incoming_public_key); + // outgoing_key_registry.schedule_value_change(new_outgoing_public_key); + // tagging_key_registry.schedule_value_change(new_tagging_public_key); } } diff --git a/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr b/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr index 7cbf988006b..8b3b5102d47 100644 --- a/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr @@ -12,6 +12,21 @@ contract StateVars { log::{emit_unencrypted_log_from_private}, }; + #[aztec(private)] + fn test_shared_mutable_private_getter_for_registry_contract( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field, + address_to_get_in_registry: AztecAddress, + ) { + // We have to derive this slot to get the location of the shared mutable inside the Map + let derived_slot = dep::aztec::hash::pedersen_hash([storage_slot_of_shared_mutable, address_to_get_in_registry.to_field()], 0); + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); + let nullifier_public_key = registry_private_getter.get_current_value_in_private(); + + emit_unencrypted_log_from_private(&mut context, nullifier_public_key); + } + #[aztec(private)] fn test_shared_mutable_private_getter( contract_address_to_read: AztecAddress, @@ -23,4 +38,13 @@ contract StateVars { emit_unencrypted_log_from_private(&mut context, authorized); } + + #[aztec(public)] + fn delay() { + // We use this as a util function to "mine a block" + dep::aztec::log::emit_unencrypted_log( + &mut context, + "dummy" + ); + } } diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index fefd2f6f8d9..438e91ff302 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -57,4 +57,4 @@ "ts-node": "^10.9.1", "typescript": "5.4.2" } -} \ No newline at end of file +} diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 78ee1b8afe7..76beb286804 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -1,11 +1,11 @@ import { AztecAddress, Fr, type PXE, type Wallet } from '@aztec/aztec.js'; -import { AuthContract, DocsExampleContract, KeyRegistryContract, StateVarsContract } from '@aztec/noir-contracts.js'; +import { GeneratorIndex } from '@aztec/circuits.js'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { KeyRegistryContract, StateVarsContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; import { setup } from './fixtures/utils.js'; -import { poseidon2Hash } from '@aztec/foundation/crypto'; -import { GeneratorIndex } from '@aztec/circuits.js'; const TIMEOUT = 100_000; @@ -25,17 +25,25 @@ describe('SharedMutablePrivateGetter', () => { keyRegistry = await KeyRegistryContract.deploy(wallet).send().deployed(); }, 30_000); + const delay = async (blocks: number) => { + for (let i = 0; i < blocks; i++) { + await stateVarsContract.methods.delay().send().wait(); + } + }; + afterAll(() => teardown()); - describe('normal flow', () => { - it('should generate keys', async () => { + describe('failure cases', () => { + let accountAddedToRegistry: AztecAddress; + + describe('should fail registering with mismatched nullifier public key', () => { const partialAddress = new Fr(69); - + const masterNullifierPublicKey = new Fr(12); const masterIncomingViewingPublicKey = new Fr(34); const masterOutgoingViewingPublicKey = new Fr(56); const masterTaggingPublicKey = new Fr(78); - + const publicKeysHash = poseidon2Hash([ masterNullifierPublicKey, masterIncomingViewingPublicKey, @@ -43,38 +51,193 @@ describe('SharedMutablePrivateGetter', () => { masterTaggingPublicKey, GeneratorIndex.PUBLIC_KEYS_HASH, ]); - - console.log(publicKeysHash); - + // We hash the partial address and the public keys hash to get the account address // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? // TODO(#5726): Move the following line to AztecAddress class? - const accountAddressFr = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); - + accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + it('should fail registering with mismatched address', async () => { + const mismatchedAddress = accountAddedToRegistry.add(new Fr(1)); + + await expect( + keyRegistry + .withWallet(wallet) + .methods.register( + AztecAddress.fromField(mismatchedAddress), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + masterNullifierPublicKey, + ) + .send() + .wait(), + ).rejects.toThrow('Computed address does not match supplied address'); + }); + + it('should fail registering with mismatched nullifier public key', async () => { + const mismatchedMasterNullifierPublicKey = masterNullifierPublicKey.add(new Fr(1)); + + await expect( + keyRegistry + .withWallet(wallet) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + mismatchedMasterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + masterNullifierPublicKey, + ) + .send() + .wait(), + ).rejects.toThrow('Computed address does not match supplied address'); + }); + + it('should fail registering a 0 address', async () => { + await expect( + keyRegistry + .withWallet(wallet) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + new Fr(0), + ) + .send() + .wait(), + ).rejects.toThrow('New nullifier public key must be non-zero'); + }); + }); + }); + + describe('key rotation flow', () => { + let accountAddedToRegistry: AztecAddress; + + it('should generate and register with original keys', async () => { + const partialAddress = new Fr(69); + + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? + // TODO(#5726): Move the following line to AztecAddress class? + accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + await keyRegistry .withWallet(wallet) - .methods.register(AztecAddress.fromField(accountAddressFr), partialAddress, { - nullifier_public_key: masterNullifierPublicKey, - incoming_public_key: masterIncomingViewingPublicKey, - outgoing_public_key: masterOutgoingViewingPublicKey, - tagging_public_key: masterTaggingPublicKey, - }) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + masterNullifierPublicKey, + ) .send() .wait(); }); - }); + it('checks our registry contract from state vars contract and fails because the address has not been registered yet', async () => { + const { txHash } = await stateVarsContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); + }); - // it('checks authorized from auth contract from state vars contract', async () => { - // await delay(5); + it('checks our registry contract from state vars contract and finds the address and associated nullifier public key after a delay', async () => { + await delay(5); - // const { txHash } = await stateVarsContract.methods - // .test_shared_mutable_private_getter(authContract.address, 2) - // .send() - // .wait(); + const { txHash } = await stateVarsContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); + }); + + it('we rotate the nullifier key', async () => { + const partialAddress = new Fr(69); + + // This changes + const oldMasterNullifierPublicKey = new Fr(12); + const newMasterNullifierPublicKey = new Fr(910); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + const publicKeysHash = poseidon2Hash([ + oldMasterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? + // TODO(#5726): Move the following line to AztecAddress class? + accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + await keyRegistry + .withWallet(wallet) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + oldMasterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + newMasterNullifierPublicKey, + ) + .send() + .wait(); + }); + + it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await stateVarsContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); + }); + + it('checks our registry contract from state vars contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await stateVarsContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - // const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - // expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(6969696969)); - // }); -}); \ No newline at end of file + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + }); + }); +}); From ac9adc3d3257e40952929913c30b0e7060d7cff1 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Tue, 16 Apr 2024 08:45:07 -0500 Subject: [PATCH 15/31] Update cli_docs_sandbox.test.ts --- yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts index 446330a461e..1b4b5d5c2c2 100644 --- a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts +++ b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts @@ -129,6 +129,7 @@ SchnorrHardcodedAccountContractArtifact SchnorrSingleKeyAccountContractArtifact SlowTreeContractArtifact StatefulTestContractArtifact +StateVarsContractArtifact TestContractArtifact TokenBlacklistContractArtifact TokenBridgeContractArtifact From 9d3c8315c711b08d6a58cd14eb39b0c1e200aba1 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Tue, 16 Apr 2024 09:40:40 -0500 Subject: [PATCH 16/31] Update cli_docs_sandbox.test.ts --- yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts index 1b4b5d5c2c2..bb66e836b7f 100644 --- a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts +++ b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts @@ -128,8 +128,8 @@ SchnorrAccountContractArtifact SchnorrHardcodedAccountContractArtifact SchnorrSingleKeyAccountContractArtifact SlowTreeContractArtifact -StatefulTestContractArtifact StateVarsContractArtifact +StatefulTestContractArtifact TestContractArtifact TokenBlacklistContractArtifact TokenBridgeContractArtifact From 9e184de64b69c1847ba1c8b594c54a0d8eba2a5a Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 16 Apr 2024 16:18:11 +0000 Subject: [PATCH 17/31] expand comments --- .../key_registry_contract/src/main.nr | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 1e9a02cf3a7..9010a1c559f 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -30,7 +30,8 @@ contract KeyRegistry { #[aztec(storage)] struct Storage { - // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality nullifier_public_key_registry: Map>, // incoming_public_key_registry: Map>, // outgoing_public_key_registry: Map>, @@ -46,15 +47,15 @@ contract KeyRegistry { original_outgoing_public_key: Field, original_tagging_public_key: Field, new_nullifier_public_key: Field, - // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. - // new_incoming_public_key: FIeld, + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality // new_incoming_public_key: FIeld, // new_outgoing_public_key: FIeld, // new_tagging_public_key: FIeld, ) { assert( (new_nullifier_public_key != 0), - // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. - // (new_incoming_public_key != 0) & + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality // (new_incoming_public_key != 0) & // (new_outgoing_public_key != 0) & // (new_tagging_public_key != 0), "New nullifier public key must be non-zero" @@ -87,14 +88,15 @@ contract KeyRegistry { assert(computed_address.eq(address), "Computed address does not match supplied address"); let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); - // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality // let incoming_key_registry = storage.incoming_public_key_registry.at(address); // let outgoing_key_registry = storage.outgoing_public_key_registry.at(address); // let tagging_key_registry = storage.taggin_public_key_registry.at(address); nullifier_key_registry.schedule_value_change(new_nullifier_public_key); - // We are not supporting rotating / changing keys other than the nullifier public in the registry, but may in the future. - // incoming_key_registry.schedule_value_change(new_incoming_public_key); + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality // incoming_key_registry.schedule_value_change(new_incoming_public_key); // outgoing_key_registry.schedule_value_change(new_outgoing_public_key); // tagging_key_registry.schedule_value_change(new_tagging_public_key); } From d39ac15bf16c327f888b9c1f3e2530e8d393875c Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 16 Apr 2024 21:13:07 +0000 Subject: [PATCH 18/31] address comments --- .../key_registry_contract/Nargo.toml | 1 + .../key_registry_contract/src/main.nr | 58 +++++-- .../end-to-end/src/e2e_key_registry.test.ts | 141 ++++++++++-------- 3 files changed, 123 insertions(+), 77 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml index 22f4236171f..cae3a7ead7e 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml @@ -6,3 +6,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } +authwit = { path = "../../../aztec-nr/authwit" } diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 9010a1c559f..7cbf5ca187d 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -1,5 +1,7 @@ contract KeyRegistry { use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; + use dep::authwit::auth::assert_current_call_valid_authwit_public; + use dep::aztec::{ context::gas::GasOpts, state_vars::{ @@ -39,16 +41,12 @@ contract KeyRegistry { } #[aztec(public)] - fn register( + fn rotate_keys( address: AztecAddress, - partial_address: PartialAddress, - original_nullifier_public_key: Field, - original_incoming_public_key: Field, - original_outgoing_public_key: Field, - original_tagging_public_key: Field, new_nullifier_public_key: Field, // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. - // Uncomment lines below to enable that functionality // new_incoming_public_key: FIeld, + // Uncomment lines below to enable that functionality + // new_incoming_public_key: FIeld, // new_outgoing_public_key: FIeld, // new_tagging_public_key: FIeld, ) { @@ -61,15 +59,51 @@ contract KeyRegistry { "New nullifier public key must be non-zero" ); + if (!address.eq(context.msg_sender())) { + assert_current_call_valid_authwit_public(&mut context, address); + } + + let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality + // let incoming_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); + // let outgoing_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); + // let tagging_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); + + nullifier_key_registry.schedule_value_change(new_nullifier_public_key); + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality + // incoming_entry.schedule_value_change(incoming_public_key); + // outgoing_entry.schedule_value_change(outgoing_public_key); + // tagging_entry.schedule_value_change(tagging_public_key); + } + + #[aztec(public)] + fn register_from_preimage( + address: AztecAddress, + partial_address: PartialAddress, + nullifier_public_key: Field, + incoming_public_key: Field, + outgoing_public_key: Field, + tagging_public_key: Field, + ) { + assert( + (nullifier_public_key != 0) & + (incoming_public_key != 0) & + (outgoing_public_key != 0) & + (tagging_public_key != 0), + "All public keys must be non-zero" + ); + // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); // let address = AztecAddress::compute(public_keys_hash, partial_address); // We could also pass in original_public_keys_hash instead of computing it here, if all we need the original one is for being able to prove ownership of address let public_keys_hash = poseidon2_hash([ - original_nullifier_public_key, - original_incoming_public_key, - original_outgoing_public_key, - original_tagging_public_key, + nullifier_public_key, + incoming_public_key, + outgoing_public_key, + tagging_public_key, GENERATOR_INDEX__PUBLIC_KEYS_HASH, ], 5 @@ -94,7 +128,7 @@ contract KeyRegistry { // let outgoing_key_registry = storage.outgoing_public_key_registry.at(address); // let tagging_key_registry = storage.taggin_public_key_registry.at(address); - nullifier_key_registry.schedule_value_change(new_nullifier_public_key); + nullifier_key_registry.schedule_value_change(nullifier_public_key); // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. // Uncomment lines below to enable that functionality // incoming_key_registry.schedule_value_change(new_incoming_public_key); // outgoing_key_registry.schedule_value_change(new_outgoing_public_key); diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 76beb286804..ee1b7d3c54e 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -1,11 +1,11 @@ -import { AztecAddress, Fr, type PXE, type Wallet } from '@aztec/aztec.js'; +import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; import { GeneratorIndex } from '@aztec/circuits.js'; import { poseidon2Hash } from '@aztec/foundation/crypto'; import { KeyRegistryContract, StateVarsContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; -import { setup } from './fixtures/utils.js'; +import { publicDeployAccounts, setup } from './fixtures/utils.js'; const TIMEOUT = 100_000; @@ -15,14 +15,16 @@ describe('SharedMutablePrivateGetter', () => { let pxe: PXE; jest.setTimeout(TIMEOUT); - let wallet: Wallet; + let wallets: AccountWallet[]; let teardown: () => Promise; beforeAll(async () => { - ({ teardown, wallet, pxe } = await setup(2)); - stateVarsContract = await StateVarsContract.deploy(wallet).send().deployed(); - keyRegistry = await KeyRegistryContract.deploy(wallet).send().deployed(); + ({ teardown, pxe, wallets } = await setup(2)); + stateVarsContract = await StateVarsContract.deploy(wallets[0]).send().deployed(); + keyRegistry = await KeyRegistryContract.deploy(wallets[0]).send().deployed(); + + await publicDeployAccounts(wallets[0], wallets.slice(0, 2)); }, 30_000); const delay = async (blocks: number) => { @@ -36,7 +38,7 @@ describe('SharedMutablePrivateGetter', () => { describe('failure cases', () => { let accountAddedToRegistry: AztecAddress; - describe('should fail registering with mismatched nullifier public key', () => { + describe('should fail registering or rotating with bad input', () => { const partialAddress = new Fr(69); const masterNullifierPublicKey = new Fr(12); @@ -62,15 +64,14 @@ describe('SharedMutablePrivateGetter', () => { await expect( keyRegistry - .withWallet(wallet) - .methods.register( + .withWallet(wallets[0]) + .methods.register_from_preimage( AztecAddress.fromField(mismatchedAddress), partialAddress, masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, - masterNullifierPublicKey, ) .send() .wait(), @@ -82,42 +83,41 @@ describe('SharedMutablePrivateGetter', () => { await expect( keyRegistry - .withWallet(wallet) - .methods.register( + .withWallet(wallets[0]) + .methods.register_from_preimage( AztecAddress.fromField(accountAddedToRegistry), partialAddress, mismatchedMasterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, - masterNullifierPublicKey, ) .send() .wait(), ).rejects.toThrow('Computed address does not match supplied address'); }); - it('should fail registering a 0 address', async () => { - await expect( - keyRegistry - .withWallet(wallet) - .methods.register( - AztecAddress.fromField(accountAddedToRegistry), - partialAddress, - masterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - new Fr(0), - ) - .send() - .wait(), - ).rejects.toThrow('New nullifier public key must be non-zero'); + it('should fail when trying to rotate setting a 0 key', async () => { + await expect(keyRegistry.withWallet(wallets[0]).methods.rotate_keys( + wallets[0].getAddress(), + new Fr(0), + ).send().wait()).rejects.toThrow( + 'New nullifier public key must be non-zero', + ); + }); + + it('should fail when trying to rotate for another address without authwit', async () => { + await expect(keyRegistry.withWallet(wallets[0]).methods.rotate_keys( + wallets[1].getAddress(), + new Fr(2), + ).send().wait()).rejects.toThrow( + 'Assertion failed: Message not authorized by account', + ); }); }); }); - describe('key rotation flow', () => { + describe('key registration flow', () => { let accountAddedToRegistry: AztecAddress; it('should generate and register with original keys', async () => { @@ -142,15 +142,14 @@ describe('SharedMutablePrivateGetter', () => { accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); await keyRegistry - .withWallet(wallet) - .methods.register( + .withWallet(wallets[0]) + .methods.register_from_preimage( AztecAddress.fromField(accountAddedToRegistry), partialAddress, masterNullifierPublicKey, masterIncomingViewingPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, - masterNullifierPublicKey, ) .send() .wait(); @@ -178,66 +177,78 @@ describe('SharedMutablePrivateGetter', () => { expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); }); + }); + describe('key rotation flow', () => { it('we rotate the nullifier key', async () => { - const partialAddress = new Fr(69); - // This changes - const oldMasterNullifierPublicKey = new Fr(12); const newMasterNullifierPublicKey = new Fr(910); - const masterIncomingViewingPublicKey = new Fr(34); - const masterOutgoingViewingPublicKey = new Fr(56); - const masterTaggingPublicKey = new Fr(78); - const publicKeysHash = poseidon2Hash([ - oldMasterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - GeneratorIndex.PUBLIC_KEYS_HASH, - ]); + await keyRegistry.withWallet(wallets[0]).methods.rotate_keys( + wallets[0].getAddress(), + newMasterNullifierPublicKey, + ).send().wait(); + }); - // We hash the partial address and the public keys hash to get the account address - // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? - // TODO(#5726): Move the following line to AztecAddress class? - accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await stateVarsContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); - await keyRegistry - .withWallet(wallet) - .methods.register( - AztecAddress.fromField(accountAddedToRegistry), - partialAddress, - oldMasterNullifierPublicKey, - masterIncomingViewingPublicKey, - masterOutgoingViewingPublicKey, - masterTaggingPublicKey, - newMasterNullifierPublicKey, - ) + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + }); + + it('checks our registry contract from state vars contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await stateVarsContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + }); + }); + + describe('key rotation flow with authwit', () => { + it('wallet 0 lets wallet 1 call rotate_keys on his behalf with a pre-defined new public key', async () => { + // This changes + const newMasterNullifierPublicKey = new Fr(420); + + const action = keyRegistry + .withWallet(wallets[1]) + .methods.rotate_keys(wallets[0].getAddress(), newMasterNullifierPublicKey); + + await wallets[0].setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true).send().wait(); + + await action.send().wait(); }); it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { const { txHash } = await stateVarsContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); }); it('checks our registry contract from state vars contract and finds the new nullifier public key that has been rotated', async () => { await delay(5); const { txHash } = await stateVarsContract.methods - .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); const rawLogs = await pxe.getUnencryptedLogs({ txHash }); - expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(420)); }); }); }); From 634c15bc59bd096e15141506410687c0e0b78fe7 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 17 Apr 2024 06:35:26 +0000 Subject: [PATCH 19/31] yarn format --- .../end-to-end/src/e2e_key_registry.test.ts | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index ee1b7d3c54e..003836ed2c4 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -98,21 +98,15 @@ describe('SharedMutablePrivateGetter', () => { }); it('should fail when trying to rotate setting a 0 key', async () => { - await expect(keyRegistry.withWallet(wallets[0]).methods.rotate_keys( - wallets[0].getAddress(), - new Fr(0), - ).send().wait()).rejects.toThrow( - 'New nullifier public key must be non-zero', - ); + await expect( + keyRegistry.withWallet(wallets[0]).methods.rotate_keys(wallets[0].getAddress(), new Fr(0)).send().wait(), + ).rejects.toThrow('New nullifier public key must be non-zero'); }); it('should fail when trying to rotate for another address without authwit', async () => { - await expect(keyRegistry.withWallet(wallets[0]).methods.rotate_keys( - wallets[1].getAddress(), - new Fr(2), - ).send().wait()).rejects.toThrow( - 'Assertion failed: Message not authorized by account', - ); + await expect( + keyRegistry.withWallet(wallets[0]).methods.rotate_keys(wallets[1].getAddress(), new Fr(2)).send().wait(), + ).rejects.toThrow('Assertion failed: Message not authorized by account'); }); }); }); @@ -184,10 +178,11 @@ describe('SharedMutablePrivateGetter', () => { // This changes const newMasterNullifierPublicKey = new Fr(910); - await keyRegistry.withWallet(wallets[0]).methods.rotate_keys( - wallets[0].getAddress(), - newMasterNullifierPublicKey, - ).send().wait(); + await keyRegistry + .withWallet(wallets[0]) + .methods.rotate_keys(wallets[0].getAddress(), newMasterNullifierPublicKey) + .send() + .wait(); }); it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { @@ -223,7 +218,10 @@ describe('SharedMutablePrivateGetter', () => { .withWallet(wallets[1]) .methods.rotate_keys(wallets[0].getAddress(), newMasterNullifierPublicKey); - await wallets[0].setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true).send().wait(); + await wallets[0] + .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) + .send() + .wait(); await action.send().wait(); }); From d663fa8b80a178cf858e5c6b978ebc0e86628adb Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 17 Apr 2024 07:20:23 +0000 Subject: [PATCH 20/31] test --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 003836ed2c4..e7cc067c12e 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -25,7 +25,7 @@ describe('SharedMutablePrivateGetter', () => { keyRegistry = await KeyRegistryContract.deploy(wallets[0]).send().deployed(); await publicDeployAccounts(wallets[0], wallets.slice(0, 2)); - }, 30_000); + }, 120_000); const delay = async (blocks: number) => { for (let i = 0; i < blocks; i++) { From 9ab61ba74fb8b919bfff2d1bee38e2d6654b5258 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:59:25 -0500 Subject: [PATCH 21/31] Update yarn-project/end-to-end/src/e2e_key_registry.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index e7cc067c12e..4baa1dae4c5 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -46,6 +46,7 @@ describe('SharedMutablePrivateGetter', () => { const masterOutgoingViewingPublicKey = new Fr(56); const masterTaggingPublicKey = new Fr(78); + // TODO(#5726): use computePublicKeysHash function const publicKeysHash = poseidon2Hash([ masterNullifierPublicKey, masterIncomingViewingPublicKey, From 2f7e4920f74c338e4c1042e5b5f9ce80b898c0ef Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:59:37 -0500 Subject: [PATCH 22/31] Update yarn-project/end-to-end/src/e2e_key_registry.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 4baa1dae4c5..51a17feaf30 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -186,7 +186,7 @@ describe('SharedMutablePrivateGetter', () => { .wait(); }); - it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { const { txHash } = await stateVarsContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() From d9e61c728db0eb91773f742c38d2ca449c4611da Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:59:47 -0500 Subject: [PATCH 23/31] Update yarn-project/end-to-end/src/e2e_key_registry.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 51a17feaf30..977d3790955 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -227,7 +227,7 @@ describe('SharedMutablePrivateGetter', () => { await action.send().wait(); }); - it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { const { txHash } = await stateVarsContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() From 51180e3080d4d3920caba7f339e1e9b734ac4670 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:59:54 -0500 Subject: [PATCH 24/31] Update yarn-project/end-to-end/src/e2e_key_registry.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 977d3790955..e2a936c8dc8 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -132,7 +132,6 @@ describe('SharedMutablePrivateGetter', () => { ]); // We hash the partial address and the public keys hash to get the account address - // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? // TODO(#5726): Move the following line to AztecAddress class? accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); From 4918f41bfc7c2c8c799c812097e653ae1d706c7f Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:00:37 -0500 Subject: [PATCH 25/31] Update yarn-project/end-to-end/src/e2e_key_registry.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index e2a936c8dc8..7523da6d93a 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -61,7 +61,7 @@ describe('SharedMutablePrivateGetter', () => { accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); it('should fail registering with mismatched address', async () => { - const mismatchedAddress = accountAddedToRegistry.add(new Fr(1)); + const mismatchedAddress = Fr.random(); await expect( keyRegistry From 8867e5e3fa03e51b1e66ef0a2198b7c9d429c9f2 Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:00:45 -0500 Subject: [PATCH 26/31] Update yarn-project/end-to-end/src/e2e_key_registry.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 7523da6d93a..25603850341 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -80,7 +80,7 @@ describe('SharedMutablePrivateGetter', () => { }); it('should fail registering with mismatched nullifier public key', async () => { - const mismatchedMasterNullifierPublicKey = masterNullifierPublicKey.add(new Fr(1)); + const mismatchedMasterNullifierPublicKey = Fr.random(); await expect( keyRegistry From 78093cd77a947ad6079f4a26f415ad08306de73e Mon Sep 17 00:00:00 2001 From: esau <152162806+sklppy88@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:00:58 -0500 Subject: [PATCH 27/31] Update yarn-project/end-to-end/src/e2e_key_registry.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jan Beneš --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 25603850341..31376819ffd 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -56,7 +56,6 @@ describe('SharedMutablePrivateGetter', () => { ]); // We hash the partial address and the public keys hash to get the account address - // TODO(#5726): Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1? // TODO(#5726): Move the following line to AztecAddress class? accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); From 2b1b5cbc699ac47d8c2d4f70b2498816aaa49ddb Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 17 Apr 2024 18:06:54 +0000 Subject: [PATCH 28/31] address comments --- .../shared_mutable_private_getter.nr | 10 ++-- noir-projects/noir-contracts/Nargo.toml | 1 - .../key_registry_contract/src/main.nr | 27 ++-------- .../contracts/state_vars_contract/Nargo.toml | 9 ---- .../contracts/state_vars_contract/src/main.nr | 50 ------------------- .../contracts/test_contract/src/main.nr | 39 +++++++++++++++ .../src/composed/cli_docs_sandbox.test.ts | 1 - .../end-to-end/src/e2e_key_registry.test.ts | 36 ++++++------- .../end-to-end/src/e2e_state_vars.test.ts | 31 ++++++++---- 9 files changed, 88 insertions(+), 116 deletions(-) delete mode 100644 noir-projects/noir-contracts/contracts/state_vars_contract/Nargo.toml delete mode 100644 noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr index e76b215a377..2f4f4339481 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr @@ -8,7 +8,7 @@ use crate::state_vars::{storage::Storage, shared_mutable::scheduled_value_change struct SharedMutablePrivateGetter { context: PrivateContext, // The contract address of the contract we want to read from - contract_address: AztecAddress, + other_contract_address: AztecAddress, // The storage slot where the SharedMutable is stored on the other contract storage_slot: Field, } @@ -18,12 +18,12 @@ struct SharedMutablePrivateGetter { impl SharedMutablePrivateGetter { pub fn new( context: PrivateContext, - contract_address: AztecAddress, + other_contract_address: AztecAddress, storage_slot: Field, ) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - assert(contract_address.to_field() != 0, "Contract address cannot be 0"); - Self { context, contract_address, storage_slot } + assert(other_contract_address.to_field() != 0, "Other contract address cannot be 0"); + Self { context, other_contract_address, storage_slot } } pub fn get_current_value_in_private(self) -> T where T: FromField { @@ -50,7 +50,7 @@ impl SharedMutablePrivateGetter { raw_fields[i] = public_storage_historical_read( context, derived_slot + i as Field, - self.contract_address + self.other_contract_address ); } diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index 7cf2286b66e..b3d1c57c752 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -34,7 +34,6 @@ members = [ "contracts/schnorr_hardcoded_account_contract", "contracts/schnorr_single_key_account_contract", "contracts/slow_tree_contract", - "contracts/state_vars_contract", "contracts/stateful_test_contract", "contracts/test_contract", "contracts/token_contract", diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index 7cbf5ca187d..8f2810f3dbf 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -41,22 +41,13 @@ contract KeyRegistry { } #[aztec(public)] - fn rotate_keys( + fn rotate_nullifier_public_key( address: AztecAddress, new_nullifier_public_key: Field, - // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. - // Uncomment lines below to enable that functionality - // new_incoming_public_key: FIeld, - // new_outgoing_public_key: FIeld, - // new_tagging_public_key: FIeld, ) { assert( - (new_nullifier_public_key != 0), - // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. - // Uncomment lines below to enable that functionality // (new_incoming_public_key != 0) & - // (new_outgoing_public_key != 0) & - // (new_tagging_public_key != 0), - "New nullifier public key must be non-zero" + new_nullifier_public_key != 0, + "New nullifier public key must be non-zero" ); if (!address.eq(context.msg_sender())) { @@ -64,22 +55,12 @@ contract KeyRegistry { } let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); - // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. - // Uncomment lines below to enable that functionality - // let incoming_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); - // let outgoing_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); - // let tagging_entry = storage.nullifier_public_key_registry.at(context.msg_sender()); nullifier_key_registry.schedule_value_change(new_nullifier_public_key); - // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. - // Uncomment lines below to enable that functionality - // incoming_entry.schedule_value_change(incoming_public_key); - // outgoing_entry.schedule_value_change(outgoing_public_key); - // tagging_entry.schedule_value_change(tagging_public_key); } #[aztec(public)] - fn register_from_preimage( + fn register( address: AztecAddress, partial_address: PartialAddress, nullifier_public_key: Field, diff --git a/noir-projects/noir-contracts/contracts/state_vars_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/state_vars_contract/Nargo.toml deleted file mode 100644 index 7bcf33b2ecf..00000000000 --- a/noir-projects/noir-contracts/contracts/state_vars_contract/Nargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "state_vars_contract" -authors = [""] -compiler_version = ">=0.25.0" -type = "contract" - -[dependencies] -aztec = { path = "../../../aztec-nr/aztec" } -authwit = { path = "../../../aztec-nr/authwit" } diff --git a/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr b/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr deleted file mode 100644 index 8b3b5102d47..00000000000 --- a/noir-projects/noir-contracts/contracts/state_vars_contract/src/main.nr +++ /dev/null @@ -1,50 +0,0 @@ -contract StateVars { - use dep::aztec::prelude::{ - AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, - PrivateContext, Map, PublicMutable, PublicImmutable, PrivateMutable, PrivateImmutable, - PrivateSet, SharedImmutable - }; - use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; - - use dep::aztec::{ - state_vars::shared_mutable::SharedMutablePrivateGetter, - context::{PublicContext, Context}, - log::{emit_unencrypted_log_from_private}, - }; - - #[aztec(private)] - fn test_shared_mutable_private_getter_for_registry_contract( - contract_address_to_read: AztecAddress, - storage_slot_of_shared_mutable: Field, - address_to_get_in_registry: AztecAddress, - ) { - // We have to derive this slot to get the location of the shared mutable inside the Map - let derived_slot = dep::aztec::hash::pedersen_hash([storage_slot_of_shared_mutable, address_to_get_in_registry.to_field()], 0); - // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); - let nullifier_public_key = registry_private_getter.get_current_value_in_private(); - - emit_unencrypted_log_from_private(&mut context, nullifier_public_key); - } - - #[aztec(private)] - fn test_shared_mutable_private_getter( - contract_address_to_read: AztecAddress, - storage_slot_of_shared_mutable: Field, - ) { - // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly - let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, storage_slot_of_shared_mutable); - let authorized = test.get_current_value_in_private(); - - emit_unencrypted_log_from_private(&mut context, authorized); - } - - #[aztec(public)] - fn delay() { - // We use this as a util function to "mine a block" - dep::aztec::log::emit_unencrypted_log( - &mut context, - "dummy" - ); - } -} diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 663cafa4860..5e04f66e65f 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -9,6 +9,9 @@ contract Test { abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTES_PER_PAGE} }; + + use dep::aztec::state_vars::shared_mutable::SharedMutablePrivateGetter; + // docs:start:unencrypted_import use dep::aztec::prelude::emit_unencrypted_log; // docs:end:unencrypted_import @@ -388,6 +391,42 @@ contract Test { constant.value } + #[aztec(private)] + fn test_shared_mutable_private_getter_for_registry_contract( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field, + address_to_get_in_registry: AztecAddress, + ) { + // We have to derive this slot to get the location of the shared mutable inside the Map + let derived_slot = dep::aztec::hash::pedersen_hash([storage_slot_of_shared_mutable, address_to_get_in_registry.to_field()], 0); + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); + let nullifier_public_key = registry_private_getter.get_current_value_in_private(); + + emit_unencrypted_log_from_private(&mut context, nullifier_public_key); + } + + #[aztec(private)] + fn test_shared_mutable_private_getter( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field, + ) { + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, storage_slot_of_shared_mutable); + let authorized = test.get_current_value_in_private(); + + emit_unencrypted_log_from_private(&mut context, authorized); + } + + #[aztec(public)] + fn delay() { + // We use this as a util function to "mine a block" + dep::aztec::log::emit_unencrypted_log( + &mut context, + "dummy" + ); + } + // Purely exists for testing unconstrained fn get_random(kinda_seed: Field) -> pub Field { kinda_seed * unsafe_rand() diff --git a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts index bb66e836b7f..446330a461e 100644 --- a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts +++ b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts @@ -128,7 +128,6 @@ SchnorrAccountContractArtifact SchnorrHardcodedAccountContractArtifact SchnorrSingleKeyAccountContractArtifact SlowTreeContractArtifact -StateVarsContractArtifact StatefulTestContractArtifact TestContractArtifact TokenBlacklistContractArtifact diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 31376819ffd..57f9864f961 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -1,7 +1,7 @@ import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; import { GeneratorIndex } from '@aztec/circuits.js'; import { poseidon2Hash } from '@aztec/foundation/crypto'; -import { KeyRegistryContract, StateVarsContract } from '@aztec/noir-contracts.js'; +import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -11,7 +11,7 @@ const TIMEOUT = 100_000; describe('SharedMutablePrivateGetter', () => { let keyRegistry: KeyRegistryContract; - let stateVarsContract: StateVarsContract; + let testContract: TestContract; let pxe: PXE; jest.setTimeout(TIMEOUT); @@ -21,7 +21,7 @@ describe('SharedMutablePrivateGetter', () => { beforeAll(async () => { ({ teardown, pxe, wallets } = await setup(2)); - stateVarsContract = await StateVarsContract.deploy(wallets[0]).send().deployed(); + testContract = await TestContract.deploy(wallets[0]).send().deployed(); keyRegistry = await KeyRegistryContract.deploy(wallets[0]).send().deployed(); await publicDeployAccounts(wallets[0], wallets.slice(0, 2)); @@ -29,7 +29,7 @@ describe('SharedMutablePrivateGetter', () => { const delay = async (blocks: number) => { for (let i = 0; i < blocks; i++) { - await stateVarsContract.methods.delay().send().wait(); + await testContract.methods.delay().send().wait(); } }; @@ -65,7 +65,7 @@ describe('SharedMutablePrivateGetter', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.register_from_preimage( + .methods.register( AztecAddress.fromField(mismatchedAddress), partialAddress, masterNullifierPublicKey, @@ -84,7 +84,7 @@ describe('SharedMutablePrivateGetter', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.register_from_preimage( + .methods.register( AztecAddress.fromField(accountAddedToRegistry), partialAddress, mismatchedMasterNullifierPublicKey, @@ -99,13 +99,13 @@ describe('SharedMutablePrivateGetter', () => { it('should fail when trying to rotate setting a 0 key', async () => { await expect( - keyRegistry.withWallet(wallets[0]).methods.rotate_keys(wallets[0].getAddress(), new Fr(0)).send().wait(), + keyRegistry.withWallet(wallets[0]).methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)).send().wait(), ).rejects.toThrow('New nullifier public key must be non-zero'); }); it('should fail when trying to rotate for another address without authwit', async () => { await expect( - keyRegistry.withWallet(wallets[0]).methods.rotate_keys(wallets[1].getAddress(), new Fr(2)).send().wait(), + keyRegistry.withWallet(wallets[0]).methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)).send().wait(), ).rejects.toThrow('Assertion failed: Message not authorized by account'); }); }); @@ -136,7 +136,7 @@ describe('SharedMutablePrivateGetter', () => { await keyRegistry .withWallet(wallets[0]) - .methods.register_from_preimage( + .methods.register( AztecAddress.fromField(accountAddedToRegistry), partialAddress, masterNullifierPublicKey, @@ -149,7 +149,7 @@ describe('SharedMutablePrivateGetter', () => { }); it('checks our registry contract from state vars contract and fails because the address has not been registered yet', async () => { - const { txHash } = await stateVarsContract.methods + const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) .send() .wait(); @@ -161,7 +161,7 @@ describe('SharedMutablePrivateGetter', () => { it('checks our registry contract from state vars contract and finds the address and associated nullifier public key after a delay', async () => { await delay(5); - const { txHash } = await stateVarsContract.methods + const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) .send() .wait(); @@ -179,13 +179,13 @@ describe('SharedMutablePrivateGetter', () => { await keyRegistry .withWallet(wallets[0]) - .methods.rotate_keys(wallets[0].getAddress(), newMasterNullifierPublicKey) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) .send() .wait(); }); it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - const { txHash } = await stateVarsContract.methods + const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); @@ -197,7 +197,7 @@ describe('SharedMutablePrivateGetter', () => { it('checks our registry contract from state vars contract and finds the new nullifier public key that has been rotated', async () => { await delay(5); - const { txHash } = await stateVarsContract.methods + const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); @@ -209,13 +209,13 @@ describe('SharedMutablePrivateGetter', () => { }); describe('key rotation flow with authwit', () => { - it('wallet 0 lets wallet 1 call rotate_keys on his behalf with a pre-defined new public key', async () => { + it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { // This changes const newMasterNullifierPublicKey = new Fr(420); const action = keyRegistry .withWallet(wallets[1]) - .methods.rotate_keys(wallets[0].getAddress(), newMasterNullifierPublicKey); + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey); await wallets[0] .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) @@ -226,7 +226,7 @@ describe('SharedMutablePrivateGetter', () => { }); it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { - const { txHash } = await stateVarsContract.methods + const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); @@ -238,7 +238,7 @@ describe('SharedMutablePrivateGetter', () => { it('checks our registry contract from state vars contract and finds the new nullifier public key that has been rotated', async () => { await delay(5); - const { txHash } = await stateVarsContract.methods + const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() .wait(); diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 03ca49a0771..b96b9e9beea 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -1,5 +1,5 @@ import { AztecAddress, Fr, type PXE, type Wallet } from '@aztec/aztec.js'; -import { AuthContract, DocsExampleContract, StateVarsContract } from '@aztec/noir-contracts.js'; +import { AuthContract, DocsExampleContract, TestContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -221,7 +221,7 @@ describe('e2e_state_vars', () => { describe('SharedMutablePrivateGetter', () => { let authContract: AuthContract; - let stateVarsContract: StateVarsContract; + let testContract: TestContract; const delay = async (blocks: number) => { for (let i = 0; i < blocks; i++) { @@ -230,26 +230,39 @@ describe('e2e_state_vars', () => { }; beforeAll(async () => { - stateVarsContract = await StateVarsContract.deploy(wallet).send().deployed(); + testContract = await TestContract.deploy(wallet).send().deployed(); + // We use the auth contract here because has a nice, clear, simple implementation of the Shared Mutable, + // and we will need to read from it to test our private getter. authContract = await AuthContract.deploy(wallet, wallet.getAddress()).send().deployed(); - }, 30_000); - it('should set authorized in auth contract', async () => { + // We set the authorized value here, knowing there will be some delay before the value change takes place await authContract - .withWallet(wallet) - .methods.set_authorized(AztecAddress.fromField(new Fr(6969696969))) + .withWallet(wallet) + .methods.set_authorized(AztecAddress.fromField(new Fr(6969696969))) + .send() + .wait(); + }, 30_000); + + it('checks authorized in auth contract from test contract and finds the old value because the change hasn\'t been applied yet', async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter(authContract.address, 2) .send() .wait(); + + // The function above emits an unencrypted log as a means of returning the data + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); }); - it('checks authorized from auth contract from state vars contract', async () => { + it('checks authorized in auth contract from test contract and finds the correctly set value', async () => { await delay(5); - const { txHash } = await stateVarsContract.methods + const { txHash } = await testContract.methods .test_shared_mutable_private_getter(authContract.address, 2) .send() .wait(); + // The function above emits an unencrypted log as a means of returning the data const rawLogs = await pxe.getUnencryptedLogs({ txHash }); expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(6969696969)); }); From b655e76f229dc3cab1971fc9fd100e1df94a720b Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 17 Apr 2024 18:11:55 +0000 Subject: [PATCH 29/31] yarn format --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 12 ++++++++++-- yarn-project/end-to-end/src/e2e_state_vars.test.ts | 10 +++++----- yarn-project/tsconfig.json | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 57f9864f961..5c1d467b672 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -99,13 +99,21 @@ describe('SharedMutablePrivateGetter', () => { it('should fail when trying to rotate setting a 0 key', async () => { await expect( - keyRegistry.withWallet(wallets[0]).methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)).send().wait(), + keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)) + .send() + .wait(), ).rejects.toThrow('New nullifier public key must be non-zero'); }); it('should fail when trying to rotate for another address without authwit', async () => { await expect( - keyRegistry.withWallet(wallets[0]).methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)).send().wait(), + keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)) + .send() + .wait(), ).rejects.toThrow('Assertion failed: Message not authorized by account'); }); }); diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index b96b9e9beea..f673150cc6f 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -237,13 +237,13 @@ describe('e2e_state_vars', () => { // We set the authorized value here, knowing there will be some delay before the value change takes place await authContract - .withWallet(wallet) - .methods.set_authorized(AztecAddress.fromField(new Fr(6969696969))) - .send() - .wait(); + .withWallet(wallet) + .methods.set_authorized(AztecAddress.fromField(new Fr(6969696969))) + .send() + .wait(); }, 30_000); - it('checks authorized in auth contract from test contract and finds the old value because the change hasn\'t been applied yet', async () => { + it("checks authorized in auth contract from test contract and finds the old value because the change hasn't been applied yet", async () => { const { txHash } = await testContract.methods .test_shared_mutable_private_getter(authContract.address, 2) .send() diff --git a/yarn-project/tsconfig.json b/yarn-project/tsconfig.json index 95f7ccc5cee..eafb807f772 100644 --- a/yarn-project/tsconfig.json +++ b/yarn-project/tsconfig.json @@ -16,7 +16,7 @@ "resolveJsonModule": true, "composite": true, "skipLibCheck": true, - "noImplicitOverride": true, + "noImplicitOverride": true }, "references": [ { "path": "accounts/tsconfig.json" }, From bb4b7cb0625efbdd1838eb2e53888cad1477bb98 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 17 Apr 2024 18:14:30 +0000 Subject: [PATCH 30/31] fix --- .../end-to-end/src/e2e_key_registry.test.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index 5c1d467b672..df4f5879ae6 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -38,7 +38,7 @@ describe('SharedMutablePrivateGetter', () => { describe('failure cases', () => { let accountAddedToRegistry: AztecAddress; - describe('should fail registering or rotating with bad input', () => { + describe('should fail registering with bad input', () => { const partialAddress = new Fr(69); const masterNullifierPublicKey = new Fr(12); @@ -96,7 +96,9 @@ describe('SharedMutablePrivateGetter', () => { .wait(), ).rejects.toThrow('Computed address does not match supplied address'); }); + }); + describe('should fail when rotating keys with bad input', () => { it('should fail when trying to rotate setting a 0 key', async () => { await expect( keyRegistry @@ -116,7 +118,7 @@ describe('SharedMutablePrivateGetter', () => { .wait(), ).rejects.toThrow('Assertion failed: Message not authorized by account'); }); - }); + }) }); describe('key registration flow', () => { @@ -156,7 +158,7 @@ describe('SharedMutablePrivateGetter', () => { .wait(); }); - it('checks our registry contract from state vars contract and fails because the address has not been registered yet', async () => { + it('checks our registry contract from test contract and fails because the address has not been registered yet', async () => { const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) .send() @@ -166,7 +168,7 @@ describe('SharedMutablePrivateGetter', () => { expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); }); - it('checks our registry contract from state vars contract and finds the address and associated nullifier public key after a delay', async () => { + it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { await delay(5); const { txHash } = await testContract.methods @@ -192,7 +194,7 @@ describe('SharedMutablePrivateGetter', () => { .wait(); }); - it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() @@ -202,7 +204,7 @@ describe('SharedMutablePrivateGetter', () => { expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); }); - it('checks our registry contract from state vars contract and finds the new nullifier public key that has been rotated', async () => { + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { await delay(5); const { txHash } = await testContract.methods @@ -233,7 +235,7 @@ describe('SharedMutablePrivateGetter', () => { await action.send().wait(); }); - it("checks our registry contract from state vars contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { const { txHash } = await testContract.methods .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) .send() @@ -243,7 +245,7 @@ describe('SharedMutablePrivateGetter', () => { expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); }); - it('checks our registry contract from state vars contract and finds the new nullifier public key that has been rotated', async () => { + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { await delay(5); const { txHash } = await testContract.methods From 96ed013648f21c2860a9997011be146e2e35f799 Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Wed, 17 Apr 2024 18:50:48 +0000 Subject: [PATCH 31/31] yarn fmt --- yarn-project/end-to-end/src/e2e_key_registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index df4f5879ae6..37f6ac8cea5 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -118,7 +118,7 @@ describe('SharedMutablePrivateGetter', () => { .wait(), ).rejects.toThrow('Assertion failed: Message not authorized by account'); }); - }) + }); }); describe('key registration flow', () => {