From d51309954ab4a5ae1c829c86185b02c156baf3c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Tue, 12 Nov 2024 07:40:03 -0600 Subject: [PATCH] refactor: token partial notes refactor pt. 2 - bridging (#9600) --- l1-contracts/test/portals/TokenPortal.sol | 30 +++------ l1-contracts/test/portals/TokenPortal.t.sol | 14 +---- l1-contracts/test/portals/UniswapPortal.sol | 10 +-- l1-contracts/test/portals/UniswapPortal.t.sol | 14 +---- .../contracts/test_contract/src/main.nr | 4 +- .../token_bridge_contract/src/main.nr | 61 +++++++++---------- .../contracts/token_contract/src/main.nr | 26 +++++--- .../token_contract/src/test/utils.nr | 5 +- .../token_portal_content_hash_lib/src/lib.nr | 17 +++--- .../contracts/uniswap_contract/src/main.nr | 2 - .../contracts/uniswap_contract/src/util.nr | 20 +++--- yarn-project/aztec.js/src/index.ts | 2 +- .../aztec.js/src/utils/portal_manager.ts | 35 +++++------ yarn-project/aztec/src/examples/token.ts | 3 +- yarn-project/bot/src/factory.ts | 3 +- .../src/benchmarks/bench_prover.test.ts | 3 +- .../src/benchmarks/bench_tx_size_fees.test.ts | 3 +- .../token_bridge_failure_cases.test.ts | 13 ++-- .../token_bridge_private.test.ts | 43 ++----------- .../token_bridge_public_to_private.test.ts | 4 +- .../src/e2e_fees/private_payments.test.ts | 6 +- .../private_transfer_recursion.test.ts | 3 +- .../end-to-end/src/fixtures/token_utils.ts | 3 +- .../end-to-end/src/guides/up_quick_start.sh | 2 +- .../writing_an_account_contract.test.ts | 3 +- .../end-to-end/src/sample-dapp/index.mjs | 3 +- yarn-project/end-to-end/src/shared/browser.ts | 3 +- .../src/shared/cross_chain_test_harness.ts | 28 +++------ .../end-to-end/src/shared/uniswap_l1_l2.ts | 21 +------ .../src/protocol_contract_data.ts | 4 +- .../src/client/private_execution.test.ts | 6 +- 31 files changed, 151 insertions(+), 243 deletions(-) diff --git a/l1-contracts/test/portals/TokenPortal.sol b/l1-contracts/test/portals/TokenPortal.sol index 674b007ce95..d9bd3280946 100644 --- a/l1-contracts/test/portals/TokenPortal.sol +++ b/l1-contracts/test/portals/TokenPortal.sol @@ -22,11 +22,7 @@ contract TokenPortal { ); event DepositToAztecPrivate( - bytes32 secretHashForRedeemingMintedNotes, - uint256 amount, - bytes32 secretHashForL2MessageConsumption, - bytes32 key, - uint256 index + uint256 amount, bytes32 secretHashForL2MessageConsumption, bytes32 key, uint256 index ); IRegistry public registry; @@ -76,26 +72,22 @@ contract TokenPortal { // docs:start:deposit_private /** * @notice Deposit funds into the portal and adds an L2 message which can only be consumed privately on Aztec - * @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec. The hash should be 254 bits (so it can fit in a Field element) * @param _amount - The amount to deposit * @param _secretHashForL2MessageConsumption - The hash of the secret consumable L1 to L2 message. The hash should be 254 bits (so it can fit in a Field element) * @return The key of the entry in the Inbox and its leaf index */ - function depositToAztecPrivate( - bytes32 _secretHashForRedeemingMintedNotes, - uint256 _amount, - bytes32 _secretHashForL2MessageConsumption - ) external returns (bytes32, uint256) { + function depositToAztecPrivate(uint256 _amount, bytes32 _secretHashForL2MessageConsumption) + external + returns (bytes32, uint256) + { // Preamble IInbox inbox = IRollup(registry.getRollup()).INBOX(); DataStructures.L2Actor memory actor = DataStructures.L2Actor(l2Bridge, 1); - // Hash the message content to be reconstructed in the receiving contract - bytes32 contentHash = Hash.sha256ToField( - abi.encodeWithSignature( - "mint_private(bytes32,uint256)", _secretHashForRedeemingMintedNotes, _amount - ) - ); + // Hash the message content to be reconstructed in the receiving contract - the signature below does not correspond + // to a real function. It's just an identifier of an action. + bytes32 contentHash = + Hash.sha256ToField(abi.encodeWithSignature("mint_private(uint256)", _amount)); // Hold the tokens in the portal underlying.safeTransferFrom(msg.sender, address(this), _amount); @@ -105,9 +97,7 @@ contract TokenPortal { inbox.sendL2Message(actor, contentHash, _secretHashForL2MessageConsumption); // Emit event - emit DepositToAztecPrivate( - _secretHashForRedeemingMintedNotes, _amount, _secretHashForL2MessageConsumption, key, index - ); + emit DepositToAztecPrivate(_amount, _secretHashForL2MessageConsumption, key, index); return (key, index); } diff --git a/l1-contracts/test/portals/TokenPortal.t.sol b/l1-contracts/test/portals/TokenPortal.t.sol index 105de7afe29..ba5fa33c0c0 100644 --- a/l1-contracts/test/portals/TokenPortal.t.sol +++ b/l1-contracts/test/portals/TokenPortal.t.sol @@ -49,9 +49,6 @@ contract TokenPortalTest is Test { // this hash is just a random 32 byte string bytes32 internal secretHashForL2MessageConsumption = 0x147e4fec49805c924e28150fc4b36824679bc17ecb1d7d9f6a9effb7fde6b6a0; - // this hash is just a random 32 byte string - bytes32 internal secretHashForRedeemingMintedNotes = - 0x157e4fec49805c924e28150fc4b36824679bc17ecb1d7d9f6a9effb7fde6b6a0; // params for withdraw: address internal recipient = address(0xdead); @@ -94,11 +91,7 @@ contract TokenPortalTest is Test { return DataStructures.L1ToL2Msg({ sender: DataStructures.L1Actor(address(tokenPortal), block.chainid), recipient: DataStructures.L2Actor(l2TokenAddress, 1), - content: Hash.sha256ToField( - abi.encodeWithSignature( - "mint_private(bytes32,uint256)", secretHashForRedeemingMintedNotes, amount - ) - ), + content: Hash.sha256ToField(abi.encodeWithSignature("mint_private(uint256)", amount)), secretHash: secretHashForL2MessageConsumption, index: _index }); @@ -137,9 +130,8 @@ contract TokenPortalTest is Test { // event we will get // Perform op - (bytes32 leaf, uint256 index) = tokenPortal.depositToAztecPrivate( - secretHashForRedeemingMintedNotes, amount, secretHashForL2MessageConsumption - ); + (bytes32 leaf, uint256 index) = + tokenPortal.depositToAztecPrivate(amount, secretHashForL2MessageConsumption); assertEq(leaf, expectedLeaf, "returned leaf and calculated leaf should match"); assertEq(index, expectedIndex, "returned index and calculated index should match"); diff --git a/l1-contracts/test/portals/UniswapPortal.sol b/l1-contracts/test/portals/UniswapPortal.sol index fc6bebd74a4..a4eb66d8b80 100644 --- a/l1-contracts/test/portals/UniswapPortal.sol +++ b/l1-contracts/test/portals/UniswapPortal.sol @@ -158,7 +158,6 @@ contract UniswapPortal { * @param _uniswapFeeTier - The fee tier for the swap on UniswapV3 * @param _outputTokenPortal - The ethereum address of the output token portal * @param _amountOutMinimum - The minimum amount of output assets to receive from the swap (slippage protection) - * @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec. The hash should be 254 bits (so it can fit in a Field element) * @param _secretHashForL1ToL2Message - The hash of the secret consumable message. The hash should be 254 bits (so it can fit in a Field element) * @param _withCaller - When true, using `msg.sender` as the caller, otherwise address(0) * @return A hash of the L1 to L2 message inserted in the Inbox @@ -169,7 +168,6 @@ contract UniswapPortal { uint24 _uniswapFeeTier, address _outputTokenPortal, uint256 _amountOutMinimum, - bytes32 _secretHashForRedeemingMintedNotes, bytes32 _secretHashForL1ToL2Message, bool _withCaller, // Avoiding stack too deep @@ -195,13 +193,12 @@ contract UniswapPortal { // prevent stack too deep errors vars.contentHash = Hash.sha256ToField( abi.encodeWithSignature( - "swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,address)", + "swap_private(address,uint256,uint24,address,uint256,bytes32,address)", _inputTokenPortal, _inAmount, _uniswapFeeTier, _outputTokenPortal, _amountOutMinimum, - _secretHashForRedeemingMintedNotes, _secretHashForL1ToL2Message, _withCaller ? msg.sender : address(0) ) @@ -247,9 +244,8 @@ contract UniswapPortal { vars.outputAsset.approve(address(_outputTokenPortal), amountOut); // Deposit the output asset to the L2 via its portal - return TokenPortal(_outputTokenPortal).depositToAztecPrivate( - _secretHashForRedeemingMintedNotes, amountOut, _secretHashForL1ToL2Message - ); + return + TokenPortal(_outputTokenPortal).depositToAztecPrivate(amountOut, _secretHashForL1ToL2Message); } } // docs:end:solidity_uniswap_swap_private diff --git a/l1-contracts/test/portals/UniswapPortal.t.sol b/l1-contracts/test/portals/UniswapPortal.t.sol index 84afe101e34..bf37ae19e64 100644 --- a/l1-contracts/test/portals/UniswapPortal.t.sol +++ b/l1-contracts/test/portals/UniswapPortal.t.sol @@ -44,7 +44,6 @@ contract UniswapPortalTest is Test { uint24 internal uniswapFeePool = 3000; // 0.3% fee uint256 internal amountOutMinimum = 0; bytes32 internal aztecRecipient = bytes32(uint256(0x3)); - bytes32 internal secretHashForRedeemingMintedNotes = bytes32(uint256(0x4)); uint256 internal l2BlockNumber = 69; @@ -140,26 +139,21 @@ contract UniswapPortalTest is Test { /** * L2 to L1 message to be added to the outbox - - * @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec * @param _caller - designated caller on L1 that will call the swap function - typically address(this) * Set to address(0) if anyone can call. */ - function _createUniswapSwapMessagePrivate( - bytes32 _secretHashForRedeemingMintedNotes, - address _caller - ) internal view returns (bytes32) { + function _createUniswapSwapMessagePrivate(address _caller) internal view returns (bytes32) { DataStructures.L2ToL1Msg memory message = DataStructures.L2ToL1Msg({ sender: DataStructures.L2Actor(l2UniswapAddress, 1), recipient: DataStructures.L1Actor(address(uniswapPortal), block.chainid), content: Hash.sha256ToField( abi.encodeWithSignature( - "swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,address)", + "swap_private(address,uint256,uint24,address,uint256,bytes32,address)", address(daiTokenPortal), amount, uniswapFeePool, address(wethTokenPortal), amountOutMinimum, - _secretHashForRedeemingMintedNotes, secretHash, _caller ) @@ -572,8 +566,7 @@ contract UniswapPortalTest is Test { }) ]; - bytes32 messageHashPortalChecksAgainst = - _createUniswapSwapMessagePrivate(secretHashForRedeemingMintedNotes, address(this)); + bytes32 messageHashPortalChecksAgainst = _createUniswapSwapMessagePrivate(address(this)); bytes32 actualRoot; bytes32 consumedRoot; @@ -607,7 +600,6 @@ contract UniswapPortalTest is Test { uniswapFeePool, address(wethTokenPortal), amountOutMinimum, - secretHashForRedeemingMintedNotes, secretHash, true, outboxMessageMetadata 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 8b745370265..723239b18d0 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -386,15 +386,13 @@ contract Test { #[private] fn consume_mint_private_message( - secret_hash_for_redeeming_minted_notes: Field, amount: Field, secret_for_L1_to_L2_message_consumption: Field, portal_address: EthAddress, message_leaf_index: Field, ) { // Consume L1 to L2 message and emit nullifier - let content_hash = - get_mint_private_content_hash(secret_hash_for_redeeming_minted_notes, amount); + let content_hash = get_mint_private_content_hash(amount); context.consume_l1_to_l2_message( content_hash, secret_for_L1_to_L2_message_consumption, diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index 4ef9953c938..b5a75ad1623 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -9,7 +9,7 @@ use dep::aztec::macros::aztec; #[aztec] contract TokenBridge { - use dep::aztec::prelude::{AztecAddress, EthAddress, PublicMutable, SharedImmutable}; + use dep::aztec::prelude::{AztecAddress, EthAddress, SharedImmutable}; use dep::token_portal_content_hash_lib::{ get_mint_private_content_hash, get_mint_public_content_hash, get_withdraw_content_hash, @@ -27,7 +27,7 @@ contract TokenBridge { // Storage structure, containing all storage, and specifying what slots they use. #[storage] struct Storage { - token: PublicMutable, + token: SharedImmutable, portal_address: SharedImmutable, } @@ -35,7 +35,7 @@ contract TokenBridge { #[public] #[initializer] fn constructor(token: AztecAddress, portal_address: EthAddress) { - storage.token.write(token); + storage.token.initialize(token); storage.portal_address.initialize(portal_address); } // docs:end:token_bridge_storage_and_constructor @@ -65,7 +65,7 @@ contract TokenBridge { ); // Mint tokens - Token::at(storage.token.read()).mint_public(to, amount).call(&mut context); + Token::at(storage.token.read_public()).mint_public(to, amount).call(&mut context); } // docs:end:claim_public @@ -84,25 +84,26 @@ contract TokenBridge { context.message_portal(storage.portal_address.read_public(), content); // Burn tokens - Token::at(storage.token.read()).burn_public(context.msg_sender(), amount, nonce).call( - &mut context, - ); + Token::at(storage.token.read_public()) + .burn_public(context.msg_sender(), amount, nonce) + .call(&mut context); } // docs:end:exit_to_l1_public + // docs:start:claim_private - // Consumes a L1->L2 message and calls the token contract to mint the appropriate amount in private assets - // User needs to call token.redeem_shield() to get the private assets - // TODO(#8416): Consider creating a truly private claim flow. + /// Claims the bridged tokens and makes them accessible in private. Note that recipient's address is not revealed + /// but the amount is. Hence it's most likely possible to determine to which L1 deposit this claim corresponds to + /// (unless there are multiple pending deposits of the same amount). + /// TODO(#8416): Consider creating a truly private claim flow. #[private] fn claim_private( - secret_hash_for_redeeming_minted_notes: Field, // secret hash used to redeem minted notes at a later time. This enables anyone to call this function and mint tokens to a user on their behalf + recipient: AztecAddress, // recipient of the bridged tokens amount: Field, secret_for_L1_to_L2_message_consumption: Field, // secret used to consume the L1 to L2 message message_leaf_index: Field, ) { // Consume L1 to L2 message and emit nullifier - let content_hash = - get_mint_private_content_hash(secret_hash_for_redeeming_minted_notes, amount); + let content_hash = get_mint_private_content_hash(amount); context.consume_l1_to_l2_message( content_hash, secret_for_L1_to_L2_message_consumption, @@ -110,13 +111,15 @@ contract TokenBridge { message_leaf_index, ); - // Mint tokens on L2 - // `mint_private` on token is public. So we call an internal public function - // which then calls the public method on the token contract. - // Since the secret_hash is passed, no secret is leaked. - TokenBridge::at(context.this_address()) - ._call_mint_on_token(amount, secret_hash_for_redeeming_minted_notes) - .enqueue(&mut context); + // Read the token address from storage + let token_address = storage.token.read_private(); + + // At last we mint the tokens + // docs:start:call_mint_on_token + Token::at(token_address).mint_to_private(context.msg_sender(), recipient, amount).call( + &mut context, + ); + // docs:end:call_mint_on_token } // docs:end:claim_private @@ -147,26 +150,18 @@ contract TokenBridge { #[public] #[view] fn get_token() -> AztecAddress { - storage.token.read() + storage.token.read_public() } // docs:end:get_token - // docs:start:call_mint_on_token - // This is a public call as we need to read from public storage. - // Also, note that user hashes their secret in private and only sends the hash in public - // meaning only user can `redeem_shield` at a later time with their secret. - #[public] - #[internal] - fn _call_mint_on_token(amount: Field, secret_hash: Field) { - Token::at(storage.token.read()).mint_private_old(amount, secret_hash).call(&mut context); - } - // docs:end:call_mint_on_token - // docs:start:assert_token_is_same #[public] #[internal] fn _assert_token_is_same(token: AztecAddress) { - assert(storage.token.read().eq(token), "Token address is not the same as seen in storage"); + assert( + storage.token.read_public().eq(token), + "Token address is not the same as seen in storage", + ); } // docs:end:assert_token_is_same } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index 4492b78f1e8..d7d33b87c64 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -478,7 +478,7 @@ contract Token { let token = Token::at(context.this_address()); // We prepare the transfer. - let hiding_point_slot = _prepare_transfer_to_private(to, &mut context, storage); + let hiding_point_slot = _prepare_transfer_to_private(from, to, &mut context, storage); // At last we finalize the transfer. Usage of the `unsafe` method here is safe because we set the `from` // function argument to a message sender, guaranteeing that he can transfer only his own tokens. @@ -491,7 +491,8 @@ contract Token { /// finalized by calling `finalize_transfer_to_private`. Returns a hiding point slot. #[private] fn prepare_transfer_to_private(to: AztecAddress) -> Field { - _prepare_transfer_to_private(to, &mut context, storage) + let from = context.msg_sender(); + _prepare_transfer_to_private(from, to, &mut context, storage) } /// This function exists separately from `prepare_transfer_to_private` solely as an optimization as it allows @@ -501,6 +502,7 @@ contract Token { /// function. #[contract_library_method] fn _prepare_transfer_to_private( + from: AztecAddress, // recipient of the outgoing: TODO(#9887): this is not great? to: AztecAddress, context: &mut PrivateContext, storage: Storage<&mut PrivateContext>, @@ -513,10 +515,9 @@ contract Token { let note_randomness = unsafe { random() }; let note_setup_payload = UintNote::setup_payload().new(to, note_randomness, to_note_slot); - // We set the ovpk to the message sender's ovpk and we encrypt the log. - let from_ovpk = get_public_keys(context.msg_sender()).ovpk_m; - let setup_log = - note_setup_payload.encrypt_log(context, from_ovpk, to, context.msg_sender()); + // We get the keys and encrypt the log of the note + let from_ovpk = get_public_keys(from).ovpk_m; + let setup_log = note_setup_payload.encrypt_log(context, from_ovpk, to, from); // Using the x-coordinate as a hiding point slot is safe against someone else interfering with it because // we have a guarantee that the public functions of the transaction are executed right after the private ones @@ -590,17 +591,22 @@ contract Token { /// Mints token `amount` to a private balance of `to`. Message sender has to have minter permissions (checked /// in the enqueud call). #[private] - fn mint_to_private(to: AztecAddress, amount: Field) { - let from = context.msg_sender(); + fn mint_to_private( + from: AztecAddress, // recipient of the outgoing: TODO(#9887): this is not great? + to: AztecAddress, + amount: Field, + ) { let token = Token::at(context.this_address()); // We prepare the transfer. - let hiding_point_slot = _prepare_transfer_to_private(to, &mut context, storage); + let hiding_point_slot = _prepare_transfer_to_private(from, to, &mut context, storage); // At last we finalize the mint. Usage of the `unsafe` method here is safe because we set the `from` // function argument to a message sender, guaranteeing that only a message sender with minter permissions // can successfully execute the function. - token._finalize_mint_to_private_unsafe(from, amount, hiding_point_slot).enqueue(&mut context); + token + ._finalize_mint_to_private_unsafe(context.msg_sender(), amount, hiding_point_slot) + .enqueue(&mut context); } /// Finalizes a mint of token `amount` to a private balance of `to`. The mint must be prepared by calling diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr index 53f894c85b5..893e659706f 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr @@ -78,7 +78,10 @@ pub unconstrained fn mint_private( let note_randomness = random(); let _ = OracleMock::mock("getRandomField").returns(note_randomness); - Token::at(token_contract_address).mint_to_private(recipient, amount).call(&mut env.private()); + let from = recipient; // we are setting from to recipient because of TODO(#9887) + Token::at(token_contract_address).mint_to_private(from, recipient, amount).call( + &mut env.private(), + ); add_token_note( env, diff --git a/noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr b/noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr index f7789aefcd5..c31f6c4e0a9 100644 --- a/noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr +++ b/noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr @@ -29,23 +29,20 @@ pub fn get_mint_public_content_hash(owner: AztecAddress, amount: Field) -> Field // Computes a content hash of a deposit/mint_private message. // Refer TokenPortal.sol for reference on L1. pub fn get_mint_private_content_hash( - secret_hash_for_redeeming_minted_notes: Field, amount: Field ) -> Field { - let mut hash_bytes = [0; 68]; - let secret_hash_bytes:[u8; 32] = secret_hash_for_redeeming_minted_notes.to_be_bytes(); + let mut hash_bytes = [0; 36]; let amount_bytes:[u8; 32] = amount.to_be_bytes(); for i in 0..32 { - hash_bytes[i + 4] = secret_hash_bytes[i]; - hash_bytes[i + 36] = amount_bytes[i]; + hash_bytes[i + 4] = amount_bytes[i]; } - // Function selector: 0xefa012c1 keccak256('mint_private(bytes32,uint256)') - hash_bytes[0] = 0xef; - hash_bytes[1] = 0xa0; - hash_bytes[2] = 0x12; - hash_bytes[3] = 0xc1; + // Function selector: 0xb81559e2 keccak256('mint_private(uint256)') + hash_bytes[0] = 0xb8; + hash_bytes[1] = 0x15; + hash_bytes[2] = 0x59; + hash_bytes[3] = 0xe2; let content_hash = sha256_to_field(hash_bytes); content_hash diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr index a9219a45144..f95c986983d 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -121,7 +121,6 @@ contract Uniswap { uniswap_fee_tier: Field, // which uniswap tier to use (eg 3000 for 0.3% fee) minimum_output_amount: Field, // minimum output amount to receive (slippage protection for the swap) // params for the depositing output_asset back to Aztec - secret_hash_for_redeeming_minted_notes: Field, // secret hash used to redeem minted notes at a later time. This enables anyone to call this function and mint tokens to a user on their behalf secret_hash_for_L1_to_l2_message: Field, // for when l1 uniswap portal inserts the message to consume output assets on L2 caller_on_L1: EthAddress, // ethereum address that can call this function on the L1 portal (0x0 if anyone can call) ) { @@ -172,7 +171,6 @@ contract Uniswap { uniswap_fee_tier, output_asset_bridge_portal_address, minimum_output_amount, - secret_hash_for_redeeming_minted_notes, secret_hash_for_L1_to_l2_message, caller_on_L1, ); diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr index 8d93994d624..a0e2ca12774 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr @@ -58,11 +58,10 @@ pub fn compute_swap_private_content_hash( uniswap_fee_tier: Field, output_asset_bridge_portal_address: EthAddress, minimum_output_amount: Field, - secret_hash_for_redeeming_minted_notes: Field, secret_hash_for_L1_to_l2_message: Field, caller_on_L1: EthAddress, ) -> Field { - let mut hash_bytes = [0; 260]; // 8 fields of 32 bytes each + 4 bytes fn selector + let mut hash_bytes = [0; 228]; // 7 fields of 32 bytes each + 4 bytes fn selector let input_token_portal_bytes: [u8; 32] = input_asset_bridge_portal_address.to_field().to_be_bytes(); let in_amount_bytes: [u8; 32] = input_amount.to_be_bytes(); @@ -70,17 +69,15 @@ pub fn compute_swap_private_content_hash( let output_token_portal_bytes: [u8; 32] = output_asset_bridge_portal_address.to_field().to_be_bytes(); let amount_out_min_bytes: [u8; 32] = minimum_output_amount.to_be_bytes(); - let secret_hash_for_redeeming_minted_notes_bytes: [u8; 32] = - secret_hash_for_redeeming_minted_notes.to_be_bytes(); let secret_hash_for_L1_to_l2_message_bytes: [u8; 32] = secret_hash_for_L1_to_l2_message.to_be_bytes(); let caller_on_L1_bytes: [u8; 32] = caller_on_L1.to_field().to_be_bytes(); - // function selector: 0x16f416eb keccak256("swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,address)") - hash_bytes[0] = 0x16; - hash_bytes[1] = 0xf4; - hash_bytes[2] = 0x16; - hash_bytes[3] = 0xeb; + // function selector: 0x84e55078 keccak256("swap_private(address,uint256,uint24,address,uint256,bytes32,address)") + hash_bytes[0] = 0x84; + hash_bytes[1] = 0xe5; + hash_bytes[2] = 0x50; + hash_bytes[3] = 0x78; for i in 0..32 { hash_bytes[i + 4] = input_token_portal_bytes[i]; @@ -88,9 +85,8 @@ pub fn compute_swap_private_content_hash( hash_bytes[i + 68] = uniswap_fee_tier_bytes[i]; hash_bytes[i + 100] = output_token_portal_bytes[i]; hash_bytes[i + 132] = amount_out_min_bytes[i]; - hash_bytes[i + 164] = secret_hash_for_redeeming_minted_notes_bytes[i]; - hash_bytes[i + 196] = secret_hash_for_L1_to_l2_message_bytes[i]; - hash_bytes[i + 228] = caller_on_L1_bytes[i]; + hash_bytes[i + 164] = secret_hash_for_L1_to_l2_message_bytes[i]; + hash_bytes[i + 196] = caller_on_L1_bytes[i]; } let content_hash = sha256_to_field(hash_bytes); content_hash diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 52595470936..79b4fc59c26 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -62,7 +62,7 @@ export { type FunctionSelectorLike, type L2AmountClaim, type L2Claim, - type L2RedeemableAmountClaim, + type L2AmountClaimWithRecipient, type WrappedFieldLike, } from './utils/index.js'; diff --git a/yarn-project/aztec.js/src/utils/portal_manager.ts b/yarn-project/aztec.js/src/utils/portal_manager.ts index 3953f32f54e..7d3c3d2bae2 100644 --- a/yarn-project/aztec.js/src/utils/portal_manager.ts +++ b/yarn-project/aztec.js/src/utils/portal_manager.ts @@ -38,10 +38,9 @@ export type L2Claim = { /** L1 to L2 message info that corresponds to an amount to claim. */ export type L2AmountClaim = L2Claim & { /** Amount to claim */ claimAmount: Fr }; -/** L1 to L2 message info that corresponds to an amount to claim with associated notes to be redeemed. */ -export type L2RedeemableAmountClaim = L2AmountClaim & { - /** Secret for redeeming the minted notes */ redeemSecret: Fr; - /** Hash of the redeem secret*/ redeemSecretHash: Fr; +/** L1 to L2 message info that corresponds to an amount to claim with associated recipient. */ +export type L2AmountClaimWithRecipient = L2AmountClaim & { + /** Address that will receive the newly minted notes. */ recipient: AztecAddress; }; /** Stringifies an eth address for logging. */ @@ -279,17 +278,15 @@ export class L1ToL2TokenPortalManager { * @param amount - Amount of tokens to send. * @param mint - Whether to mint the tokens before sending (only during testing). */ - public async bridgeTokensPrivate(to: AztecAddress, amount: bigint, mint = false): Promise { + public async bridgeTokensPrivate( + to: AztecAddress, + amount: bigint, + mint = false, + ): Promise { const [claimSecret, claimSecretHash] = await this.bridgeSetup(amount, mint); - const redeemSecret = Fr.random(); - const redeemSecretHash = computeSecretHash(redeemSecret); this.logger.info('Sending L1 tokens to L2 to be claimed privately'); - const { request } = await this.portal.simulate.depositToAztecPrivate([ - redeemSecretHash.toString(), - amount, - claimSecretHash.toString(), - ]); + const { request } = await this.portal.simulate.depositToAztecPrivate([amount, claimSecretHash.toString()]); const txReceipt = await this.publicClient.waitForTransactionReceipt({ hash: await this.walletClient.writeContract(request), @@ -300,21 +297,19 @@ export class L1ToL2TokenPortalManager { this.portal.address, this.portal.abi, 'DepositToAztecPrivate', - log => - log.args.secretHashForRedeemingMintedNotes === redeemSecretHash.toString() && - log.args.amount === amount && - log.args.secretHashForL2MessageConsumption === claimSecretHash.toString(), + log => log.args.amount === amount && log.args.secretHashForL2MessageConsumption === claimSecretHash.toString(), this.logger, ); - this.logger.info(`Redeem shield secret: ${redeemSecret.toString()}, secret hash: ${redeemSecretHash.toString()}`); + this.logger.info( + `Claim message secret: ${claimSecret.toString()}, claim message secret hash: ${claimSecretHash.toString()}`, + ); return { claimAmount: new Fr(amount), claimSecret, claimSecretHash, - redeemSecret, - redeemSecretHash, + recipient: to, messageHash: log.args.key, messageLeafIndex: log.args.index, }; @@ -329,7 +324,7 @@ export class L1ToL2TokenPortalManager { } } -/** Helper for interacting with a test TokenPortal on L1 for both withdrawing from and briding to L2. */ +/** Helper for interacting with a test TokenPortal on L1 for both withdrawing from and bridging to L2. */ export class L1TokenPortalManager extends L1ToL2TokenPortalManager { private readonly outbox: GetContractReturnType>; diff --git a/yarn-project/aztec/src/examples/token.ts b/yarn-project/aztec/src/examples/token.ts index 754640d49e2..763eb40540d 100644 --- a/yarn-project/aztec/src/examples/token.ts +++ b/yarn-project/aztec/src/examples/token.ts @@ -41,7 +41,8 @@ async function main() { // Mint tokens to Alice logger.info(`Minting ${ALICE_MINT_BALANCE} more coins to Alice...`); - await tokenAlice.methods.mint_to_private(aliceWallet.getAddress(), ALICE_MINT_BALANCE).send().wait(); + const from = aliceWallet.getAddress(); // we are setting from to Alice here because of TODO(#9887) + await tokenAlice.methods.mint_to_private(from, aliceWallet.getAddress(), ALICE_MINT_BALANCE).send().wait(); logger.info(`${ALICE_MINT_BALANCE} tokens were successfully minted by Alice and transferred to private`); diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index 053dfb8f04b..e59910700e5 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -147,9 +147,10 @@ export class BotFactory { if (privateBalance < MIN_BALANCE) { this.log.info(`Minting private tokens for ${sender.toString()}`); + const from = sender; // we are setting from to sender here because of TODO(#9887) calls.push( isStandardToken - ? token.methods.mint_to_private(sender, MINT_BALANCE).request() + ? token.methods.mint_to_private(from, sender, MINT_BALANCE).request() : token.methods.mint(MINT_BALANCE, sender, sender).request(), ); } diff --git a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts index 082f7575bf5..7148d1be742 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts @@ -112,10 +112,11 @@ describe('benchmarks/proving', () => { initialFpContract.address, ); + const from = initialSchnorrWallet.getAddress(); // we are setting from to initial schnorr wallet here because of TODO(#9887) await Promise.all([ initialGasContract.methods.claim(initialFpContract.address, 1e12, claimSecret, messageLeafIndex).send().wait(), initialTokenContract.methods.mint_public(initialSchnorrWallet.getAddress(), 1e12).send().wait(), - initialTokenContract.methods.mint_to_private(initialSchnorrWallet.getAddress(), 1e12).send().wait(), + initialTokenContract.methods.mint_to_private(from, initialSchnorrWallet.getAddress(), 1e12).send().wait(), ]); }); diff --git a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts index 0ccea5c9fde..ab248cca561 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts @@ -71,7 +71,8 @@ describe('benchmarks/tx_size_fees', () => { feeJuice.methods.claim(fpc.address, 100e9, fpcSecret, fpcLeafIndex).send().wait(), feeJuice.methods.claim(aliceWallet.getAddress(), 100e9, aliceSecret, aliceLeafIndex).send().wait(), ]); - await token.methods.mint_to_private(aliceWallet.getAddress(), 100e9).send().wait(); + const from = aliceWallet.getAddress(); // we are setting from to Alice here because of TODO(#9887) + await token.methods.mint_to_private(from, aliceWallet.getAddress(), 100e9).send().wait(); await token.methods.mint_public(aliceWallet.getAddress(), 100e9).send().wait(); }); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_failure_cases.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_failure_cases.test.ts index f0a0e64c90b..cac9f75b106 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_failure_cases.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_failure_cases.test.ts @@ -50,24 +50,25 @@ describe('e2e_cross_chain_messaging token_bridge_failure_cases', () => { await crossChainTestHarness.makeMessageConsumable(claim.messageHash); // Wrong message hash - const content = sha256ToField([ - Buffer.from(toFunctionSelector('mint_private(bytes32,uint256)').substring(2), 'hex'), - claim.claimSecretHash, - new Fr(bridgeAmount), + const wrongBridgeAmount = bridgeAmount + 1n; + const wrongMessageContent = sha256ToField([ + Buffer.from(toFunctionSelector('mint_private(uint256)').substring(2), 'hex'), + new Fr(wrongBridgeAmount), ]); const wrongMessage = new L1ToL2Message( new L1Actor(crossChainTestHarness.tokenPortalAddress, crossChainTestHarness.publicClient.chain.id), new L2Actor(l2Bridge.address, 1), - content, + wrongMessageContent, claim.claimSecretHash, new Fr(claim.messageLeafIndex), ); + // Sending wrong secret hashes should fail: await expect( l2Bridge .withWallet(user2Wallet) - .methods.claim_private(claim.claimSecretHash, bridgeAmount, claim.claimSecret, claim.messageLeafIndex) + .methods.claim_private(ownerAddress, wrongBridgeAmount, claim.claimSecret, claim.messageLeafIndex) .prove(), ).rejects.toThrow(`No L1 to L2 message found for message hash ${wrongMessage.hash().toString()}`); }, 60_000); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts index 4ba54c6760d..87af389c0e3 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_private.test.ts @@ -1,9 +1,7 @@ -import { Fr, L1Actor, L1ToL2Message, L2Actor } from '@aztec/aztec.js'; -import { sha256ToField } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/aztec.js'; import { RollupAbi } from '@aztec/l1-artifacts'; import { getContract } from 'viem'; -import { toFunctionSelector } from 'viem/utils'; import { CrossChainMessagingTest } from './cross_chain_messaging_test.js'; @@ -63,8 +61,6 @@ describe('e2e_cross_chain_messaging token_bridge_private', () => { // 3. Consume L1 -> L2 message and mint private tokens on L2 await crossChainTestHarness.consumeMessageOnAztecAndMintPrivately(claim); - // tokens were minted privately in a TransparentNote which the owner (person who knows the secret) must redeem: - await crossChainTestHarness.redeemShieldPrivatelyOnL2(bridgeAmount, claim.redeemSecret); await crossChainTestHarness.expectPrivateBalanceOnL2(ownerAddress, bridgeAmount); // time to withdraw the funds again! @@ -105,7 +101,8 @@ describe('e2e_cross_chain_messaging token_bridge_private', () => { }); // docs:end:e2e_private_cross_chain - it('Someone else can mint funds to me on my behalf (privately)', async () => { + // This test checks that it's enough to have the claim secret to claim the funds to whoever we want. + it('Claim secret is enough to consume the message', async () => { const l1TokenBalance = 1000000n; const bridgeAmount = 100n; @@ -116,43 +113,13 @@ describe('e2e_cross_chain_messaging token_bridge_private', () => { // Wait for the message to be available for consumption await crossChainTestHarness.makeMessageConsumable(claim.messageHash); - // 3. Consume L1 -> L2 message and mint private tokens on L2 - const content = sha256ToField([ - Buffer.from(toFunctionSelector('mint_private(bytes32,uint256)').substring(2), 'hex'), - claim.claimSecretHash, - new Fr(bridgeAmount), - ]); - - const wrongMessage = new L1ToL2Message( - new L1Actor(crossChainTestHarness.tokenPortalAddress, crossChainTestHarness.publicClient.chain.id), - new L2Actor(l2Bridge.address, 1), - content, - claim.claimSecretHash, - new Fr(claim.messageLeafIndex), - ); - - // Sending wrong secret hashes should fail: - await expect( - l2Bridge - .withWallet(user2Wallet) - .methods.claim_private(claim.claimSecretHash, bridgeAmount, claim.claimSecret, claim.messageLeafIndex) - .prove(), - ).rejects.toThrow(`No L1 to L2 message found for message hash ${wrongMessage.hash().toString()}`); - // send the right one - - const consumptionReceipt = await l2Bridge + await l2Bridge .withWallet(user2Wallet) - .methods.claim_private(claim.redeemSecretHash, bridgeAmount, claim.claimSecret, claim.messageLeafIndex) + .methods.claim_private(ownerAddress, bridgeAmount, claim.claimSecret, claim.messageLeafIndex) .send() .wait(); - // Now user1 can claim the notes that user2 minted on their behalf. - await crossChainTestHarness.addPendingShieldNoteToPXE( - bridgeAmount, - claim.redeemSecretHash, - consumptionReceipt.txHash, - ); - await crossChainTestHarness.redeemShieldPrivatelyOnL2(bridgeAmount, claim.redeemSecret); await crossChainTestHarness.expectPrivateBalanceOnL2(ownerAddress, bridgeAmount); }), 90_000; diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public_to_private.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public_to_private.test.ts index 8f95f9be159..0b065456ecb 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public_to_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging/token_bridge_public_to_private.test.ts @@ -2,6 +2,7 @@ import { Fr } from '@aztec/circuits.js'; import { CrossChainMessagingTest } from './cross_chain_messaging_test.js'; +// TODO(benesjan): this test seems quite redundant. Nuke? describe('e2e_cross_chain_messaging token_bridge_public_to_private', () => { const t = new CrossChainMessagingTest('token_bridge_public_to_private'); @@ -44,10 +45,9 @@ describe('e2e_cross_chain_messaging token_bridge_public_to_private', () => { await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount); // Create the commitment to be spent in the private domain - await crossChainTestHarness.shieldFundsOnL2(shieldAmount, claim.claimSecretHash); + await crossChainTestHarness.transferToPrivateOnL2(shieldAmount); // Create the transaction spending the commitment - await crossChainTestHarness.redeemShieldPrivatelyOnL2(shieldAmount, claim.claimSecret); await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount - shieldAmount); await crossChainTestHarness.expectPrivateBalanceOnL2(ownerAddress, shieldAmount); diff --git a/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts b/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts index c37d79414f7..bf9fdb65ba8 100644 --- a/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/private_payments.test.ts @@ -183,8 +183,9 @@ describe('e2e_fees private_payment', () => { * increase Alice's private banana balance by feeAmount by finalizing partial note */ const newlyMintedBananas = 10n; + const from = aliceAddress; // we are setting from to Alice here because of TODO(#9887) const tx = await bananaCoin.methods - .mint_to_private(aliceAddress, newlyMintedBananas) + .mint_to_private(from, aliceAddress, newlyMintedBananas) .send({ fee: { gasSettings, @@ -349,9 +350,10 @@ describe('e2e_fees private_payment', () => { await expectMapping(t.getGasBalanceFn, [bankruptFPC.address], [0n]); + const from = aliceAddress; // we are setting from to Alice here because of TODO(#9887) await expect( bananaCoin.methods - .mint_to_private(aliceAddress, 10) + .mint_to_private(from, aliceAddress, 10) .send({ // we need to skip public simulation otherwise the PXE refuses to accept the TX skipPublicSimulation: true, diff --git a/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts index 9d04d7e0542..7039882ac10 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/private_transfer_recursion.test.ts @@ -23,7 +23,8 @@ describe('e2e_token_contract private transfer recursion', () => { const notesPerIteration = 3; for (let mintedNotes = 0; mintedNotes < noteAmounts.length; mintedNotes += notesPerIteration) { const toMint = noteAmounts.slice(mintedNotes, mintedNotes + notesPerIteration); - const actions = toMint.map(amt => asset.methods.mint_to_private(wallets[0].getAddress(), amt).request()); + const from = wallets[0].getAddress(); // we are setting from to sender here because of TODO(#9887) + const actions = toMint.map(amt => asset.methods.mint_to_private(from, wallets[0].getAddress(), amt).request()); await new BatchCall(wallets[0], actions).send().wait(); } diff --git a/yarn-project/end-to-end/src/fixtures/token_utils.ts b/yarn-project/end-to-end/src/fixtures/token_utils.ts index d557bbea2ff..834438f686f 100644 --- a/yarn-project/end-to-end/src/fixtures/token_utils.ts +++ b/yarn-project/end-to-end/src/fixtures/token_utils.ts @@ -24,7 +24,8 @@ export async function mintTokensToPrivate( amount: bigint, ) { const tokenAsMinter = await TokenContract.at(token.address, minterWallet); - await tokenAsMinter.methods.mint_to_private(recipient, amount).send().wait(); + const from = minterWallet.getAddress(); // we are setting from to minter here because of TODO(#9887) + await tokenAsMinter.methods.mint_to_private(from, recipient, amount).send().wait(); } const awaitUserSynchronized = async (wallet: Wallet, owner: AztecAddress) => { diff --git a/yarn-project/end-to-end/src/guides/up_quick_start.sh b/yarn-project/end-to-end/src/guides/up_quick_start.sh index f0ce8cb624c..3c659cb89f7 100755 --- a/yarn-project/end-to-end/src/guides/up_quick_start.sh +++ b/yarn-project/end-to-end/src/guides/up_quick_start.sh @@ -23,7 +23,7 @@ echo "Deployed contract at $TOKEN_ADDRESS" # docs:start:mint-private MINT_AMOUNT=69 -aztec-wallet send mint_to_private -ca last --args accounts:alice $MINT_AMOUNT -f alice +aztec-wallet send mint_to_private -ca last --args accounts:alice accounts:alice $MINT_AMOUNT -f alice # docs:end:mint-private # docs:start:get-balance diff --git a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts index e78d1973d38..3840c08a3bf 100644 --- a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts +++ b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts @@ -64,7 +64,8 @@ describe('guides/writing_an_account_contract', () => { logger.info(`Deployed token contract at ${token.address}`); const mintAmount = 50n; - await token.methods.mint_to_private(address, mintAmount).send().wait(); + const from = address; // we are setting from to address here because of TODO(#9887) + await token.methods.mint_to_private(from, address, mintAmount).send().wait(); const balance = await token.methods.balance_of_private(address).simulate(); logger.info(`Balance of wallet is now ${balance}`); diff --git a/yarn-project/end-to-end/src/sample-dapp/index.mjs b/yarn-project/end-to-end/src/sample-dapp/index.mjs index 91f94f5ef90..2c68a011117 100644 --- a/yarn-project/end-to-end/src/sample-dapp/index.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/index.mjs @@ -40,7 +40,8 @@ async function mintPrivateFunds(pxe) { // We mint tokens to the owner const mintAmount = 20n; - await token.methods.mint_to_private(ownerWallet.getAddress(), mintAmount).send().wait(); + const from = ownerWallet.getAddress(); // we are setting from to owner here because of TODO(#9887) + await token.methods.mint_to_private(from, ownerWallet.getAddress(), mintAmount).send().wait(); await showPrivateBalances(pxe); } diff --git a/yarn-project/end-to-end/src/shared/browser.ts b/yarn-project/end-to-end/src/shared/browser.ts index 75e1019196e..ea9dde82e56 100644 --- a/yarn-project/end-to-end/src/shared/browser.ts +++ b/yarn-project/end-to-end/src/shared/browser.ts @@ -252,7 +252,8 @@ export const browserTestSuite = ( console.log(`Contract Deployed: ${token.address}`); // We mint tokens to the owner - await token.methods.mint_to_private(owner.getAddress(), initialBalance).send().wait(); + const from = owner.getAddress(); // we are setting from to owner here because of TODO(#9887) + await token.methods.mint_to_private(from, owner.getAddress(), initialBalance).send().wait(); return [txHash.toString(), token.address.toString()]; }, diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 17e4123f2fb..b561aa03488 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -10,7 +10,7 @@ import { type L1TokenManager, L1TokenPortalManager, type L2AmountClaim, - type L2RedeemableAmountClaim, + type L2AmountClaimWithRecipient, Note, type PXE, type SiblingPath, @@ -256,16 +256,14 @@ export class CrossChainTestHarness { } async consumeMessageOnAztecAndMintPrivately( - claim: Pick, + claim: Pick, ) { this.logger.info('Consuming messages on L2 privately'); - const { claimAmount, claimSecret: secretForL2MessageConsumption, messageLeafIndex, redeemSecretHash } = claim; - const consumptionReceipt = await this.l2Bridge.methods - .claim_private(redeemSecretHash, claimAmount, secretForL2MessageConsumption, messageLeafIndex) + const { recipient, claimAmount, claimSecret: secretForL2MessageConsumption, messageLeafIndex } = claim; + await this.l2Bridge.methods + .claim_private(recipient, claimAmount, secretForL2MessageConsumption, messageLeafIndex) .send() .wait(); - - await this.addPendingShieldNoteToPXE(claimAmount.toBigInt(), redeemSecretHash, consumptionReceipt.txHash); } async consumeMessageOnAztecAndMintPublicly( @@ -340,14 +338,9 @@ export class CrossChainTestHarness { ); } - async shieldFundsOnL2(shieldAmount: bigint, secretHash: Fr) { - this.logger.info('Shielding funds on L2'); - const shieldReceipt = await this.l2Token.methods - .shield(this.ownerAddress, shieldAmount, secretHash, 0) - .send() - .wait(); - - await this.addPendingShieldNoteToPXE(shieldAmount, secretHash, shieldReceipt.txHash); + async transferToPrivateOnL2(shieldAmount: bigint) { + this.logger.info('Transferring to private on L2'); + await this.l2Token.methods.transfer_to_private(this.ownerAddress, shieldAmount).send().wait(); } async addPendingShieldNoteToPXE(shieldAmount: bigint, secretHash: Fr, txHash: TxHash) { @@ -364,11 +357,6 @@ export class CrossChainTestHarness { await this.ownerWallet.addNote(extendedNote); } - async redeemShieldPrivatelyOnL2(shieldAmount: bigint, secret: Fr) { - this.logger.info('Spending note in private call'); - await this.l2Token.methods.redeem_shield(this.ownerAddress, shieldAmount, secret).send().wait(); - } - async transferToPublicOnL2(amount: bigint, nonce = Fr.ZERO) { this.logger.info('Transferring tokens to public'); await this.l2Token.methods.transfer_to_public(this.ownerAddress, this.ownerAddress, amount, nonce).send().wait(); diff --git a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts index d33bcb1ccab..6e594253985 100644 --- a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts +++ b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts @@ -200,7 +200,6 @@ export const uniswapL1L2TestSuite = ( // 2. Claim WETH on L2 logger.info('Minting weth on L2'); await wethCrossChainHarness.consumeMessageOnAztecAndMintPrivately(wethDepositClaim); - await wethCrossChainHarness.redeemShieldPrivatelyOnL2(wethAmountToBridge, wethDepositClaim.redeemSecret); await wethCrossChainHarness.expectPrivateBalanceOnL2(ownerAddress, wethAmountToBridge); // Store balances @@ -223,7 +222,6 @@ export const uniswapL1L2TestSuite = ( // 4. Swap on L1 - sends L2 to L1 message to withdraw WETH to L1 and another message to swap assets. logger.info('Withdrawing weth to L1 and sending message to swap to dai'); const [secretForDepositingSwappedDai, secretHashForDepositingSwappedDai] = generateClaimSecret(); - const [secretForRedeemingDai, secretHashForRedeemingDai] = generateClaimSecret(); const l2UniswapInteractionReceipt = await uniswapL2Contract.methods .swap_private( @@ -234,14 +232,13 @@ export const uniswapL1L2TestSuite = ( nonceForWETHTransferToPublicApproval, uniswapFeeTier, minimumOutputAmount, - secretHashForRedeemingDai, secretHashForDepositingSwappedDai, ownerEthAddress, ) .send() .wait(); - const swapPrivateFunction = 'swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,address)'; + const swapPrivateFunction = 'swap_private(address,uint256,uint24,address,uint256,bytes32,address)'; const swapPrivateContent = sha256ToField([ Buffer.from(toFunctionSelector(swapPrivateFunction).substring(2), 'hex'), wethCrossChainHarness.tokenPortalAddress.toBuffer32(), @@ -249,7 +246,6 @@ export const uniswapL1L2TestSuite = ( new Fr(uniswapFeeTier), daiCrossChainHarness.tokenPortalAddress.toBuffer32(), new Fr(minimumOutputAmount), - secretHashForRedeemingDai, secretHashForDepositingSwappedDai, ownerEthAddress.toBuffer32(), ]); @@ -322,7 +318,6 @@ export const uniswapL1L2TestSuite = ( Number(uniswapFeeTier), daiCrossChainHarness.tokenPortalAddress.toString(), minimumOutputAmount, - secretHashForRedeemingDai.toString(), secretHashForDepositingSwappedDai.toString(), true, [withdrawMessageMetadata, swapPrivateMessageMetadata], @@ -352,12 +347,11 @@ export const uniswapL1L2TestSuite = ( // 6. claim dai on L2 logger.info('Consuming messages to mint dai on L2'); await daiCrossChainHarness.consumeMessageOnAztecAndMintPrivately({ - redeemSecretHash: secretHashForRedeemingDai, claimAmount: new Fr(daiAmountToBridge), claimSecret: secretForDepositingSwappedDai, messageLeafIndex: tokenOutMsgIndex, + recipient: ownerAddress, }); - await daiCrossChainHarness.redeemShieldPrivatelyOnL2(daiAmountToBridge, secretForRedeemingDai); await daiCrossChainHarness.expectPrivateBalanceOnL2(ownerAddress, daiL2BalanceBeforeSwap + daiAmountToBridge); const wethL2BalanceAfterSwap = await wethCrossChainHarness.getL2PrivateBalanceOf(ownerAddress); @@ -640,7 +634,6 @@ export const uniswapL1L2TestSuite = ( uniswapFeeTier, minimumOutputAmount, Fr.random(), - Fr.random(), ownerEthAddress, ) .prove(), @@ -678,7 +671,6 @@ export const uniswapL1L2TestSuite = ( uniswapFeeTier, minimumOutputAmount, Fr.random(), - Fr.random(), ownerEthAddress, ) .prove(), @@ -824,7 +816,6 @@ export const uniswapL1L2TestSuite = ( // Swap logger.info('Withdrawing weth to L1 and sending message to swap to dai'); - const [, secretHashForRedeemingDai] = generateClaimSecret(); const [, secretHashForDepositingSwappedDai] = generateClaimSecret(); const withdrawReceipt = await uniswapL2Contract.methods @@ -836,7 +827,6 @@ export const uniswapL1L2TestSuite = ( nonceForWETHTransferToPublicApproval, uniswapFeeTier, minimumOutputAmount, - secretHashForRedeemingDai, secretHashForDepositingSwappedDai, ownerEthAddress, ) @@ -845,9 +835,7 @@ export const uniswapL1L2TestSuite = ( const swapPrivateContent = sha256ToField([ Buffer.from( - toFunctionSelector('swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,address)').substring( - 2, - ), + toFunctionSelector('swap_private(address,uint256,uint24,address,uint256,bytes32,address)').substring(2), 'hex', ), wethCrossChainHarness.tokenPortalAddress.toBuffer32(), @@ -855,7 +843,6 @@ export const uniswapL1L2TestSuite = ( new Fr(uniswapFeeTier), daiCrossChainHarness.tokenPortalAddress.toBuffer32(), new Fr(minimumOutputAmount), - secretHashForRedeemingDai, secretHashForDepositingSwappedDai, ownerEthAddress.toBuffer32(), ]); @@ -1049,7 +1036,6 @@ export const uniswapL1L2TestSuite = ( await rollup.write.setAssumeProvenThroughBlockNumber([await rollup.read.getPendingBlockNumber()]); // Call swap_private on L1 - const secretHashForRedeemingDai = Fr.random(); // creating my own secret hash logger.info('Execute withdraw and swap on the uniswapPortal!'); const swapArgs = [ @@ -1058,7 +1044,6 @@ export const uniswapL1L2TestSuite = ( Number(uniswapFeeTier), daiCrossChainHarness.tokenPortalAddress.toString(), minimumOutputAmount, - secretHashForRedeemingDai.toString(), secretHashForDepositingSwappedDai.toString(), true, [withdrawMessageMetadata, swapPublicMessageMetadata], diff --git a/yarn-project/protocol-contracts/src/protocol_contract_data.ts b/yarn-project/protocol-contracts/src/protocol_contract_data.ts index a210ce408ca..484ae16e204 100644 --- a/yarn-project/protocol-contracts/src/protocol_contract_data.ts +++ b/yarn-project/protocol-contracts/src/protocol_contract_data.ts @@ -53,11 +53,11 @@ export const ProtocolContractLeaf = { AuthRegistry: Fr.fromString('0x0931f3bf89563f3898ae9650851083cd560ad800c2e3c561c3853eec4dd7ea8b'), ContractInstanceDeployer: Fr.fromString('0x266ea4c9917455daa905c1dd1a10753714c6d0369b6f2fe23feeca6de556d164'), ContractClassRegisterer: Fr.fromString('0x1ccb7a219f72a851089e956d527997b01068d5a28c9ae96b35ebeb45f068af23'), - MultiCallEntrypoint: Fr.fromString('0x000b94baf1a8eebc1b280aa1f162f88ef4fa9da6bf4ebbe5bbb2a40386a91314'), + MultiCallEntrypoint: Fr.fromString('0x1d060217817cf472a579638db722903fd1bbc4c3bdb0ecefa5694c0d4eed851a'), FeeJuice: Fr.fromString('0x1e47caab3dd90f26b91e14e003a5ceab8d069b654174f6d698cdec9b1a6d19d5'), Router: Fr.fromString('0x00827d5a8aedb9627d9e5de04735600a4dbb817d4a2f51281aab991699f5de99'), }; export const protocolContractTreeRoot = Fr.fromString( - '0x23b9c035580b52d82ff309cd3c70acf754be2070d861572faf90fa403001ac24', + '0x24df09a860e983bd4e2e63538c62419d9640ae4d2ed77153b104cb8f1a9fd27e', ); diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index dbdba82276e..989c5ed7067 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -607,7 +607,6 @@ describe('Private Execution test suite', () => { let bridgedAmount = 100n; const l1ToL2MessageIndex = 0; - const secretHashForRedeemingNotes = new Fr(2n); let secretForL1ToL2MessageConsumption = new Fr(1n); let crossChainMsgRecipient: AztecAddress | undefined; @@ -627,8 +626,8 @@ describe('Private Execution test suite', () => { const computePreimage = () => buildL1ToL2Message( - toFunctionSelector('mint_private(bytes32,uint256)').substring(2), - [secretHashForRedeemingNotes, new Fr(bridgedAmount)], + toFunctionSelector('mint_private(uint256)').substring(2), + [new Fr(bridgedAmount)], crossChainMsgRecipient ?? contractAddress, secretForL1ToL2MessageConsumption, l1ToL2MessageIndex, @@ -636,7 +635,6 @@ describe('Private Execution test suite', () => { const computeArgs = () => encodeArguments(artifact, [ - secretHashForRedeemingNotes, bridgedAmount, secretForL1ToL2MessageConsumption, crossChainMsgSender ?? preimage.sender.sender,