From 9103eabd25fefadc4ffd4d689ca7e924f96f36cb Mon Sep 17 00:00:00 2001 From: LHerskind Date: Thu, 14 Sep 2023 16:04:09 +0000 Subject: [PATCH 1/6] fix: replace private token in tests --- .../end-to-end/src/e2e_2_rpc_servers.test.ts | 42 ++++++++----- .../src/e2e_escrow_contract.test.ts | 45 ++++++++----- .../e2e_multiple_accounts_1_enc_key.test.ts | 42 ++++++++----- .../src/e2e_sandbox_example.test.ts | 63 +++++++++++-------- .../writing_an_account_contract.test.ts | 27 +++++--- .../src/contracts/escrow_contract/src/main.nr | 17 ++--- .../src/private_token_contract_interface.nr | 1 - 7 files changed, 150 insertions(+), 87 deletions(-) delete mode 120000 yarn-project/noir-contracts/src/contracts/escrow_contract/src/private_token_contract_interface.nr diff --git a/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts b/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts index 554ad930ff6..07fe8f805f2 100644 --- a/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts @@ -1,10 +1,10 @@ import { AztecNodeService } from '@aztec/aztec-node'; import { AztecRPCServer, EthAddress, Fr } from '@aztec/aztec-rpc'; -import { AztecAddress, Wallet } from '@aztec/aztec.js'; +import { AztecAddress, Wallet, computeMessageSecretHash } from '@aztec/aztec.js'; import { DebugLogger } from '@aztec/foundation/log'; import { retryUntil } from '@aztec/foundation/retry'; import { toBigInt } from '@aztec/foundation/serialize'; -import { ChildContract, PrivateTokenContract } from '@aztec/noir-contracts/types'; +import { ChildContract, TokenContract } from '@aztec/noir-contracts/types'; import { AztecRPC, CompleteAddress, TxStatus } from '@aztec/types'; import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup, setupAztecRPCServer } from './fixtures/utils.js'; @@ -71,15 +71,27 @@ describe('e2e_2_rpc_servers', () => { await awaitUserSynchronised(wallet, owner); // Then check the balance - const contractWithWallet = await PrivateTokenContract.at(tokenAddress, wallet); - const balance = await contractWithWallet.methods.getBalance(owner).view({ from: owner }); + const contractWithWallet = await TokenContract.at(tokenAddress, wallet); + const balance = await contractWithWallet.methods.balance_of_private({ address: owner }).view({ from: owner }); logger(`Account ${owner} balance: ${balance}`); expect(balance).toBe(expectedBalance); }; const deployPrivateTokenContract = async (initialBalance: bigint, owner: AztecAddress) => { logger(`Deploying PrivateToken contract...`); - const contract = await PrivateTokenContract.deploy(walletA, initialBalance, owner).send().deployed(); + const contract = await TokenContract.deploy(walletA).send().deployed(); + expect((await contract.methods._initialize({ address: owner }).send().wait()).status).toBe(TxStatus.MINED); + + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + + expect((await contract.methods.mint_private(initialBalance, secretHash).send().wait()).status).toEqual( + TxStatus.MINED, + ); + expect( + (await contract.methods.redeem_shield({ address: owner }, initialBalance, secret).send().wait()).status, + ).toEqual(TxStatus.MINED); + logger('L2 contract deployed'); return contract.completeAddress; @@ -101,7 +113,7 @@ describe('e2e_2_rpc_servers', () => { // Add privateToken to RPC server B await aztecRpcServerB.addContracts([ { - abi: PrivateTokenContract.abi, + abi: TokenContract.abi, completeAddress: completeTokenAddress, portalContract: EthAddress.ZERO, }, @@ -113,12 +125,11 @@ describe('e2e_2_rpc_servers', () => { await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1); // Transfer funds from A to B via RPC server A - const contractWithWalletA = await PrivateTokenContract.at(tokenAddress, walletA); - const txAToB = contractWithWalletA.methods.transfer(transferAmount1, userB.address).send(); - - await txAToB.isMined({ interval: 0.1 }); - const receiptAToB = await txAToB.getReceipt(); - + const contractWithWalletA = await TokenContract.at(tokenAddress, walletA); + const receiptAToB = await contractWithWalletA.methods + .transfer({ address: userA.address }, { address: userB.address }, transferAmount1, 0) + .send() + .wait(); expect(receiptAToB.status).toBe(TxStatus.MINED); // Check balances and logs are as expected @@ -127,8 +138,11 @@ describe('e2e_2_rpc_servers', () => { await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2); // Transfer funds from B to A via RPC server B - const contractWithWalletB = await PrivateTokenContract.at(tokenAddress, walletB); - await contractWithWalletB.methods.transfer(transferAmount2, userA.address).send().wait({ interval: 0.1 }); + const contractWithWalletB = await TokenContract.at(tokenAddress, walletB); + await contractWithWalletB.methods + .transfer({ address: userB.address }, { address: userA.address }, transferAmount2, 0) + .send() + .wait({ interval: 0.1 }); // Check balances and logs are as expected await expectTokenBalance(walletA, tokenAddress, userA.address, initialBalance - transferAmount1 + transferAmount2); diff --git a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts index 5121aaafdc7..94571b751e1 100644 --- a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts @@ -1,11 +1,11 @@ import { AztecNodeService } from '@aztec/aztec-node'; import { AztecRPCServer } from '@aztec/aztec-rpc'; -import { AccountWallet, AztecAddress, BatchCall, generatePublicKey } from '@aztec/aztec.js'; +import { AccountWallet, AztecAddress, BatchCall, computeMessageSecretHash, generatePublicKey } from '@aztec/aztec.js'; import { CompleteAddress, Fr, GrumpkinPrivateKey, GrumpkinScalar, getContractDeploymentInfo } from '@aztec/circuits.js'; import { DebugLogger } from '@aztec/foundation/log'; import { EscrowContractAbi } from '@aztec/noir-contracts/artifacts'; -import { EscrowContract, PrivateTokenContract } from '@aztec/noir-contracts/types'; -import { AztecRPC, PublicKey } from '@aztec/types'; +import { EscrowContract, TokenContract } from '@aztec/noir-contracts/types'; +import { AztecRPC, PublicKey, TxStatus } from '@aztec/types'; import { setup } from './fixtures/utils.js'; @@ -17,7 +17,7 @@ describe('e2e_escrow_contract', () => { let accounts: CompleteAddress[]; let logger: DebugLogger; - let privateTokenContract: PrivateTokenContract; + let token: TokenContract; let escrowContract: EscrowContract; let owner: AztecAddress; let recipient: AztecAddress; @@ -51,8 +51,19 @@ describe('e2e_escrow_contract', () => { logger(`Escrow contract deployed at ${escrowContract.address}`); // Deploy Private Token contract and mint funds for the escrow contract - privateTokenContract = await PrivateTokenContract.deploy(wallet, 100n, escrowContract.address).send().deployed(); - logger(`Token contract deployed at ${privateTokenContract.address}`); + token = await TokenContract.deploy(wallet).send().deployed(); + + expect((await token.methods._initialize({ address: owner }).send().wait()).status).toBe(TxStatus.MINED); + + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + + expect((await token.methods.mint_private(100n, secretHash).send().wait()).status).toEqual(TxStatus.MINED); + expect( + (await token.methods.redeem_shield({ address: escrowContract.address }, 100n, secret).send().wait()).status, + ).toEqual(TxStatus.MINED); + + logger(`Token contract deployed at ${token.address}`); }, 100_000); afterEach(async () => { @@ -61,7 +72,7 @@ describe('e2e_escrow_contract', () => { }, 30_000); const expectBalance = async (who: AztecAddress, expectedBalance: bigint) => { - const balance = await privateTokenContract.methods.getBalance(who).view({ from: who }); + const balance = await token.methods.balance_of_private({ address: who }).view({ from: who }); logger(`Account ${who} balance: ${balance}`); expect(balance).toBe(expectedBalance); }; @@ -72,7 +83,7 @@ describe('e2e_escrow_contract', () => { await expectBalance(escrowContract.address, 100n); logger(`Withdrawing funds from token contract to ${recipient}`); - await escrowContract.methods.withdraw(privateTokenContract.address, 30, recipient).send().wait(); + await escrowContract.methods.withdraw(token.address, 30, recipient).send().wait(); await expectBalance(owner, 0n); await expectBalance(recipient, 30n); @@ -81,21 +92,25 @@ describe('e2e_escrow_contract', () => { it('refuses to withdraw funds as a non-owner', async () => { await expect( - escrowContract - .withWallet(recipientWallet) - .methods.withdraw(privateTokenContract.address, 30, recipient) - .simulate(), + escrowContract.withWallet(recipientWallet).methods.withdraw(token.address, 30, recipient).simulate(), ).rejects.toThrowError(); }, 60_000); it('moves funds using multiple keys on the same tx (#1010)', async () => { logger(`Minting funds in token contract to ${owner}`); - await privateTokenContract.methods.mint(50, owner).send().wait(); + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + + expect((await token.methods.mint_private(50n, secretHash).send().wait()).status).toEqual(TxStatus.MINED); + expect((await token.methods.redeem_shield({ address: owner }, 50n, secret).send().wait()).status).toEqual( + TxStatus.MINED, + ); + await expectBalance(owner, 50n); const actions = [ - privateTokenContract.methods.transfer(10, recipient).request(), - escrowContract.methods.withdraw(privateTokenContract.address, 20, recipient).request(), + token.methods.transfer({ address: owner }, { address: recipient }, 10, 0).request(), + escrowContract.methods.withdraw(token.address, 20, recipient).request(), ]; await new BatchCall(wallet, actions).send().wait(); diff --git a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts index 453a185ddf7..467c3de7d35 100644 --- a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts +++ b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts @@ -1,9 +1,9 @@ import { AztecNodeService } from '@aztec/aztec-node'; import { AztecRPCServer } from '@aztec/aztec-rpc'; -import { AztecAddress, Wallet, generatePublicKey, getSchnorrAccount } from '@aztec/aztec.js'; -import { GrumpkinScalar } from '@aztec/circuits.js'; +import { AztecAddress, Wallet, computeMessageSecretHash, generatePublicKey, getSchnorrAccount } from '@aztec/aztec.js'; +import { Fr, GrumpkinScalar } from '@aztec/circuits.js'; import { DebugLogger } from '@aztec/foundation/log'; -import { PrivateTokenContract } from '@aztec/noir-contracts/types'; +import { TokenContract } from '@aztec/noir-contracts/types'; import { AztecRPC, TxStatus } from '@aztec/types'; import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup } from './fixtures/utils.js'; @@ -15,7 +15,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const accounts: AztecAddress[] = []; let logger: DebugLogger; - let privateTokenAddress: AztecAddress; + let tokenAddress: AztecAddress; const initialBalance = 987n; const numAccounts = 3; @@ -42,12 +42,20 @@ describe('e2e_multiple_accounts_1_enc_key', () => { expect(account.publicKey).toEqual(encryptionPublicKey); } - logger(`Deploying Private Token...`); - privateTokenAddress = await PrivateTokenContract.deploy(wallets[0], initialBalance, accounts[0]) - .send() - .deployed() - .then(c => c.address); - logger(`Private Token deployed at ${privateTokenAddress}`); + logger(`Deploying Token...`); + const token = await TokenContract.deploy(wallets[0]).send().deployed(); + tokenAddress = token.address; + logger(`Token deployed at ${tokenAddress}`); + + expect((await token.methods._initialize({ address: accounts[0] }).send().wait()).status).toBe(TxStatus.MINED); + + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + + expect((await token.methods.mint_private(initialBalance, secretHash).send().wait()).status).toEqual(TxStatus.MINED); + expect( + (await token.methods.redeem_shield({ address: accounts[0] }, initialBalance, secret).send().wait()).status, + ).toEqual(TxStatus.MINED); }, 100_000); afterEach(async () => { @@ -62,8 +70,8 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const owner = accounts[userIndex]; // Then check the balance - const contractWithWallet = await PrivateTokenContract.at(privateTokenAddress, wallet); - const balance = await contractWithWallet.methods.getBalance(owner).view({ from: owner }); + const contractWithWallet = await TokenContract.at(tokenAddress, wallet); + const balance = await contractWithWallet.methods.balance_of_private({ address: owner }).view({ from: owner }); logger(`Account ${owner} balance: ${balance}`); expect(balance).toBe(expectedBalance); }; @@ -79,12 +87,12 @@ describe('e2e_multiple_accounts_1_enc_key', () => { const sender = accounts[senderIndex]; const receiver = accounts[receiverIndex]; - const contractWithWallet = await PrivateTokenContract.at(privateTokenAddress, wallets[senderIndex]); - - const tx = contractWithWallet.methods.transfer(transferAmount, receiver).send(); - await tx.isMined({ interval: 0.1 }); - const receipt = await tx.getReceipt(); + const contractWithWallet = await TokenContract.at(tokenAddress, wallets[senderIndex]); + const receipt = await contractWithWallet.methods + .transfer({ address: sender }, { address: receiver }, transferAmount, 0) + .send() + .wait(); expect(receipt.status).toBe(TxStatus.MINED); for (let i = 0; i < expectedBalances.length; i++) { diff --git a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts index 27ef20a8298..39d36a7f097 100644 --- a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts +++ b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts @@ -2,14 +2,21 @@ /* eslint-disable import/no-duplicates */ // docs:start:imports -import { AztecRPC, createAztecRpcClient, createDebugLogger, getSchnorrAccount, waitForSandbox } from '@aztec/aztec.js'; +import { + AztecRPC, + Fr, + computeMessageSecretHash, + createDebugLogger, + getSchnorrAccount, + waitForSandbox, +} from '@aztec/aztec.js'; // docs:end:imports /* eslint-enable @typescript-eslint/no-unused-vars */ // Note: this is a hack to make the docs use http://localhost:8080 and CI to use the SANDBOX_URL import { createAztecRpcClient as createAztecRpcClient2 } from '@aztec/aztec.js'; import { GrumpkinScalar } from '@aztec/circuits.js'; -import { PrivateTokenContract } from '@aztec/noir-contracts/types'; +import { TokenContract } from '@aztec/noir-contracts/types'; const { SANDBOX_URL = 'http://localhost:8080' } = process.env; @@ -22,7 +29,7 @@ describe('e2e_sandbox_example', () => { it('sandbox example works', async () => { // docs:start:setup ////////////// CREATE THE CLIENT INTERFACE AND CONTACT THE SANDBOX ////////////// - const logger = createDebugLogger('private-token'); + const logger = createDebugLogger('token'); const sandboxUrl = 'http://localhost:8080'; // We create AztecRPC client connected to the sandbox URL @@ -88,41 +95,44 @@ describe('e2e_sandbox_example', () => { expect(registeredAccounts.find(acc => acc.equals(bob))).toBeTruthy(); // docs:start:Deployment - ////////////// DEPLOY OUR PRIVATE TOKEN CONTRACT ////////////// + ////////////// DEPLOY OUR TOKEN CONTRACT ////////////// - // Deploy a private token contract, create a contract abstraction object and link it to the owner's wallet + // Deploy a token contract, create a contract abstraction object and link it to the owner's wallet // The contract's constructor takes 2 arguments, the initial supply and the owner of that initial supply const initialSupply = 1_000_000n; - logger(`Deploying private token contract minting an initial ${initialSupply} tokens to Alice...`); - const contract = await PrivateTokenContract.deploy( - aztecRpc, - initialSupply, // the initial supply - alice, // the owner of the initial supply - ) - .send() - .deployed(); + logger(`Deploying token contract minting an initial ${initialSupply} tokens to Alice...`); + const contract = await TokenContract.deploy(aztecRpc).send().deployed(); + + // Create the contract abstraction and link to Alice's wallet for future signing + const tokenContractAlice = await TokenContract.at(contract.address, await accounts[0].getWallet()); + + await tokenContractAlice.methods._initialize({ address: alice }).send().wait(); + await tokenContractAlice.methods.set_minter({ address: bob }, 1).send().wait(); logger(`Contract successfully deployed at address ${contract.address.toShortString()}`); + + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + + await tokenContractAlice.methods.mint_private(initialSupply, secretHash).send().wait(); + await tokenContractAlice.methods.redeem_shield({ address: alice }, initialSupply, secret).send().wait(); // docs:end:Deployment - // ensure that private token contract is registered in the rpc + // ensure that token contract is registered in the rpc expect(await aztecRpc.getContracts()).toEqual(expect.arrayContaining([contract.address])); // docs:start:Balance ////////////// QUERYING THE TOKEN BALANCE FOR EACH ACCOUNT ////////////// - // Create the contract abstraction and link to Alice's wallet for future signing - const tokenContractAlice = await PrivateTokenContract.at(contract.address, await accounts[0].getWallet()); - // Bob wants to mint some funds, the contract is already deployed, create an abstraction and link it his wallet - const tokenContractBob = await PrivateTokenContract.at(contract.address, await accounts[1].getWallet()); + const tokenContractBob = await TokenContract.at(contract.address, await accounts[1].getWallet()); - let aliceBalance = await tokenContractAlice.methods.getBalance(alice).view(); + let aliceBalance = await tokenContractAlice.methods.balance_of_private({ address: alice }).view(); logger(`Alice's balance ${aliceBalance}`); - let bobBalance = await tokenContractBob.methods.getBalance(bob).view(); + let bobBalance = await tokenContractBob.methods.balance_of_private({ address: bob }).view(); logger(`Bob's balance ${bobBalance}`); // docs:end:Balance @@ -136,13 +146,13 @@ describe('e2e_sandbox_example', () => { // We will now transfer tokens from ALice to Bob const transferQuantity = 543n; logger(`Transferring ${transferQuantity} tokens from Alice to Bob...`); - await tokenContractAlice.methods.transfer(transferQuantity, bob).send().wait(); + await tokenContractAlice.methods.transfer({ address: alice }, { address: bob }, transferQuantity, 0).send().wait(); // Check the new balances - aliceBalance = await tokenContractAlice.methods.getBalance(alice).view(); + aliceBalance = await tokenContractAlice.methods.balance_of_private({ address: alice }).view(); logger(`Alice's balance ${aliceBalance}`); - bobBalance = await tokenContractBob.methods.getBalance(bob).view(); + bobBalance = await tokenContractBob.methods.balance_of_private({ address: bob }).view(); logger(`Bob's balance ${bobBalance}`); // docs:end:Transfer @@ -155,13 +165,14 @@ describe('e2e_sandbox_example', () => { // Now mint some further funds for Bob const mintQuantity = 10_000n; logger(`Minting ${mintQuantity} tokens to Bob...`); - await tokenContractBob.methods.mint(mintQuantity, bob).send().wait(); + await tokenContractBob.methods.mint_private(mintQuantity, secretHash).send().wait(); + await tokenContractBob.methods.redeem_shield({ address: bob }, mintQuantity, secret).send().wait(); // Check the new balances - aliceBalance = await tokenContractAlice.methods.getBalance(alice).view(); + aliceBalance = await tokenContractAlice.methods.balance_of_private({ address: alice }).view(); logger(`Alice's balance ${aliceBalance}`); - bobBalance = await tokenContractBob.methods.getBalance(bob).view(); + bobBalance = await tokenContractBob.methods.balance_of_private({ address: bob }).view(); logger(`Bob's balance ${bobBalance}`); // docs:end:Mint 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 466240732e3..7b9e848a28e 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 @@ -1,8 +1,15 @@ import { AztecRPCServer } from '@aztec/aztec-rpc'; -import { AccountManager, AuthWitnessProvider, BaseAccountContract, CompleteAddress, Fr } from '@aztec/aztec.js'; +import { + AccountManager, + AuthWitnessProvider, + BaseAccountContract, + CompleteAddress, + Fr, + computeMessageSecretHash, +} from '@aztec/aztec.js'; import { GrumpkinPrivateKey, GrumpkinScalar } from '@aztec/circuits.js'; import { Schnorr } from '@aztec/circuits.js/barretenberg'; -import { PrivateTokenContract, SchnorrHardcodedAccountContractAbi } from '@aztec/noir-contracts/types'; +import { SchnorrHardcodedAccountContractAbi, TokenContract } from '@aztec/noir-contracts/types'; import { AuthWitness } from '@aztec/types'; import { setup } from '../fixtures/utils.js'; @@ -59,14 +66,20 @@ describe('guides/writing_an_account_contract', () => { logger(`Deployed account contract at ${address}`); // docs:start:account-contract-works - const token = await PrivateTokenContract.deploy(wallet, 100, address).send().deployed(); + const token = await TokenContract.deploy(wallet).send().deployed(); logger(`Deployed token contract at ${token.address}`); + await token.methods._initialize({ address }).send().wait(); - await token.methods.mint(50, address).send().wait(); - const balance = await token.methods.getBalance(address).view(); + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + + await token.methods.mint_private(50, secretHash).send().wait(); + await token.methods.redeem_shield({ address }, 50, secret).send().wait(); + + const balance = await token.methods.balance_of_private({ address }).view(); logger(`Balance of wallet is now ${balance}`); // docs:end:account-contract-works - expect(balance).toEqual(150n); + expect(balance).toEqual(50n); // docs:start:account-contract-fails const walletAddress = wallet.getCompleteAddress(); @@ -77,7 +90,7 @@ describe('guides/writing_an_account_contract', () => { const tokenWithWrongWallet = token.withWallet(wrongWallet); try { - await tokenWithWrongWallet.methods.mint(200, address).simulate(); + await tokenWithWrongWallet.methods.mint_private(200, secretHash).simulate(); } catch (err) { logger(`Failed to send tx: ${err}`); } diff --git a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr index 81131fae5e3..b287671792b 100644 --- a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr @@ -1,5 +1,4 @@ mod address_note; -mod private_token_contract_interface; // Sample escrow contract that stores a balance of a private token on behalf of an owner. contract Escrow { @@ -14,6 +13,7 @@ contract Escrow { utils as note_utils, }, oracle::get_public_key::get_public_key, + oracle::compute_selector::compute_selector, state_vars::set::Set, }; @@ -23,8 +23,6 @@ contract Escrow { ADDRESS_NOTE_LEN, }; - use crate::private_token_contract_interface::PrivateTokenPrivateContextInterface; - struct Storage { owners: Set, } @@ -59,9 +57,9 @@ contract Escrow { // Withdraws balance. Requires that msg.sender is registered as an owner. #[aztec(private)] fn withdraw( - token: pub Field, - amount: pub Field, - recipient: pub Field, + token: Field, + amount: Field, + recipient: Field, ) { let this = context.this_address(); let sender = context.msg_sender(); @@ -75,7 +73,12 @@ contract Escrow { assert(note.address == sender); assert(note.owner == this); - let _callStackItem = PrivateTokenPrivateContextInterface::at(token).transfer(&mut context, amount, recipient); + let selector = compute_selector("transfer((Field),(Field),Field,Field)"); + let _callStackItem = context.call_private_function( + token, + selector, + [this, recipient, amount, 0] + ); } unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; ADDRESS_NOTE_LEN]) -> [Field; 4] { diff --git a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/private_token_contract_interface.nr b/yarn-project/noir-contracts/src/contracts/escrow_contract/src/private_token_contract_interface.nr deleted file mode 120000 index 0f8207f8b98..00000000000 --- a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/private_token_contract_interface.nr +++ /dev/null @@ -1 +0,0 @@ -../../private_token_contract/src/interface.nr \ No newline at end of file From f4fffdf668a0fd04655dc00d3064b430cfdeeca9 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Fri, 15 Sep 2023 14:52:39 +0000 Subject: [PATCH 2/6] refactor: replace private_token in sample_dapp e2e --- .../src/e2e_sandbox_example.test.ts | 2 +- .../end-to-end/src/sample-dapp/contracts.mjs | 14 ++---- .../end-to-end/src/sample-dapp/deploy.mjs | 21 ++++----- .../end-to-end/src/sample-dapp/index.mjs | 43 ++++++++++++++----- .../end-to-end/src/sample-dapp/index.test.mjs | 25 ++++++++--- 5 files changed, 63 insertions(+), 42 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts index 39d36a7f097..0e4058a2015 100644 --- a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts +++ b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts @@ -108,7 +108,7 @@ describe('e2e_sandbox_example', () => { const tokenContractAlice = await TokenContract.at(contract.address, await accounts[0].getWallet()); await tokenContractAlice.methods._initialize({ address: alice }).send().wait(); - await tokenContractAlice.methods.set_minter({ address: bob }, 1).send().wait(); + await tokenContractAlice.methods.set_minter({ address: bob }, true).send().wait(); logger(`Contract successfully deployed at address ${contract.address.toShortString()}`); diff --git a/yarn-project/end-to-end/src/sample-dapp/contracts.mjs b/yarn-project/end-to-end/src/sample-dapp/contracts.mjs index d72e4f4bd5f..b0892378b01 100644 --- a/yarn-project/end-to-end/src/sample-dapp/contracts.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/contracts.mjs @@ -1,19 +1,11 @@ import { Contract } from '@aztec/aztec.js'; -import { - PrivateTokenContractAbi as PrivateTokenArtifact, - PublicTokenContractAbi as PublicTokenArtifact, -} from '@aztec/noir-contracts/artifacts'; +import { TokenContractAbi } from '@aztec/noir-contracts/artifacts'; import { readFileSync } from 'fs'; // docs:start:get-tokens -export async function getPrivateToken(client) { +export async function getToken(client) { const addresses = JSON.parse(readFileSync('addresses.json')); - return Contract.at(addresses.privateToken, PrivateTokenArtifact, client); -} - -export async function getPublicToken(client) { - const addresses = JSON.parse(readFileSync('addresses.json')); - return Contract.at(addresses.publicToken, PublicTokenArtifact, client); + return Contract.at(addresses.token, TokenContractAbi, client); } // docs:end:get-tokens diff --git a/yarn-project/end-to-end/src/sample-dapp/deploy.mjs b/yarn-project/end-to-end/src/sample-dapp/deploy.mjs index af8d7604f00..1fa4036fee5 100644 --- a/yarn-project/end-to-end/src/sample-dapp/deploy.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/deploy.mjs @@ -1,8 +1,5 @@ -import { ContractDeployer, createAztecRpcClient } from '@aztec/aztec.js'; -import { - PrivateTokenContractAbi as PrivateTokenArtifact, - PublicTokenContractAbi as PublicTokenArtifact, -} from '@aztec/noir-contracts/artifacts'; +import { Contract, ContractDeployer, createAztecRpcClient, getSandboxAccountsWallets } from '@aztec/aztec.js'; +import { TokenContractAbi } from '@aztec/noir-contracts/artifacts'; import { writeFileSync } from 'fs'; import { fileURLToPath } from 'url'; @@ -12,17 +9,15 @@ const { SANDBOX_URL = 'http://localhost:8080' } = process.env; async function main() { const client = createAztecRpcClient(SANDBOX_URL); - const [owner] = await client.getRegisteredAccounts(); + const [owner] = await getSandboxAccountsWallets(client); - const privateTokenDeployer = new ContractDeployer(PrivateTokenArtifact, client); - const { contractAddress: privateTokenAddress } = await privateTokenDeployer.deploy(100n, owner.address).send().wait(); - console.log(`Private token deployed at ${privateTokenAddress.toString()}`); + const token = await Contract.deploy(client, TokenContractAbi, []).send().deployed(); - const publicTokenDeployer = new ContractDeployer(PublicTokenArtifact, client); - const { contractAddress: publicTokenAddress } = await publicTokenDeployer.deploy().send().wait(); - console.log(`Public token deployed at ${publicTokenAddress.toString()}`); + await token.withWallet(owner).methods._initialize({ address: owner.getAddress() }).send().wait(); - const addresses = { privateToken: privateTokenAddress.toString(), publicToken: publicTokenAddress.toString() }; + console.log(`Token deployed at ${token.address.toString()}`); + + const addresses = { token: token.address.toString() }; writeFileSync('addresses.json', JSON.stringify(addresses, null, 2)); } // docs:end:dapp-deploy 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 a911862283f..e07d8d78ed9 100644 --- a/yarn-project/end-to-end/src/sample-dapp/index.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/index.mjs @@ -1,7 +1,13 @@ -import { L2BlockL2Logs, createAztecRpcClient, getSandboxAccountsWallets } from '@aztec/aztec.js'; +import { + Fr, + L2BlockL2Logs, + computeMessageSecretHash, + createAztecRpcClient, + getSandboxAccountsWallets, +} from '@aztec/aztec.js'; import { fileURLToPath } from '@aztec/foundation/url'; -import { getPrivateToken, getPublicToken } from './contracts.mjs'; +import { getToken } from './contracts.mjs'; const { SANDBOX_URL = 'http://localhost:8080' } = process.env; @@ -15,22 +21,37 @@ async function showAccounts(client) { async function showPrivateBalances(client) { // docs:start:showPrivateBalances const accounts = await client.getRegisteredAccounts(); - const privateToken = await getPrivateToken(client); + const token = await getToken(client); for (const account of accounts) { // highlight-next-line:showPrivateBalances - const balance = await privateToken.methods.getBalance(account.address).view(); + const balance = await token.methods.balance_of_private({ address: account.address }).view(); console.log(`Balance of ${account.address}: ${balance}`); } // docs:end:showPrivateBalances } +async function mintPrivateFunds(client) { + const [owner] = await getSandboxAccountsWallets(client); + const token = await getToken(owner); + + await showPrivateBalances(client); + + const mintAmount = 20n; + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + await token.methods.mint_private(mintAmount, secretHash).send().wait(); + await token.methods.redeem_shield({ address: owner.getAddress() }, mintAmount, secret).send().wait(); + + await showPrivateBalances(client); +} + async function transferPrivateFunds(client) { // docs:start:transferPrivateFunds const [owner, recipient] = await getSandboxAccountsWallets(client); - const privateToken = await getPrivateToken(owner); + const token = await getToken(owner); - const tx = privateToken.methods.transfer(1n, recipient.getAddress()).send(); + const tx = token.methods.transfer({ address: owner.getAddress() }, { address: recipient.getAddress() }, 1n, 0).send(); console.log(`Sent transfer transaction ${await tx.getTxHash()}`); await showPrivateBalances(client); @@ -44,11 +65,11 @@ async function transferPrivateFunds(client) { async function showPublicBalances(client) { // docs:start:showPublicBalances const accounts = await client.getRegisteredAccounts(); - const publicToken = await getPublicToken(client); + const token = await getToken(client); for (const account of accounts) { // highlight-next-line:showPublicBalances - const balance = await publicToken.methods.publicBalanceOf(account.address).view(); + const balance = await token.methods.balance_of_public({ address: account.address }).view(); console.log(`Balance of ${account.address}: ${balance}`); } // docs:end:showPublicBalances @@ -57,9 +78,9 @@ async function showPublicBalances(client) { async function mintPublicFunds(client) { // docs:start:mintPublicFunds const [owner] = await getSandboxAccountsWallets(client); - const publicToken = await getPublicToken(owner); + const token = await getToken(owner); - const tx = publicToken.methods.mint(100n, owner.getAddress()).send(); + const tx = token.methods.mint_public({ address: owner.getAddress() }, 100n).send(); console.log(`Sent mint transaction ${await tx.getTxHash()}`); await showPublicBalances(client); @@ -84,6 +105,8 @@ async function main() { await showAccounts(client); + await mintPrivateFunds(client); + await transferPrivateFunds(client); await mintPublicFunds(client); diff --git a/yarn-project/end-to-end/src/sample-dapp/index.test.mjs b/yarn-project/end-to-end/src/sample-dapp/index.test.mjs index 001412e17f6..88f8cf4d335 100644 --- a/yarn-project/end-to-end/src/sample-dapp/index.test.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/index.test.mjs @@ -1,15 +1,23 @@ import { createSandbox } from '@aztec/aztec-sandbox'; -import { Contract, createAccount } from '@aztec/aztec.js'; -import { PrivateTokenContractAbi as PrivateTokenArtifact } from '@aztec/noir-contracts/artifacts'; +import { Contract, Fr, computeMessageSecretHash, createAccount } from '@aztec/aztec.js'; +import { TokenContractAbi } from '@aztec/noir-contracts/artifacts'; -describe('private token', () => { +describe('token', () => { // docs:start:setup let rpc, stop, owner, recipient, token; beforeAll(async () => { ({ rpcServer: rpc, stop } = await createSandbox()); owner = await createAccount(rpc); recipient = await createAccount(rpc); - token = await Contract.deploy(owner, PrivateTokenArtifact, [100n, owner.getAddress()]).send().deployed(); + + token = await Contract.deploy(owner, TokenContractAbi, []).send().deployed(); + await token.methods._initialize({ address: owner.getAddress() }).send().wait(); + + const initialBalance = 20n; + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + await token.methods.mint_private(initialBalance, secretHash).send().wait(); + await token.methods.redeem_shield({ address: owner.getAddress() }, initialBalance, secret).send().wait(); }, 60_000); afterAll(() => stop()); @@ -17,9 +25,12 @@ describe('private token', () => { // docs:start:test it('increases recipient funds on transfer', async () => { - expect(await token.methods.getBalance(recipient.getAddress()).view()).toEqual(0n); - await token.methods.transfer(20n, recipient.getAddress()).send().wait(); - expect(await token.methods.getBalance(recipient.getAddress()).view()).toEqual(20n); + expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(0n); + await token.methods + .transfer({ address: owner.getAddress() }, { address: recipient.getAddress() }, 20n, 0) + .send() + .wait(); + expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(20n); }); // docs:end:test }); From c77fc90e606b96b786672b19eded4511caf80b9b Mon Sep 17 00:00:00 2001 From: LHerskind Date: Sat, 16 Sep 2023 08:47:49 +0000 Subject: [PATCH 3/6] feat: add stateful test contract for simulator tests --- .../src/client/private_execution.test.ts | 28 +++--- .../client/unconstrained_execution.test.ts | 6 +- yarn-project/noir-contracts/Nargo.toml | 1 + .../stateful_test_contract/Nargo.toml | 9 ++ .../stateful_test_contract/src/main.nr | 99 +++++++++++++++++++ 5 files changed, 126 insertions(+), 17 deletions(-) create mode 100644 yarn-project/noir-contracts/src/contracts/stateful_test_contract/Nargo.toml create mode 100644 yarn-project/noir-contracts/src/contracts/stateful_test_contract/src/main.nr diff --git a/yarn-project/acir-simulator/src/client/private_execution.test.ts b/yarn-project/acir-simulator/src/client/private_execution.test.ts index e6ba3fc3793..ad155199005 100644 --- a/yarn-project/acir-simulator/src/client/private_execution.test.ts +++ b/yarn-project/acir-simulator/src/client/private_execution.test.ts @@ -38,7 +38,7 @@ import { ParentContractAbi, PendingCommitmentsContractAbi, PrivateTokenAirdropContractAbi, - PrivateTokenContractAbi, + StatefulTestContractAbi, TestContractAbi, } from '@aztec/noir-contracts/artifacts'; import { PackedArguments, TxExecutionRequest } from '@aztec/types'; @@ -401,7 +401,7 @@ describe('Private Execution test suite', () => { }); }); - describe('private token contract', () => { + describe('stateful test contract contract', () => { const contractAddress = defaultContractAddress; const mockFirstNullifier = new Fr(1111); let currentNoteIndex = 0n; @@ -439,7 +439,7 @@ describe('Private Execution test suite', () => { oracle.getFunctionABI.mockImplementation((_, selector) => Promise.resolve( - PrivateTokenContractAbi.functions.find(f => + StatefulTestContractAbi.functions.find(f => selector.equals(FunctionSelector.fromNameAndParameters(f.name, f.parameters)), )!, ), @@ -484,9 +484,9 @@ describe('Private Execution test suite', () => { }); it('should a constructor with arguments that inserts notes', async () => { - const abi = getFunctionAbi(PrivateTokenContractAbi, 'constructor'); + const abi = getFunctionAbi(StatefulTestContractAbi, 'constructor'); - const result = await runSimulator({ args: [140, owner], abi }); + const result = await runSimulator({ args: [owner, 140], abi }); expect(result.newNotes).toHaveLength(1); const newNote = result.newNotes[0]; @@ -501,10 +501,10 @@ describe('Private Execution test suite', () => { ); }); - it('should run the mint function', async () => { - const abi = getFunctionAbi(PrivateTokenContractAbi, 'mint'); + it('should run the create_note function', async () => { + const abi = getFunctionAbi(StatefulTestContractAbi, 'create_note'); - const result = await runSimulator({ args: [140, owner], abi }); + const result = await runSimulator({ args: [owner, 140], abi }); expect(result.newNotes).toHaveLength(1); const newNote = result.newNotes[0]; @@ -519,9 +519,9 @@ describe('Private Execution test suite', () => { ); }); - it('should run the transfer function', async () => { + it('should run the destroy_and_create function', async () => { const amountToTransfer = 100n; - const abi = getFunctionAbi(PrivateTokenContractAbi, 'transfer'); + const abi = getFunctionAbi(StatefulTestContractAbi, 'destroy_and_create'); const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm); const recipientStorageSlot = computeSlotForMapping(new Fr(1n), recipient.toField(), circuitsWasm); @@ -534,7 +534,7 @@ describe('Private Execution test suite', () => { ); await insertLeaves(consumedNotes.map(n => n.siloedNoteHash)); - const args = [amountToTransfer, recipient]; + const args = [recipient, amountToTransfer]; const result = await runSimulator({ args, abi, msgSender: owner }); // The two notes were nullified @@ -565,10 +565,10 @@ describe('Private Execution test suite', () => { expect(readRequests).toEqual(expect.arrayContaining(consumedNotes.map(n => n.uniqueSiloedNoteHash))); }); - it('should be able to transfer with dummy notes', async () => { + it('should be able to destroy_and_create with dummy notes', async () => { const amountToTransfer = 100n; const balance = 160n; - const abi = getFunctionAbi(PrivateTokenContractAbi, 'transfer'); + const abi = getFunctionAbi(StatefulTestContractAbi, 'destroy_and_create'); const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm); @@ -580,7 +580,7 @@ describe('Private Execution test suite', () => { ); await insertLeaves(consumedNotes.map(n => n.siloedNoteHash)); - const args = [amountToTransfer, recipient]; + const args = [recipient, amountToTransfer]; const result = await runSimulator({ args, abi, msgSender: owner }); const newNullifiers = result.callStackItem.publicInputs.newNullifiers.filter(field => !field.equals(Fr.ZERO)); diff --git a/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts b/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts index ec318a9f6a5..3e38c3999b4 100644 --- a/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts @@ -3,7 +3,7 @@ import { FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; -import { PrivateTokenContractAbi } from '@aztec/noir-contracts/artifacts'; +import { StatefulTestContractAbi } from '@aztec/noir-contracts/artifacts'; import { FunctionCall } from '@aztec/types'; import { mock } from 'jest-mock-extended'; @@ -39,9 +39,9 @@ describe('Unconstrained Execution test suite', () => { }); }); - it('should run the getBalance function', async () => { + it('should run the summed_values function', async () => { const contractAddress = AztecAddress.random(); - const abi = PrivateTokenContractAbi.functions.find(f => f.name === 'getBalance')!; + const abi = StatefulTestContractAbi.functions.find(f => f.name === 'summed_values')!; const preimages = [...Array(5).fill(buildNote(1n, owner)), ...Array(2).fill(buildNote(2n, owner))]; diff --git a/yarn-project/noir-contracts/Nargo.toml b/yarn-project/noir-contracts/Nargo.toml index 28bf8f460ee..2d5cfebf585 100644 --- a/yarn-project/noir-contracts/Nargo.toml +++ b/yarn-project/noir-contracts/Nargo.toml @@ -20,6 +20,7 @@ members = [ "src/contracts/schnorr_account_contract", "src/contracts/schnorr_hardcoded_account_contract", "src/contracts/schnorr_single_key_account_contract", + "src/contracts/stateful_test_contract", "src/contracts/test_contract", "src/contracts/token_contract", "src/contracts/uniswap_contract", diff --git a/yarn-project/noir-contracts/src/contracts/stateful_test_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/stateful_test_contract/Nargo.toml new file mode 100644 index 00000000000..165aea0bfe4 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/stateful_test_contract/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "stateful_test_contract" +authors = [""] +compiler_version = "0.1" +type = "contract" + +[dependencies] +aztec = { path = "../../../../aztec-nr/aztec" } +value_note = { path = "../../../../aztec-nr/value-note"} \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/stateful_test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/stateful_test_contract/src/main.nr new file mode 100644 index 00000000000..e8bb13a2a66 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/stateful_test_contract/src/main.nr @@ -0,0 +1,99 @@ +// A contract used for testing a random hodgepodge of small features from simulator and end-to-end tests. +contract StatefulTest { + use dep::std::option::Option; + use dep::value_note::{ + balance_utils, + utils::{increment, decrement}, + value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + }; + use dep::aztec::{ + context::{PrivateContext, PublicContext, Context}, + note::{ + note_header::NoteHeader, + utils as note_utils, + }, + state_vars::{map::Map, public_state::PublicState, set::Set}, + types::type_serialisation::field_serialisation::{ + FieldSerialisationMethods, FIELD_SERIALISED_LEN, + }, + }; + + struct Storage { + notes: Map>, + public_values: Map>, + } + + impl Storage { + fn init(context: Context) -> pub Self { + Storage { + notes: Map::new( + context, + 1, // Storage slot + |context, slot| { + Set::new(context, slot, ValueNoteMethods) + }, + ), + public_values: Map::new( + context, + 2, + |context, slot| { + PublicState::new( + context, + slot, + FieldSerialisationMethods, + ) + }, + ), + } + } + } + + #[aztec(private)] + fn constructor(owner: Field, value: Field) { + let storage = Storage::init(Context::private(&mut context)); + let loc = storage.notes.at(owner); + increment(loc, value, owner); + } + + #[aztec(private)] + fn create_note( + owner: Field, + value: Field, + ) { + let storage = Storage::init(Context::private(&mut context)); + if (value != 0){ + let loc = storage.notes.at(owner); + increment(loc, value, owner); + } + } + + #[aztec(private)] + fn destroy_and_create( + recipient: Field, + amount: Field, + ) { + let storage = Storage::init(Context::private(&mut context)); + let sender = context.msg_sender(); + + let sender_notes = storage.notes.at(sender); + decrement(sender_notes, amount, sender); + + let recipient_notes = storage.notes.at(recipient); + increment(recipient_notes, amount, recipient); + } + + unconstrained fn summed_values( + owner: Field, + ) -> Field { + let storage = Storage::init(Context::none()); + let owner_balance = storage.notes.at(owner); + + // Return the sum of all notes in the set. + balance_utils::get_balance(owner_balance) + } + + unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; VALUE_NOTE_LEN]) -> [Field; 4] { + let note_header = NoteHeader { contract_address, nonce, storage_slot }; + note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) + } +} From 825702d193d9cf09c15877117d8b6e932aefd0a0 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Sat, 16 Sep 2023 10:08:33 +0000 Subject: [PATCH 4/6] test: fix missing abi --- 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 921c1b28a3c..055d605e0dc 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 @@ -101,6 +101,7 @@ PublicTokenContractAbi SchnorrAccountContractAbi SchnorrHardcodedAccountContractAbi SchnorrSingleKeyAccountContractAbi +StatefulTestContractAbi TestContractAbi TokenContractAbi UniswapContractAbi From 69b1bfe91502a40900bb57d664e2841c7c007898 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Sat, 16 Sep 2023 10:56:34 +0000 Subject: [PATCH 5/6] test: Update more e2e tests --- yarn-project/end-to-end/src/canary/browser.ts | 75 +++++++++++-------- yarn-project/end-to-end/src/canary/cli.ts | 36 ++++++--- .../end-to-end/src/e2e_2_rpc_servers.test.ts | 8 +- 3 files changed, 73 insertions(+), 46 deletions(-) diff --git a/yarn-project/end-to-end/src/canary/browser.ts b/yarn-project/end-to-end/src/canary/browser.ts index c455d9e95ea..7aa320a2079 100644 --- a/yarn-project/end-to-end/src/canary/browser.ts +++ b/yarn-project/end-to-end/src/canary/browser.ts @@ -1,6 +1,6 @@ /* eslint-disable no-console */ import * as AztecJs from '@aztec/aztec.js'; -import { PrivateTokenContractAbi } from '@aztec/noir-contracts/artifacts'; +import { TokenContractAbi } from '@aztec/noir-contracts/artifacts'; import { Server } from 'http'; import Koa from 'koa'; @@ -111,60 +111,66 @@ export const browserTestSuite = (setup: () => Server, pageLogger: AztecJs.DebugL expect(stringAccounts.includes(result)).toBeTruthy(); }, 15_000); - it('Deploys Private Token contract', async () => { - await deployPrivateTokenContract(); - }, 30_000); + it('Deploys Token contract', async () => { + await deployTokenContract(); + }, 60_000); it("Gets the owner's balance", async () => { const result = await page.evaluate( - async (rpcUrl, contractAddress, PrivateTokenContractAbi) => { + async (rpcUrl, contractAddress, TokenContractAbi) => { const { Contract, AztecAddress, createAztecRpcClient } = window.AztecJs; const client = createAztecRpcClient(rpcUrl!); const owner = (await client.getRegisteredAccounts())[0].address; const [wallet] = await AztecJs.getSandboxAccountsWallets(client); - const contract = await Contract.at(AztecAddress.fromString(contractAddress), PrivateTokenContractAbi, wallet); - const balance = await contract.methods.getBalance(owner).view({ from: owner }); - console.log(`Owner's balance: ${balance}`); + const contract = await Contract.at(AztecAddress.fromString(contractAddress), TokenContractAbi, wallet); + const balance = await contract.methods.balance_of_private({ address: owner }).view({ from: owner }); return balance; }, SANDBOX_URL, - (await getPrivateTokenAddress()).toString(), - PrivateTokenContractAbi, + (await getTokenAddress()).toString(), + TokenContractAbi, ); expect(result).toEqual(initialBalance); }); it('Sends a transfer TX', async () => { const result = await page.evaluate( - async (rpcUrl, contractAddress, transferAmount, PrivateTokenContractAbi) => { + async (rpcUrl, contractAddress, transferAmount, TokenContractAbi) => { console.log(`Starting transfer tx`); const { AztecAddress, Contract, createAztecRpcClient } = window.AztecJs; const client = createAztecRpcClient(rpcUrl!); const accounts = await client.getRegisteredAccounts(); - const owner = accounts[0].address; const receiver = accounts[1].address; const [wallet] = await AztecJs.getSandboxAccountsWallets(client); - const contract = await Contract.at(AztecAddress.fromString(contractAddress), PrivateTokenContractAbi, wallet); - await contract.methods.transfer(transferAmount, receiver).send().wait(); + const contract = await Contract.at(AztecAddress.fromString(contractAddress), TokenContractAbi, wallet); + await contract.methods + .transfer({ address: accounts[0].address }, { address: receiver }, transferAmount, 0) + .send() + .wait(); console.log(`Transferred ${transferAmount} tokens to new Account`); - const receiverBalance = await contract.methods.getBalance(receiver).view({ from: receiver }); - console.log(`Receiver's balance is now: ${receiverBalance}`); - const senderBalance = await contract.methods.getBalance(owner).view({ from: owner }); - console.log(`Updated sender balance: ${senderBalance}`); - return receiverBalance; + return await contract.methods.balance_of_private({ address: receiver }).view({ from: receiver }); }, SANDBOX_URL, - (await getPrivateTokenAddress()).toString(), + (await getTokenAddress()).toString(), transferAmount, - PrivateTokenContractAbi, + TokenContractAbi, ); expect(result).toEqual(transferAmount); }, 60_000); - const deployPrivateTokenContract = async () => { + const deployTokenContract = async () => { const txHash = await page.evaluate( - async (rpcUrl, privateKeyString, initialBalance, PrivateTokenContractAbi) => { - const { GrumpkinScalar, DeployMethod, createAztecRpcClient, getUnsafeSchnorrAccount } = window.AztecJs; + async (rpcUrl, privateKeyString, initialBalance, TokenContractAbi) => { + const { + GrumpkinScalar, + DeployMethod, + createAztecRpcClient, + getUnsafeSchnorrAccount, + Contract, + Fr, + computeMessageSecretHash, + getSandboxAccountsWallets, + } = window.AztecJs; const client = createAztecRpcClient(rpcUrl!); let accounts = await client.getRegisteredAccounts(); if (accounts.length === 0) { @@ -173,20 +179,25 @@ export const browserTestSuite = (setup: () => Server, pageLogger: AztecJs.DebugL await getUnsafeSchnorrAccount(client, privateKey).waitDeploy(); accounts = await client.getRegisteredAccounts(); } - const owner = accounts[0]; - const tx = new DeployMethod(owner.publicKey, client, PrivateTokenContractAbi, [ - initialBalance, - owner.address, - ]).send(); + const [owner] = await getSandboxAccountsWallets(client); + const tx = new DeployMethod(accounts[0].publicKey, client, TokenContractAbi).send(); await tx.wait(); const receipt = await tx.getReceipt(); console.log(`Contract Deployed: ${receipt.contractAddress}`); + + const token = await Contract.at(receipt.contractAddress!, TokenContractAbi, owner); + await token.methods._initialize({ address: owner.getAddress() }).send().wait(); + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + await token.methods.mint_private(initialBalance, secretHash).send().wait(); + await token.methods.redeem_shield({ address: owner.getAddress() }, initialBalance, secret).send().wait(); + return receipt.txHash.toString(); }, SANDBOX_URL, privKey.toString(), initialBalance, - PrivateTokenContractAbi, + TokenContractAbi, ); const txResult = await testClient.getTxReceipt(AztecJs.TxHash.fromString(txHash)); @@ -194,9 +205,9 @@ export const browserTestSuite = (setup: () => Server, pageLogger: AztecJs.DebugL contractAddress = txResult.contractAddress!; }; - const getPrivateTokenAddress = async () => { + const getTokenAddress = async () => { if (!contractAddress) { - await deployPrivateTokenContract(); + await deployTokenContract(); } return contractAddress; }; diff --git a/yarn-project/end-to-end/src/canary/cli.ts b/yarn-project/end-to-end/src/canary/cli.ts index 7cda9b1c3bd..2cc7442ef29 100644 --- a/yarn-project/end-to-end/src/canary/cli.ts +++ b/yarn-project/end-to-end/src/canary/cli.ts @@ -1,4 +1,4 @@ -import { AztecAddress, AztecRPC, CompleteAddress, DebugLogger } from '@aztec/aztec.js'; +import { AztecAddress, AztecRPC, CompleteAddress, DebugLogger, Fr, computeMessageSecretHash } from '@aztec/aztec.js'; import { getProgram } from '@aztec/cli'; import stringArgv from 'string-argv'; @@ -52,7 +52,9 @@ export const cliTestSuite = ( if (addRpcUrl) { args.push('--rpc-url', rpcUrl); } - return cli.parseAsync(args); + const res = cli.parseAsync(args); + resetCli(); + return res; }; // Returns first match across all logs collected so far @@ -115,8 +117,8 @@ export const cliTestSuite = ( expect(foundAddress).toBeDefined(); const ownerAddress = AztecAddress.fromString(foundAddress!); - debug('Deploy Private Token Contract using created account.'); - await run(`deploy PrivateTokenContractAbi --args ${INITIAL_BALANCE} ${ownerAddress} --salt 0`); + debug('Deploy Token Contract using created account.'); + await run(`deploy TokenContractAbi --salt 0`); const loggedAddress = findInLogs(/Contract\sdeployed\sat\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; expect(loggedAddress).toBeDefined(); contractAddress = AztecAddress.fromString(loggedAddress!); @@ -129,6 +131,22 @@ export const cliTestSuite = ( const checkResult = findInLogs(/Contract\sfound\sat\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address; expect(checkResult).toEqual(deployedContract?.contractAddress.toString()); + debug('Initialize token contract.'); + await run( + `send _initialize --args ${ownerAddress} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()} --private-key ${privKey}`, + ); + + const secret = Fr.random(); + const secretHash = await computeMessageSecretHash(secret); + + debug('Mint initial tokens.'); + await run( + `send mint_private --args ${INITIAL_BALANCE} ${secretHash} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()} --private-key ${privKey}`, + ); + await run( + `send redeem_shield --args ${ownerAddress} ${INITIAL_BALANCE} ${secret} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()} --private-key ${privKey}`, + ); + // clear logs clearLogs(); await run(`get-contract-data ${loggedAddress}`); @@ -137,7 +155,7 @@ export const cliTestSuite = ( debug("Check owner's balance"); await run( - `call getBalance --args ${ownerAddress} --contract-abi PrivateTokenContractAbi --contract-address ${contractAddress.toString()}`, + `call balance_of_private --args ${ownerAddress} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()}`, ); const balance = findInLogs(/View\sresult:\s+(?\S+)/)?.groups?.data; expect(balance!).toEqual(`${BigInt(INITIAL_BALANCE).toString()}n`); @@ -148,7 +166,7 @@ export const cliTestSuite = ( const receiver = existingAccounts.find(acc => acc.address.toString() !== ownerAddress.toString()); await run( - `send transfer --args ${TRANSFER_BALANCE} ${receiver?.address.toString()} --contract-address ${contractAddress.toString()} --contract-abi PrivateTokenContractAbi --private-key ${privKey}`, + `send transfer --args ${ownerAddress.toString()} ${receiver?.address.toString()} ${TRANSFER_BALANCE} 0 --contract-address ${contractAddress.toString()} --contract-abi TokenContractAbi --private-key ${privKey}`, ); const txHash = findInLogs(/Transaction\shash:\s+(?\S+)/)?.groups?.txHash; @@ -159,13 +177,11 @@ export const cliTestSuite = ( expect(parsedResult.txHash).toEqual(txHash); expect(parsedResult.status).toEqual('mined'); debug("Check Receiver's balance"); - // Reset CLI as we're calling getBalance again - resetCli(); clearLogs(); await run( - `call getBalance --args ${receiver?.address.toString()} --contract-abi PrivateTokenContractAbi --contract-address ${contractAddress.toString()}`, + `call balance_of_private --args ${receiver?.address.toString()} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()}`, ); const receiverBalance = findInLogs(/View\sresult:\s+(?\S+)/)?.groups?.data; expect(receiverBalance).toEqual(`${BigInt(TRANSFER_BALANCE).toString()}n`); - }, 30_000); + }, 100_000); }); diff --git a/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts b/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts index 07fe8f805f2..94e8aeba8af 100644 --- a/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts @@ -77,8 +77,8 @@ describe('e2e_2_rpc_servers', () => { expect(balance).toBe(expectedBalance); }; - const deployPrivateTokenContract = async (initialBalance: bigint, owner: AztecAddress) => { - logger(`Deploying PrivateToken contract...`); + const deployTokenContract = async (initialBalance: bigint, owner: AztecAddress) => { + logger(`Deploying Token contract...`); const contract = await TokenContract.deploy(walletA).send().deployed(); expect((await contract.methods._initialize({ address: owner }).send().wait()).status).toBe(TxStatus.MINED); @@ -102,7 +102,7 @@ describe('e2e_2_rpc_servers', () => { const transferAmount1 = 654n; const transferAmount2 = 323n; - const completeTokenAddress = await deployPrivateTokenContract(initialBalance, userA.address); + const completeTokenAddress = await deployTokenContract(initialBalance, userA.address); const tokenAddress = completeTokenAddress.address; // Add account B to wallet A @@ -110,7 +110,7 @@ describe('e2e_2_rpc_servers', () => { // Add account A to wallet B await aztecRpcServerB.registerRecipient(userA); - // Add privateToken to RPC server B + // Add token to RPC server B await aztecRpcServerB.addContracts([ { abi: TokenContract.abi, From 9fc02a83e3a64d740de2a3b32d665519857048a4 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Sat, 16 Sep 2023 16:17:44 +0000 Subject: [PATCH 6/6] feat: update `up-quick-start` --- docs/docs/external/up-quick-start.md | 2 +- .../end-to-end/src/guides/up_quick_start.sh | 61 +++++++++++++------ 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/docs/docs/external/up-quick-start.md b/docs/docs/external/up-quick-start.md index d6fb502788c..b62d371cd88 100644 --- a/docs/docs/external/up-quick-start.md +++ b/docs/docs/external/up-quick-start.md @@ -12,7 +12,7 @@ The sandbox is preloaded with two [accounts](../concepts/foundation/accounts/mai #include_code declare-accounts yarn-project/end-to-end/src/guides/up_quick_start.sh bash noTitle,noLineNumbers,noSourceLink -Start by deploying a private token [contract](../concepts/foundation/contracts.md), minting an initial supply of private tokens to Alice: +Start by deploying a token [contract](../concepts/foundation/contracts.md), initializing it and minting tokens to Alice: #include_code deploy yarn-project/end-to-end/src/guides/up_quick_start.sh bash noTitle,noLineNumbers,noSourceLink 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 c27ff3454f3..7b25a747dd6 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 @@ -4,48 +4,71 @@ set -eux # docs:start:declare-accounts -ALICE="0x2e13f0201905944184fc2c09d29fcf0cac07647be171656a275f63d99b819360" -BOB="0x0d557417a3ce7d7b356a8f15d79a868fd8da2af9c5f4981feb9bcf0b614bd17e" +ALICE="0x296904eaff80711ddd5fd39d75920bfc22725cc0ae3089f16a09a4ceb91be141" +BOB="0x1106245c5c50798338e55094c38025db4053a25e96dd8cbc1e87c6dcbfb9d2ba" +ALICE_PRIVATE_KEY="0x2153536ff6628eee01cf4024889ff977a18d9fa61d0e414422f7681cf085c281" # docs:end:declare-accounts # docs:start:deploy aztec-cli deploy \ - PrivateTokenContractAbi \ - --args 1000000 $ALICE \ + TokenContractAbi \ --salt 0 + +aztec-cli check-deploy --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c + +aztec-cli send _initialize \ + --args $ALICE \ + --contract-abi TokenContractAbi \ + --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c \ + --private-key $ALICE_PRIVATE_KEY # docs:end:deploy -aztec-cli check-deploy --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f +# docs:start:mint-private +SECRET="0x29bf6afaf29f61cbcf2a4fa7da97be481fb418dc08bdab5338839974beb7b49f" +SECRET_HASH="0x0a42b1fe22b652cc8610e33bb1128040ce2d2862e7041ff235aa871739822b74" + +aztec-cli send mint_private \ + --args 1000 $SECRET_HASH \ + --contract-abi TokenContractAbi \ + --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c \ + --private-key $ALICE_PRIVATE_KEY + +aztec-cli send redeem_shield \ + --args $ALICE 1000 $SECRET \ + --contract-abi TokenContractAbi \ + --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c \ + --private-key $ALICE_PRIVATE_KEY +# docs:end:mint-private # docs:start:get-balance -aztec-cli call getBalance \ +aztec-cli call balance_of_private \ --args $ALICE \ - --contract-abi PrivateTokenContractAbi \ - --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f + --contract-abi TokenContractAbi \ + --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c # docs:end:get-balance # docs:start:transfer aztec-cli send transfer \ - --args 500 $ALICE $BOB \ - --contract-abi PrivateTokenContractAbi \ - --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f \ - --private-key 0xb2803ec899f76f6b2ac011480d24028f1a29587f8a3a92f7ee9d48d8c085c284 + --args $ALICE $BOB 500 0 \ + --contract-abi TokenContractAbi \ + --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c \ + --private-key $ALICE_PRIVATE_KEY -aztec-cli call getBalance \ +aztec-cli call balance_of_private \ --args $ALICE \ - --contract-abi PrivateTokenContractAbi \ - --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f + --contract-abi TokenContractAbi \ + --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c -aztec-cli call getBalance \ +aztec-cli call balance_of_private \ --args $BOB \ - --contract-abi PrivateTokenContractAbi \ - --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f + --contract-abi TokenContractAbi \ + --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c # docs:end:transfer aztec-cli get-logs # Test end result -BOB_BALANCE=$(aztec-cli call getBalance --args $BOB --contract-abi PrivateTokenContractAbi --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f) +BOB_BALANCE=$(aztec-cli call balance_of_private --args $BOB --contract-abi TokenContractAbi --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c) if ! echo $BOB_BALANCE | grep -q 500; then echo "Incorrect Bob balance after transaction (expected 500 but got $BOB_BALANCE)" exit 1