From 0df374dfa02ddb496b7992ee37ca9b0910e6c2df Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 15:38:15 +0000 Subject: [PATCH 01/11] fix: prevent ebs races --- .github/workflows/ci.yml | 30 +++++++++++++++--------------- scripts/attach_ebs_cache.sh | 24 ++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1d67fb668b..3c93f093cc2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,20 +152,20 @@ jobs: timeout-minutes: 15 run: earthly --no-output +bench-ultra-honk --bench_mode=cache - # # Post actions, deploy and summarize logs - # aztec-bench-summary: - # runs-on: ${{ github.actor }} - # # IMPORTANT security flaw if we don't need 'check-run-condition' - # needs: e2e-x86 - # concurrency: - # group: aztec-bench-summary-${{ github.ref_name == 'master' && github.run_id || github.ref_name }}-x86 - # cancel-in-progress: true - # steps: - # - name: Checkout - # uses: actions/checkout@v4 - # with: - # ref: ${{ github.event.pull_request.head.sha }} + # Post actions, deploy and summarize logs + aztec-bench-summary: + runs-on: ${{ github.actor }} + # IMPORTANT security flaw if we don't need 'check-run-condition' + needs: e2e-x86 + concurrency: + group: aztec-bench-summary-${{ github.ref_name == 'master' && github.run_id || github.ref_name }}-x86 + cancel-in-progress: true + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - # - name: "Assemble benchmark summary from uploaded logs" - # command: ./scripts/ci/assemble_e2e_benchmark_earthly.sh + - name: "Assemble benchmark summary from uploaded logs" + command: ./scripts/ci/assemble_e2e_benchmark_earthly.sh diff --git a/scripts/attach_ebs_cache.sh b/scripts/attach_ebs_cache.sh index 7eaa988afc2..a4650e370b2 100755 --- a/scripts/attach_ebs_cache.sh +++ b/scripts/attach_ebs_cache.sh @@ -8,7 +8,28 @@ AVAILABILITY_ZONE="us-east-2a" VOLUME_TYPE="gp2" INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id) -# TODO also mount various other aspects of docker image metadata +# Check if someone else is doing this +if [ -f /run/.ebs-cache-mounted ] ; then + MAX_WAIT_TIME=300 # Maximum wait time in seconds + WAIT_INTERVAL=10 # Interval between checks in seconds + elapsed_time=0 + # Check for existing mount, assume we can continue if existing + while ! mount | grep -q "/var/lib/docker/volumes type ext4"; then + echo "Someone already marked as mounting, waiting for them..." + if [ $elapsed_time -ge $MAX_WAIT_TIME ]; then + echo "Cache mount did not become available within $MAX_WAIT_TIME seconds... race condition?" + exit 1 + fi + + sleep $WAIT_INTERVAL + elapsed_time=$((elapsed_time + WAIT_INTERVAL)) + fi + echo "Detected existing mount, continuing..." + exit 0 +fi + +# Mark to prevent race conditions +touch /run/.ebs-cache-mounted # Check for existing mount, assume we can continue if existing if mount | grep -q "/var/lib/docker/volumes type ext4"; then @@ -57,7 +78,6 @@ while [ "$(aws ec2 describe-volumes \ --volume-ids $VOLUME_ID \ --query "Volumes[0].State" \ --output text)" != "available" ]; do - sleep 1 if [ $elapsed_time -ge $MAX_WAIT_TIME ]; then echo "Volume $VOLUME_ID did not become available within $MAX_WAIT_TIME seconds." exit 1 From d55fad5acf7e9ee839963086af02b6139816bbdb Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 11:45:55 -0400 Subject: [PATCH 02/11] Remove unused bench --- .github/workflows/ci.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c93f093cc2..6a04a246677 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -151,21 +151,3 @@ jobs: working-directory: ./barretenberg/cpp/ timeout-minutes: 15 run: earthly --no-output +bench-ultra-honk --bench_mode=cache - - # Post actions, deploy and summarize logs - aztec-bench-summary: - runs-on: ${{ github.actor }} - # IMPORTANT security flaw if we don't need 'check-run-condition' - needs: e2e-x86 - concurrency: - group: aztec-bench-summary-${{ github.ref_name == 'master' && github.run_id || github.ref_name }}-x86 - cancel-in-progress: true - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: "Assemble benchmark summary from uploaded logs" - command: ./scripts/ci/assemble_e2e_benchmark_earthly.sh - From c1df05a0632231445bc33ea43a951f9623ea35fe Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 16:10:02 +0000 Subject: [PATCH 03/11] fix syntax --- scripts/attach_ebs_cache.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/attach_ebs_cache.sh b/scripts/attach_ebs_cache.sh index a4650e370b2..78e6bb06b91 100755 --- a/scripts/attach_ebs_cache.sh +++ b/scripts/attach_ebs_cache.sh @@ -14,7 +14,7 @@ if [ -f /run/.ebs-cache-mounted ] ; then WAIT_INTERVAL=10 # Interval between checks in seconds elapsed_time=0 # Check for existing mount, assume we can continue if existing - while ! mount | grep -q "/var/lib/docker/volumes type ext4"; then + while ! mount | grep -q "/var/lib/docker/volumes type ext4"; do echo "Someone already marked as mounting, waiting for them..." if [ $elapsed_time -ge $MAX_WAIT_TIME ]; then echo "Cache mount did not become available within $MAX_WAIT_TIME seconds... race condition?" @@ -23,7 +23,7 @@ if [ -f /run/.ebs-cache-mounted ] ; then sleep $WAIT_INTERVAL elapsed_time=$((elapsed_time + WAIT_INTERVAL)) - fi + done echo "Detected existing mount, continuing..." exit 0 fi From 382d5053e46f4fe188855c6e00bcc0dafd7f2c13 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 16:18:04 +0000 Subject: [PATCH 04/11] limit prover cores --- .github/workflows/ci.yml | 3 ++- barretenberg/cpp/Earthfile | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a04a246677..ebe6980349d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,7 +96,8 @@ jobs: - name: "Native Prover Tests" working-directory: ./barretenberg/cpp/ timeout-minutes: 25 - run: earthly --no-output +test + # limit our parallelism to half our cores + run: earthly --no-output +test --hardware_concurrency=64 # push benchmarking binaries to dockerhub registry bb-bench-binaries: diff --git a/barretenberg/cpp/Earthfile b/barretenberg/cpp/Earthfile index 3d1dbc3aece..84c6c0c7297 100644 --- a/barretenberg/cpp/Earthfile +++ b/barretenberg/cpp/Earthfile @@ -232,9 +232,14 @@ test-clang-format: RUN ./format.sh check test: + ARG hardware_concurrency="" FROM +source COPY --dir +test-binaries/build build BUILD +test-clang-format FROM +preset-release-assert-test COPY --dir ./srs_db/+build/. srs_db + # limit hardware concurrency, if provided + IF [ "$HARDWARE_CONCURRENCY" != "" ] + ENV HARDWARE_CONCURRENCY=$hardware_concurrency + END RUN cd build && GTEST_COLOR=1 ctest -j$(nproc) --output-on-failure From daf03af15ea934c3e8a4fb6f31c6f67428e5f04f Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 17:24:13 +0000 Subject: [PATCH 05/11] race check fix --- scripts/attach_ebs_cache.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/attach_ebs_cache.sh b/scripts/attach_ebs_cache.sh index 78e6bb06b91..d30812b9f9b 100755 --- a/scripts/attach_ebs_cache.sh +++ b/scripts/attach_ebs_cache.sh @@ -14,7 +14,7 @@ if [ -f /run/.ebs-cache-mounted ] ; then WAIT_INTERVAL=10 # Interval between checks in seconds elapsed_time=0 # Check for existing mount, assume we can continue if existing - while ! mount | grep -q "/var/lib/docker/volumes type ext4"; do + while ! mount | grep -q "/var/lib/docker type ext4"; do echo "Someone already marked as mounting, waiting for them..." if [ $elapsed_time -ge $MAX_WAIT_TIME ]; then echo "Cache mount did not become available within $MAX_WAIT_TIME seconds... race condition?" From 506bd118e7a9cf93cb1ecb073168727c2f5522a8 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 17:37:53 +0000 Subject: [PATCH 06/11] allow keypair --- .github/workflows/setup-runner.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index 9f544f4f367..928ce594b4f 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -54,7 +54,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Start EC2 runner - uses: AztecProtocol/ec2-action-builder@v0.6 + uses: AztecProtocol/ec2-action-builder@v0.8 with: github_token: ${{ secrets.GH_SELF_HOSTED_RUNNER_TOKEN }} aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -69,6 +69,7 @@ jobs: ec2_instance_type: ${{ inputs.ec2_instance_type }} ec2_ami_id: ${{ inputs.ec2_ami_id }} ec2_instance_ttl: ${{ inputs.ec2_instance_ttl }} + ec2_key_name: "build-instance" ec2_instance_tags: '[{"Key": "Keep-Alive", "Value": "true"}]' setup: From 4bbba8103c1098accbc892bfa46f371f93ee594c Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 17:43:18 +0000 Subject: [PATCH 07/11] [ci restart-spot] From ee938f67f815ce16585f2b6704c5c88a0347f58f Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 20:49:06 +0000 Subject: [PATCH 08/11] disable flakes --- .github/workflows/start-spot.yml | 30 ++ .vscode/settings.json | 3 +- yarn-project/end-to-end/Earthfile | 20 +- .../src/e2e_account_init_fees.test.ts | 336 ------------------ .../end-to-end/src/e2e_p2p_network.test.ts | 159 --------- 5 files changed, 43 insertions(+), 505 deletions(-) create mode 100644 .github/workflows/start-spot.yml delete mode 100644 yarn-project/end-to-end/src/e2e_account_init_fees.test.ts delete mode 100644 yarn-project/end-to-end/src/e2e_p2p_network.test.ts diff --git a/.github/workflows/start-spot.yml b/.github/workflows/start-spot.yml new file mode 100644 index 00000000000..2cbc0e8415d --- /dev/null +++ b/.github/workflows/start-spot.yml @@ -0,0 +1,30 @@ +# Useful if the spot runners are in a bad state +name: Stop Personal Spot +on: + workflow_dispatch: {} +jobs: + stop-build-x86: + uses: ./.github/workflows/setup-runner.yml + with: + runner_label: ${{ github.actor }}-x86 + subaction: stop + # not used: + ebs_cache_size_gb: 256 + runner_concurrency: 50 + ec2_instance_type: m6a.32xlarge + ec2_ami_id: ami-0d8a9b0419ddb331a + ec2_instance_ttl: 40 + secrets: inherit + + stop-bench: + uses: ./.github/workflows/setup-runner.yml + with: + runner_label: ${{ github.actor }}-bench-x86 + subaction: stop + # not used: + ebs_cache_size_gb: 64 + runner_concurrency: 1 + ec2_instance_type: m6a.4xlarge + ec2_ami_id: ami-0d8a9b0419ddb331a + ec2_instance_ttl: 15 + secrets: inherit \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 8661488d112..ea41bbe2bc2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -165,5 +165,6 @@ "**/target/**": true, "**/l1-contracts/lib/**": true, "**/barretenberg/cpp/build*/**": true - } + }, + "cmake.sourceDirectory": "/mnt/user-data/adam/aztec-packages/barretenberg/cpp" } diff --git a/yarn-project/end-to-end/Earthfile b/yarn-project/end-to-end/Earthfile index 1a77fbc2683..f75127fe1f2 100644 --- a/yarn-project/end-to-end/Earthfile +++ b/yarn-project/end-to-end/Earthfile @@ -132,14 +132,16 @@ guides-dapp-testing: # ARG e2e_mode=local # DO +E2E_TEST --test=guides/up_quick_start.test.ts --e2e_mode=$e2e_mode -bench-publish-rollup: - ARG e2e_mode=local - DO +E2E_TEST --test=benchmarks/bench_publish_rollup.test.ts --debug="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" --e2e_mode=$e2e_mode --compose_file=./scripts/docker-compose-no-sandbox.yml +# TODO hanging +# bench-publish-rollup: +# ARG e2e_mode=local +# DO +E2E_TEST --test=benchmarks/bench_publish_rollup.test.ts --debug="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" --e2e_mode=$e2e_mode --compose_file=./scripts/docker-compose-no-sandbox.yml -bench-process-history: - ARG e2e_mode=local - DO +E2E_TEST --test=benchmarks/bench_process_history.test.ts --debug="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" --e2e_mode=$e2e_mode --compose_file=./scripts/docker-compose-no-sandbox.yml +# TODO hanging +# bench-process-history: +# ARG e2e_mode=local +# DO +E2E_TEST --test=benchmarks/bench_process_history.test.ts --debug="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" --e2e_mode=$e2e_mode --compose_file=./scripts/docker-compose-no-sandbox.yml -bench-tx-size: - ARG e2e_mode=local - DO +E2E_TEST --test=benchmarks/bench_tx_size_fees.test.ts --debug="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" --e2e_mode=$e2e_mode --enable_gas=1 --compose_file=./scripts/docker-compose-no-sandbox.yml +# bench-tx-size: +# ARG e2e_mode=local +# DO +E2E_TEST --test=benchmarks/bench_tx_size_fees.test.ts --debug="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" --e2e_mode=$e2e_mode --enable_gas=1 --compose_file=./scripts/docker-compose-no-sandbox.yml diff --git a/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts deleted file mode 100644 index 94f7321a0ae..00000000000 --- a/yarn-project/end-to-end/src/e2e_account_init_fees.test.ts +++ /dev/null @@ -1,336 +0,0 @@ -import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { - type AccountManager, - type DebugLogger, - ExtendedNote, - Fr, - NativeFeePaymentMethod, - Note, - PrivateFeePaymentMethod, - PublicFeePaymentMethod, - Schnorr, - type TxHash, - TxStatus, - type Wallet, - computeMessageSecretHash, - generatePublicKey, -} from '@aztec/aztec.js'; -import { type AztecAddress, CompleteAddress, Fq } from '@aztec/circuits.js'; -import { - TokenContract as BananaCoin, - FPCContract, - type GasTokenContract, - SchnorrAccountContract, -} from '@aztec/noir-contracts.js'; - -import { jest } from '@jest/globals'; - -import { - type BalancesFn, - type EndToEndContext, - expectMapping, - getBalancesFn, - publicDeployAccounts, - setup, -} from './fixtures/utils.js'; -import { GasPortalTestingHarnessFactory, type IGasBridgingTestHarness } from './shared/gas_portal_test_harness.js'; - -const TOKEN_NAME = 'BananaCoin'; -const TOKEN_SYMBOL = 'BC'; -const TOKEN_DECIMALS = 18n; -const BRIDGED_FPC_GAS = 444n; - -jest.setTimeout(1000_000); - -describe('e2e_fees_account_init', () => { - let ctx: EndToEndContext; - let logger: DebugLogger; - let sequencer: Wallet; - let sequencersAddress: AztecAddress; - let alice: Wallet; - - let gas: GasTokenContract; - let bananaCoin: BananaCoin; - let bananaFPC: FPCContract; - - let gasBridgeTestHarness: IGasBridgingTestHarness; - - let gasBalances: BalancesFn; - let bananaPublicBalances: BalancesFn; - let bananaPrivateBalances: BalancesFn; - - let bobsPrivateEncryptionKey: Fq; - let bobsPrivateSigningKey: Fq; - let bobsAccountManager: AccountManager; - let bobsAddress: AztecAddress; - - let bobsInitialGas: bigint; - let alicesInitialGas: bigint; - let sequencersInitialGas: bigint; - let fpcsInitialGas: bigint; - let fpcsInitialPublicBananas: bigint; - - let maxFee: bigint; - let actualFee: bigint; - - // run this after each test's setup phase to get the initial balances - async function initBalances() { - [[bobsInitialGas, alicesInitialGas, sequencersInitialGas, fpcsInitialGas], [fpcsInitialPublicBananas]] = - await Promise.all([ - gasBalances(bobsAddress, alice.getAddress(), sequencersAddress, bananaFPC.address), - bananaPublicBalances(bananaFPC.address), - ]); - } - - beforeAll(async () => { - ctx = await setup(2, {}, {}, true); - logger = ctx.logger; - [sequencer, alice] = ctx.wallets; - sequencersAddress = sequencer.getAddress(); - - await ctx.aztecNode.setConfig({ - feeRecipient: sequencersAddress, - }); - - gasBridgeTestHarness = await GasPortalTestingHarnessFactory.create({ - pxeService: ctx.pxe, - publicClient: ctx.deployL1ContractsValues.publicClient, - walletClient: ctx.deployL1ContractsValues.walletClient, - wallet: ctx.wallet, - logger: ctx.logger, - mockL1: false, - }); - - gas = gasBridgeTestHarness.l2Token; - - bananaCoin = await BananaCoin.deploy(sequencer, sequencersAddress, TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS) - .send() - .deployed(); - - logger.verbose(`BananaCoin deployed at ${bananaCoin.address}`); - - bananaFPC = await FPCContract.deploy(sequencer, bananaCoin.address, gas.address).send().deployed(); - logger.verbose(`bananaPay deployed at ${bananaFPC.address}`); - await publicDeployAccounts(sequencer, [sequencer]); - - await gasBridgeTestHarness.bridgeFromL1ToL2(BRIDGED_FPC_GAS, BRIDGED_FPC_GAS, bananaFPC.address); - - bananaPublicBalances = getBalancesFn('🍌.public', bananaCoin.methods.balance_of_public, logger); - bananaPrivateBalances = getBalancesFn('🍌.private', bananaCoin.methods.balance_of_private, logger); - gasBalances = getBalancesFn('⛽', gas.methods.balance_of_public, logger); - }); - - afterAll(() => ctx.teardown()); - - beforeEach(() => { - maxFee = 3n; - actualFee = 1n; - bobsPrivateEncryptionKey = Fq.random(); - bobsPrivateSigningKey = Fq.random(); - bobsAccountManager = getSchnorrAccount(ctx.pxe, bobsPrivateEncryptionKey, bobsPrivateSigningKey, Fr.random()); - bobsAddress = bobsAccountManager.getCompleteAddress().address; - }); - - describe('account pays its own fee', () => { - describe('in the gas token', () => { - beforeEach(async () => { - await gasBridgeTestHarness.bridgeFromL1ToL2(BRIDGED_FPC_GAS, BRIDGED_FPC_GAS, bobsAddress); - }); - - beforeEach(initBalances); - - it('account pays for its own fee', async () => { - await bobsAccountManager - .deploy({ - fee: { - maxFee, - paymentMethod: await NativeFeePaymentMethod.create(await bobsAccountManager.getWallet()), - }, - }) - .wait(); - - await expectMapping( - gasBalances, - [bobsAddress, sequencersAddress], - [bobsInitialGas - actualFee, sequencersInitialGas + actualFee], - ); - }); - }); - - describe('privately through an FPC', () => { - let mintedPrivateBananas: bigint; - beforeEach(async () => { - mintedPrivateBananas = 42n; - - // TODO the following sequence of events ends in a timeout - // 1. pxe.registerRecipient (aka just add the public key so pxe can encrypt notes) - // 2. mint note for mew account - // 3. accountManager.register (add pubkey + start a note processor) - // as a workaround, register (pubkey + note processors) the account first, before minting the note - await bobsAccountManager.register(); - - const secret = Fr.random(); - const secretHash = computeMessageSecretHash(secret); - const mintTx = await bananaCoin.methods.mint_private(mintedPrivateBananas, secretHash).send().wait(); - await addTransparentNoteToPxe(sequencersAddress, mintedPrivateBananas, secretHash, mintTx.txHash); - - // at this point, the new account owns a note - // but the account doesn't have a NoteProcessor registered - // so the note exists on the blockchain as an encrypted blob - // tell the pxe to start a note processor for the account ahead of its deployment - await bananaCoin.methods.redeem_shield(bobsAddress, mintedPrivateBananas, secret).send().wait(); - }); - - beforeEach(initBalances); - - it('account pays for its own fee', async () => { - const rebateSecret = Fr.random(); - const tx = await bobsAccountManager - .deploy({ - fee: { - maxFee, - paymentMethod: new PrivateFeePaymentMethod( - bananaCoin.address, - bananaFPC.address, - await bobsAccountManager.getWallet(), - rebateSecret, - ), - }, - }) - .wait(); - - expect(tx.status).toEqual(TxStatus.MINED); - - // the new account should have paid the full fee to the FPC - await expect(bananaPrivateBalances(bobsAddress)).resolves.toEqual([mintedPrivateBananas - maxFee]); - - // the FPC got paid through "unshield", so it's got a new public balance - await expect(bananaPublicBalances(bananaFPC.address)).resolves.toEqual([fpcsInitialPublicBananas + actualFee]); - - // the FPC should have paid the sequencer - await expect(gasBalances(bananaFPC.address, sequencersAddress)).resolves.toEqual([ - fpcsInitialGas - actualFee, - sequencersInitialGas + actualFee, - ]); - - // the new account should have received a refund - await expect( - // this rejects if note can't be added - addTransparentNoteToPxe(bobsAddress, maxFee - actualFee, computeMessageSecretHash(rebateSecret), tx.txHash), - ).resolves.toBeUndefined(); - - // and it can redeem the refund - await bananaCoin.methods - .redeem_shield(bobsAccountManager.getCompleteAddress().address, maxFee - actualFee, rebateSecret) - .send() - .wait(); - - await expect(bananaPrivateBalances(bobsAccountManager.getCompleteAddress().address)).resolves.toEqual([ - mintedPrivateBananas - actualFee, - ]); - }); - }); - - describe('public through an FPC', () => { - let mintedPublicBananas: bigint; - - beforeEach(async () => { - mintedPublicBananas = 37n; - await bananaCoin.methods.mint_public(bobsAddress, mintedPublicBananas).send().wait(); - }); - - beforeEach(initBalances); - - it('account pays for its own fee', async () => { - const tx = await bobsAccountManager - .deploy({ - skipPublicDeployment: false, - fee: { - maxFee, - paymentMethod: new PublicFeePaymentMethod( - bananaCoin.address, - bananaFPC.address, - await bobsAccountManager.getWallet(), - ), - }, - }) - .wait(); - - expect(tx.status).toEqual(TxStatus.MINED); - - // we should have paid the fee to the FPC - await expect( - bananaPublicBalances(bobsAccountManager.getCompleteAddress().address, bananaFPC.address), - ).resolves.toEqual([mintedPublicBananas - actualFee, fpcsInitialPublicBananas + actualFee]); - - // the FPC should have paid the sequencer - await expect(gasBalances(bananaFPC.address, sequencersAddress)).resolves.toEqual([ - fpcsInitialGas - actualFee, - sequencersInitialGas + actualFee, - ]); - }); - }); - }); - - describe('another account pays the fee', () => { - describe('in the gas token', () => { - beforeEach(async () => { - await gasBridgeTestHarness.bridgeFromL1ToL2(BRIDGED_FPC_GAS, BRIDGED_FPC_GAS, alice.getAddress()); - }); - - beforeEach(initBalances); - - it("alice pays for bob's account", async () => { - // bob generates the private keys for his account on his own - const instance = bobsAccountManager.getInstance(); - - // and gives the public keys to alice - const encPubKey = generatePublicKey(bobsPrivateEncryptionKey); - const signingPubKey = new Schnorr().computePublicKey(bobsPrivateSigningKey); - const completeAddress = CompleteAddress.fromPublicKeyAndInstance(encPubKey, instance); - - // alice registers the keys in the PXE - await ctx.pxe.registerRecipient(completeAddress); - - // and deploys bob's account, paying the fee from her balance - const tx = await SchnorrAccountContract.deployWithPublicKey(encPubKey, alice, signingPubKey.x, signingPubKey.y) - .send({ - contractAddressSalt: instance.salt, - skipClassRegistration: true, - skipPublicDeployment: true, - skipInitialization: false, - universalDeploy: true, - fee: { - maxFee, - paymentMethod: await NativeFeePaymentMethod.create(alice), - }, - }) - .wait(); - - expect(tx.status).toBe(TxStatus.MINED); - - await expectMapping( - gasBalances, - [alice.getAddress(), bobsAddress, sequencersAddress], - [alicesInitialGas - actualFee, bobsInitialGas, sequencersInitialGas + actualFee], - ); - - // bob can now use his wallet - const bobsWallet = await bobsAccountManager.getWallet(); - await expect(gas.withWallet(bobsWallet).methods.balance_of_public(alice.getAddress()).simulate()).resolves.toBe( - alicesInitialGas - actualFee, - ); - }); - }); - }); - - async function addTransparentNoteToPxe(owner: AztecAddress, amount: bigint, secretHash: Fr, txHash: TxHash) { - const storageSlot = new Fr(5); // The storage slot of `pending_shields` is 5. - const noteTypeId = new Fr(84114971101151129711410111011678111116101n); // TransparentNote - - const note = new Note([new Fr(amount), secretHash]); - // this note isn't encrypted but we need to provide a registered public key - const extendedNote = new ExtendedNote(note, owner, bananaCoin.address, storageSlot, noteTypeId, txHash); - await ctx.pxe.addNote(extendedNote); - } -}); diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts deleted file mode 100644 index 812350b4015..00000000000 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node'; -import { - type AztecAddress, - CompleteAddress, - type DebugLogger, - Fr, - Grumpkin, - GrumpkinScalar, - type SentTx, - TxStatus, -} from '@aztec/aztec.js'; -import { BootstrapNode, type P2PConfig, createLibP2PPeerId } from '@aztec/p2p'; -import { ConstantKeyPair, type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; - -import { mnemonicToAccount } from 'viem/accounts'; - -import { MNEMONIC } from './fixtures/fixtures.js'; -import { setup } from './fixtures/utils.js'; - -// Don't set this to a higher value than 9 because each node will use a different L1 publisher account and anvil seeds -const NUM_NODES = 4; -const NUM_TXS_PER_BLOCK = 4; -const NUM_TXS_PER_NODE = 2; -const BOOT_NODE_TCP_PORT = 40400; - -interface NodeContext { - node: AztecNodeService; - pxeService: PXEService; - txs: SentTx[]; - account: AztecAddress; -} - -describe('e2e_p2p_network', () => { - let config: AztecNodeConfig; - let logger: DebugLogger; - let teardown: () => Promise; - - beforeEach(async () => { - ({ teardown, config, logger } = await setup(1)); - }, 100_000); - - afterEach(() => teardown()); - - it('should rollup txs from all peers', async () => { - // create the bootstrap node for the network - const bootstrapNode = await createBootstrapNode(); - const bootstrapNodeAddress = `/ip4/127.0.0.1/tcp/${BOOT_NODE_TCP_PORT}/p2p/${bootstrapNode - .getPeerId()! - .toString()}`; - // create our network of nodes and submit txs into each of them - // the number of txs per node and the number of txs per rollup - // should be set so that the only way for rollups to be built - // is if the txs are successfully gossiped around the nodes. - const contexts: NodeContext[] = []; - for (let i = 0; i < NUM_NODES; i++) { - const node = await createNode(i + 1 + BOOT_NODE_TCP_PORT, bootstrapNodeAddress, i); - const context = await createPXEServiceAndSubmitTransactions(node, NUM_TXS_PER_NODE); - contexts.push(context); - } - - // now ensure that all txs were successfully mined - await Promise.all(contexts.flatMap(context => context.txs.map(tx => tx.wait()))); - - // shutdown all nodes. - for (const context of contexts) { - await context.node.stop(); - await context.pxeService.stop(); - } - await bootstrapNode.stop(); - }, 120_000); - - const createBootstrapNode = async () => { - const peerId = await createLibP2PPeerId(); - const bootstrapNode = new BootstrapNode(logger); - const config: P2PConfig = { - p2pEnabled: true, - tcpListenPort: BOOT_NODE_TCP_PORT, - tcpListenIp: '0.0.0.0', - announceHostname: '/tcp/127.0.0.1', - announcePort: BOOT_NODE_TCP_PORT, - peerIdPrivateKey: Buffer.from(peerId.privateKey!).toString('hex'), - clientKADRouting: false, - minPeerCount: 10, - maxPeerCount: 100, - - // TODO: the following config options are not applicable to bootstrap nodes - p2pBlockCheckIntervalMS: 1000, - p2pL2QueueSize: 1, - transactionProtocol: '', - bootstrapNodes: [''], - }; - await bootstrapNode.start(config); - - return bootstrapNode; - }; - - // creates a P2P enabled instance of Aztec Node Service - const createNode = async (tcpListenPort: number, bootstrapNode: string, publisherAddressIndex: number) => { - // We use different L1 publisher accounts in order to avoid duplicate tx nonces. We start from - // publisherAddressIndex + 1 because index 0 was already used during test environment setup. - const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: publisherAddressIndex + 1 }); - const publisherPrivKey = Buffer.from(hdAccount.getHdKey().privateKey!); - config.publisherPrivateKey = `0x${publisherPrivKey!.toString('hex')}`; - - const newConfig: AztecNodeConfig = { - ...config, - tcpListenPort, - tcpListenIp: '0.0.0.0', - enableNat: false, - bootstrapNodes: [bootstrapNode], - minTxsPerBlock: NUM_TXS_PER_BLOCK, - maxTxsPerBlock: NUM_TXS_PER_BLOCK, - p2pEnabled: true, - clientKADRouting: false, - }; - return await AztecNodeService.createAndSync(newConfig); - }; - - // submits a set of transactions to the provided Private eXecution Environment (PXE) - const submitTxsTo = async (pxe: PXEService, account: AztecAddress, numTxs: number) => { - const txs: SentTx[] = []; - for (let i = 0; i < numTxs; i++) { - const tx = getSchnorrAccount(pxe, GrumpkinScalar.random(), GrumpkinScalar.random(), Fr.random()).deploy(); - logger.info(`Tx sent with hash ${await tx.getTxHash()}`); - const receipt = await tx.getReceipt(); - expect(receipt).toEqual( - expect.objectContaining({ - status: TxStatus.PENDING, - error: '', - }), - ); - logger.info(`Receipt received for ${await tx.getTxHash()}`); - txs.push(tx); - } - return txs; - }; - - // creates an instance of the PXE and submit a given number of transactions to it. - const createPXEServiceAndSubmitTransactions = async ( - node: AztecNodeService, - numTxs: number, - ): Promise => { - const rpcConfig = getRpcConfig(); - const pxeService = await createPXEService(node, rpcConfig, true); - - const keyPair = ConstantKeyPair.random(new Grumpkin()); - const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(keyPair.getPrivateKey(), Fr.random()); - await pxeService.registerAccount(keyPair.getPrivateKey(), completeAddress.partialAddress); - - const txs = await submitTxsTo(pxeService, completeAddress.address, numTxs); - return { - txs, - account: completeAddress.address, - pxeService, - node, - }; - }; -}); From 169d7b0db366d8253a67a5fd895600ffc8fa1a10 Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 20:58:50 +0000 Subject: [PATCH 09/11] reinstate flakes --- .../src/flakey_e2e_account_init_fees.test.ts | 336 ++++++++++++++++++ .../src/flakey_e2e_p2p_network.test.ts | 159 +++++++++ 2 files changed, 495 insertions(+) create mode 100644 yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts create mode 100644 yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts diff --git a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts new file mode 100644 index 00000000000..94f7321a0ae --- /dev/null +++ b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts @@ -0,0 +1,336 @@ +import { getSchnorrAccount } from '@aztec/accounts/schnorr'; +import { + type AccountManager, + type DebugLogger, + ExtendedNote, + Fr, + NativeFeePaymentMethod, + Note, + PrivateFeePaymentMethod, + PublicFeePaymentMethod, + Schnorr, + type TxHash, + TxStatus, + type Wallet, + computeMessageSecretHash, + generatePublicKey, +} from '@aztec/aztec.js'; +import { type AztecAddress, CompleteAddress, Fq } from '@aztec/circuits.js'; +import { + TokenContract as BananaCoin, + FPCContract, + type GasTokenContract, + SchnorrAccountContract, +} from '@aztec/noir-contracts.js'; + +import { jest } from '@jest/globals'; + +import { + type BalancesFn, + type EndToEndContext, + expectMapping, + getBalancesFn, + publicDeployAccounts, + setup, +} from './fixtures/utils.js'; +import { GasPortalTestingHarnessFactory, type IGasBridgingTestHarness } from './shared/gas_portal_test_harness.js'; + +const TOKEN_NAME = 'BananaCoin'; +const TOKEN_SYMBOL = 'BC'; +const TOKEN_DECIMALS = 18n; +const BRIDGED_FPC_GAS = 444n; + +jest.setTimeout(1000_000); + +describe('e2e_fees_account_init', () => { + let ctx: EndToEndContext; + let logger: DebugLogger; + let sequencer: Wallet; + let sequencersAddress: AztecAddress; + let alice: Wallet; + + let gas: GasTokenContract; + let bananaCoin: BananaCoin; + let bananaFPC: FPCContract; + + let gasBridgeTestHarness: IGasBridgingTestHarness; + + let gasBalances: BalancesFn; + let bananaPublicBalances: BalancesFn; + let bananaPrivateBalances: BalancesFn; + + let bobsPrivateEncryptionKey: Fq; + let bobsPrivateSigningKey: Fq; + let bobsAccountManager: AccountManager; + let bobsAddress: AztecAddress; + + let bobsInitialGas: bigint; + let alicesInitialGas: bigint; + let sequencersInitialGas: bigint; + let fpcsInitialGas: bigint; + let fpcsInitialPublicBananas: bigint; + + let maxFee: bigint; + let actualFee: bigint; + + // run this after each test's setup phase to get the initial balances + async function initBalances() { + [[bobsInitialGas, alicesInitialGas, sequencersInitialGas, fpcsInitialGas], [fpcsInitialPublicBananas]] = + await Promise.all([ + gasBalances(bobsAddress, alice.getAddress(), sequencersAddress, bananaFPC.address), + bananaPublicBalances(bananaFPC.address), + ]); + } + + beforeAll(async () => { + ctx = await setup(2, {}, {}, true); + logger = ctx.logger; + [sequencer, alice] = ctx.wallets; + sequencersAddress = sequencer.getAddress(); + + await ctx.aztecNode.setConfig({ + feeRecipient: sequencersAddress, + }); + + gasBridgeTestHarness = await GasPortalTestingHarnessFactory.create({ + pxeService: ctx.pxe, + publicClient: ctx.deployL1ContractsValues.publicClient, + walletClient: ctx.deployL1ContractsValues.walletClient, + wallet: ctx.wallet, + logger: ctx.logger, + mockL1: false, + }); + + gas = gasBridgeTestHarness.l2Token; + + bananaCoin = await BananaCoin.deploy(sequencer, sequencersAddress, TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS) + .send() + .deployed(); + + logger.verbose(`BananaCoin deployed at ${bananaCoin.address}`); + + bananaFPC = await FPCContract.deploy(sequencer, bananaCoin.address, gas.address).send().deployed(); + logger.verbose(`bananaPay deployed at ${bananaFPC.address}`); + await publicDeployAccounts(sequencer, [sequencer]); + + await gasBridgeTestHarness.bridgeFromL1ToL2(BRIDGED_FPC_GAS, BRIDGED_FPC_GAS, bananaFPC.address); + + bananaPublicBalances = getBalancesFn('🍌.public', bananaCoin.methods.balance_of_public, logger); + bananaPrivateBalances = getBalancesFn('🍌.private', bananaCoin.methods.balance_of_private, logger); + gasBalances = getBalancesFn('⛽', gas.methods.balance_of_public, logger); + }); + + afterAll(() => ctx.teardown()); + + beforeEach(() => { + maxFee = 3n; + actualFee = 1n; + bobsPrivateEncryptionKey = Fq.random(); + bobsPrivateSigningKey = Fq.random(); + bobsAccountManager = getSchnorrAccount(ctx.pxe, bobsPrivateEncryptionKey, bobsPrivateSigningKey, Fr.random()); + bobsAddress = bobsAccountManager.getCompleteAddress().address; + }); + + describe('account pays its own fee', () => { + describe('in the gas token', () => { + beforeEach(async () => { + await gasBridgeTestHarness.bridgeFromL1ToL2(BRIDGED_FPC_GAS, BRIDGED_FPC_GAS, bobsAddress); + }); + + beforeEach(initBalances); + + it('account pays for its own fee', async () => { + await bobsAccountManager + .deploy({ + fee: { + maxFee, + paymentMethod: await NativeFeePaymentMethod.create(await bobsAccountManager.getWallet()), + }, + }) + .wait(); + + await expectMapping( + gasBalances, + [bobsAddress, sequencersAddress], + [bobsInitialGas - actualFee, sequencersInitialGas + actualFee], + ); + }); + }); + + describe('privately through an FPC', () => { + let mintedPrivateBananas: bigint; + beforeEach(async () => { + mintedPrivateBananas = 42n; + + // TODO the following sequence of events ends in a timeout + // 1. pxe.registerRecipient (aka just add the public key so pxe can encrypt notes) + // 2. mint note for mew account + // 3. accountManager.register (add pubkey + start a note processor) + // as a workaround, register (pubkey + note processors) the account first, before minting the note + await bobsAccountManager.register(); + + const secret = Fr.random(); + const secretHash = computeMessageSecretHash(secret); + const mintTx = await bananaCoin.methods.mint_private(mintedPrivateBananas, secretHash).send().wait(); + await addTransparentNoteToPxe(sequencersAddress, mintedPrivateBananas, secretHash, mintTx.txHash); + + // at this point, the new account owns a note + // but the account doesn't have a NoteProcessor registered + // so the note exists on the blockchain as an encrypted blob + // tell the pxe to start a note processor for the account ahead of its deployment + await bananaCoin.methods.redeem_shield(bobsAddress, mintedPrivateBananas, secret).send().wait(); + }); + + beforeEach(initBalances); + + it('account pays for its own fee', async () => { + const rebateSecret = Fr.random(); + const tx = await bobsAccountManager + .deploy({ + fee: { + maxFee, + paymentMethod: new PrivateFeePaymentMethod( + bananaCoin.address, + bananaFPC.address, + await bobsAccountManager.getWallet(), + rebateSecret, + ), + }, + }) + .wait(); + + expect(tx.status).toEqual(TxStatus.MINED); + + // the new account should have paid the full fee to the FPC + await expect(bananaPrivateBalances(bobsAddress)).resolves.toEqual([mintedPrivateBananas - maxFee]); + + // the FPC got paid through "unshield", so it's got a new public balance + await expect(bananaPublicBalances(bananaFPC.address)).resolves.toEqual([fpcsInitialPublicBananas + actualFee]); + + // the FPC should have paid the sequencer + await expect(gasBalances(bananaFPC.address, sequencersAddress)).resolves.toEqual([ + fpcsInitialGas - actualFee, + sequencersInitialGas + actualFee, + ]); + + // the new account should have received a refund + await expect( + // this rejects if note can't be added + addTransparentNoteToPxe(bobsAddress, maxFee - actualFee, computeMessageSecretHash(rebateSecret), tx.txHash), + ).resolves.toBeUndefined(); + + // and it can redeem the refund + await bananaCoin.methods + .redeem_shield(bobsAccountManager.getCompleteAddress().address, maxFee - actualFee, rebateSecret) + .send() + .wait(); + + await expect(bananaPrivateBalances(bobsAccountManager.getCompleteAddress().address)).resolves.toEqual([ + mintedPrivateBananas - actualFee, + ]); + }); + }); + + describe('public through an FPC', () => { + let mintedPublicBananas: bigint; + + beforeEach(async () => { + mintedPublicBananas = 37n; + await bananaCoin.methods.mint_public(bobsAddress, mintedPublicBananas).send().wait(); + }); + + beforeEach(initBalances); + + it('account pays for its own fee', async () => { + const tx = await bobsAccountManager + .deploy({ + skipPublicDeployment: false, + fee: { + maxFee, + paymentMethod: new PublicFeePaymentMethod( + bananaCoin.address, + bananaFPC.address, + await bobsAccountManager.getWallet(), + ), + }, + }) + .wait(); + + expect(tx.status).toEqual(TxStatus.MINED); + + // we should have paid the fee to the FPC + await expect( + bananaPublicBalances(bobsAccountManager.getCompleteAddress().address, bananaFPC.address), + ).resolves.toEqual([mintedPublicBananas - actualFee, fpcsInitialPublicBananas + actualFee]); + + // the FPC should have paid the sequencer + await expect(gasBalances(bananaFPC.address, sequencersAddress)).resolves.toEqual([ + fpcsInitialGas - actualFee, + sequencersInitialGas + actualFee, + ]); + }); + }); + }); + + describe('another account pays the fee', () => { + describe('in the gas token', () => { + beforeEach(async () => { + await gasBridgeTestHarness.bridgeFromL1ToL2(BRIDGED_FPC_GAS, BRIDGED_FPC_GAS, alice.getAddress()); + }); + + beforeEach(initBalances); + + it("alice pays for bob's account", async () => { + // bob generates the private keys for his account on his own + const instance = bobsAccountManager.getInstance(); + + // and gives the public keys to alice + const encPubKey = generatePublicKey(bobsPrivateEncryptionKey); + const signingPubKey = new Schnorr().computePublicKey(bobsPrivateSigningKey); + const completeAddress = CompleteAddress.fromPublicKeyAndInstance(encPubKey, instance); + + // alice registers the keys in the PXE + await ctx.pxe.registerRecipient(completeAddress); + + // and deploys bob's account, paying the fee from her balance + const tx = await SchnorrAccountContract.deployWithPublicKey(encPubKey, alice, signingPubKey.x, signingPubKey.y) + .send({ + contractAddressSalt: instance.salt, + skipClassRegistration: true, + skipPublicDeployment: true, + skipInitialization: false, + universalDeploy: true, + fee: { + maxFee, + paymentMethod: await NativeFeePaymentMethod.create(alice), + }, + }) + .wait(); + + expect(tx.status).toBe(TxStatus.MINED); + + await expectMapping( + gasBalances, + [alice.getAddress(), bobsAddress, sequencersAddress], + [alicesInitialGas - actualFee, bobsInitialGas, sequencersInitialGas + actualFee], + ); + + // bob can now use his wallet + const bobsWallet = await bobsAccountManager.getWallet(); + await expect(gas.withWallet(bobsWallet).methods.balance_of_public(alice.getAddress()).simulate()).resolves.toBe( + alicesInitialGas - actualFee, + ); + }); + }); + }); + + async function addTransparentNoteToPxe(owner: AztecAddress, amount: bigint, secretHash: Fr, txHash: TxHash) { + const storageSlot = new Fr(5); // The storage slot of `pending_shields` is 5. + const noteTypeId = new Fr(84114971101151129711410111011678111116101n); // TransparentNote + + const note = new Note([new Fr(amount), secretHash]); + // this note isn't encrypted but we need to provide a registered public key + const extendedNote = new ExtendedNote(note, owner, bananaCoin.address, storageSlot, noteTypeId, txHash); + await ctx.pxe.addNote(extendedNote); + } +}); diff --git a/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts new file mode 100644 index 00000000000..812350b4015 --- /dev/null +++ b/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts @@ -0,0 +1,159 @@ +import { getSchnorrAccount } from '@aztec/accounts/schnorr'; +import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node'; +import { + type AztecAddress, + CompleteAddress, + type DebugLogger, + Fr, + Grumpkin, + GrumpkinScalar, + type SentTx, + TxStatus, +} from '@aztec/aztec.js'; +import { BootstrapNode, type P2PConfig, createLibP2PPeerId } from '@aztec/p2p'; +import { ConstantKeyPair, type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; + +import { mnemonicToAccount } from 'viem/accounts'; + +import { MNEMONIC } from './fixtures/fixtures.js'; +import { setup } from './fixtures/utils.js'; + +// Don't set this to a higher value than 9 because each node will use a different L1 publisher account and anvil seeds +const NUM_NODES = 4; +const NUM_TXS_PER_BLOCK = 4; +const NUM_TXS_PER_NODE = 2; +const BOOT_NODE_TCP_PORT = 40400; + +interface NodeContext { + node: AztecNodeService; + pxeService: PXEService; + txs: SentTx[]; + account: AztecAddress; +} + +describe('e2e_p2p_network', () => { + let config: AztecNodeConfig; + let logger: DebugLogger; + let teardown: () => Promise; + + beforeEach(async () => { + ({ teardown, config, logger } = await setup(1)); + }, 100_000); + + afterEach(() => teardown()); + + it('should rollup txs from all peers', async () => { + // create the bootstrap node for the network + const bootstrapNode = await createBootstrapNode(); + const bootstrapNodeAddress = `/ip4/127.0.0.1/tcp/${BOOT_NODE_TCP_PORT}/p2p/${bootstrapNode + .getPeerId()! + .toString()}`; + // create our network of nodes and submit txs into each of them + // the number of txs per node and the number of txs per rollup + // should be set so that the only way for rollups to be built + // is if the txs are successfully gossiped around the nodes. + const contexts: NodeContext[] = []; + for (let i = 0; i < NUM_NODES; i++) { + const node = await createNode(i + 1 + BOOT_NODE_TCP_PORT, bootstrapNodeAddress, i); + const context = await createPXEServiceAndSubmitTransactions(node, NUM_TXS_PER_NODE); + contexts.push(context); + } + + // now ensure that all txs were successfully mined + await Promise.all(contexts.flatMap(context => context.txs.map(tx => tx.wait()))); + + // shutdown all nodes. + for (const context of contexts) { + await context.node.stop(); + await context.pxeService.stop(); + } + await bootstrapNode.stop(); + }, 120_000); + + const createBootstrapNode = async () => { + const peerId = await createLibP2PPeerId(); + const bootstrapNode = new BootstrapNode(logger); + const config: P2PConfig = { + p2pEnabled: true, + tcpListenPort: BOOT_NODE_TCP_PORT, + tcpListenIp: '0.0.0.0', + announceHostname: '/tcp/127.0.0.1', + announcePort: BOOT_NODE_TCP_PORT, + peerIdPrivateKey: Buffer.from(peerId.privateKey!).toString('hex'), + clientKADRouting: false, + minPeerCount: 10, + maxPeerCount: 100, + + // TODO: the following config options are not applicable to bootstrap nodes + p2pBlockCheckIntervalMS: 1000, + p2pL2QueueSize: 1, + transactionProtocol: '', + bootstrapNodes: [''], + }; + await bootstrapNode.start(config); + + return bootstrapNode; + }; + + // creates a P2P enabled instance of Aztec Node Service + const createNode = async (tcpListenPort: number, bootstrapNode: string, publisherAddressIndex: number) => { + // We use different L1 publisher accounts in order to avoid duplicate tx nonces. We start from + // publisherAddressIndex + 1 because index 0 was already used during test environment setup. + const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: publisherAddressIndex + 1 }); + const publisherPrivKey = Buffer.from(hdAccount.getHdKey().privateKey!); + config.publisherPrivateKey = `0x${publisherPrivKey!.toString('hex')}`; + + const newConfig: AztecNodeConfig = { + ...config, + tcpListenPort, + tcpListenIp: '0.0.0.0', + enableNat: false, + bootstrapNodes: [bootstrapNode], + minTxsPerBlock: NUM_TXS_PER_BLOCK, + maxTxsPerBlock: NUM_TXS_PER_BLOCK, + p2pEnabled: true, + clientKADRouting: false, + }; + return await AztecNodeService.createAndSync(newConfig); + }; + + // submits a set of transactions to the provided Private eXecution Environment (PXE) + const submitTxsTo = async (pxe: PXEService, account: AztecAddress, numTxs: number) => { + const txs: SentTx[] = []; + for (let i = 0; i < numTxs; i++) { + const tx = getSchnorrAccount(pxe, GrumpkinScalar.random(), GrumpkinScalar.random(), Fr.random()).deploy(); + logger.info(`Tx sent with hash ${await tx.getTxHash()}`); + const receipt = await tx.getReceipt(); + expect(receipt).toEqual( + expect.objectContaining({ + status: TxStatus.PENDING, + error: '', + }), + ); + logger.info(`Receipt received for ${await tx.getTxHash()}`); + txs.push(tx); + } + return txs; + }; + + // creates an instance of the PXE and submit a given number of transactions to it. + const createPXEServiceAndSubmitTransactions = async ( + node: AztecNodeService, + numTxs: number, + ): Promise => { + const rpcConfig = getRpcConfig(); + const pxeService = await createPXEService(node, rpcConfig, true); + + const keyPair = ConstantKeyPair.random(new Grumpkin()); + const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(keyPair.getPrivateKey(), Fr.random()); + await pxeService.registerAccount(keyPair.getPrivateKey(), completeAddress.partialAddress); + + const txs = await submitTxsTo(pxeService, completeAddress.address, numTxs); + return { + txs, + account: completeAddress.address, + pxeService, + node, + }; + }; +}); From 8a797332225ba71252c66f0a3ec950ec33ad051d Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 21:26:35 +0000 Subject: [PATCH 10/11] ci tests --- .circleci/config.yml | 274 +-------------------------------------- .github/workflows/ci.yml | 11 +- 2 files changed, 5 insertions(+), 280 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 29418495446..a677fed2db5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -181,108 +181,6 @@ jobs: command: | barretenberg/cpp/scripts/ci/upload_doxygen_to_s3.sh - barretenberg-stdlib-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 stdlib-tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - - barretenberg-dsl-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 dsl_tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - - barretenberg-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/bb-tests.sh - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - - barretenberg-avm-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/avm-tests.sh - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - - barretenberg-bench: - machine: - # NOTE: we usually use alpine build image when making spot images, but - # we are not able to upload to S3 with it - image: default - resource_class: medium - steps: - - *checkout - - *setup_env - - run: - name: "Benchmark" - command: cond_spot_run_build barretenberg-bench 32 - aztec_manifest_key: barretenberg-bench - - run: - name: "Upload" - command: | - barretenberg/cpp/scripts/ci/upload_benchmarks_to_s3.sh - - barretenberg-proof-system-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 stdlib_circuit_builders_tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - - barretenberg-stdlib-plonk-recursion-ultra-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_plonk_recursion_tests --gtest_filter=-*turbo* - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - - barretenberg-stdlib-honk-recursion-ultra-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_honk_recursion_tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - bb-js: machine: image: default @@ -629,136 +527,10 @@ jobs: command: build end-to-end aztec_manifest_key: end-to-end - e2e-tests: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_container end-to-end 64 ./src/e2e* - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - e2e-sandbox-example: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=composed/e2e_sandbox_example.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - uniswap-trade-on-l1-from-l2: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=composed/uniswap_trade_on_l1_from_l2.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - integration-l1-publisher: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=composed/integration_l1_publisher.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - e2e-persistence: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose-no-sandbox.yml TEST=composed/e2e_persistence.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - e2e-browser: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=composed/e2e_aztec_js_browser.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - pxe: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=composed/pxe.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - cli-docs-sandbox: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=composed/cli_docs_sandbox.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - e2e-docs-examples: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=composed/docs_examples.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - guides-writing-an-account-contract: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=guides/writing_an_account_contract.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - guides-dapp-testing: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=guides/dapp_testing.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - guides-sample-dapp: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=sample-dapp - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test - - guides-up-quick-start: - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose.yml TEST=guides/up_quick_start.test.ts - aztec_manifest_key: end-to-end - <<: *defaults_e2e_test + # For old e2e tests see yarn-project/end-to-end/Earthfile + # Semantics are similar to Dockerfile + # NOTE: Unlike other e2e, these will be re-enabled here as currently the logs functionality is not in the new earthfile setup # bench-publish-rollup: # steps: # - *checkout @@ -1024,17 +796,6 @@ workflows: - barretenberg-x86_64-linux-clang-fuzzing: *defaults - barretenberg-wasm-linux-clang: *defaults - barretenberg-x86_64-linux-clang-sol: *defaults - - barretenberg-bench: - requires: - - barretenberg-x86_64-linux-clang - <<: *defaults - - barretenberg-proof-system-tests: *bb_test - - barretenberg-dsl-tests: *bb_test - - barretenberg-tests: *bb_test - - barretenberg-avm-tests: *bb_test - - barretenberg-stdlib-tests: *bb_test - - barretenberg-stdlib-plonk-recursion-ultra-tests: *bb_test - - barretenberg-stdlib-honk-recursion-ultra-tests: *bb_test - barretenberg-acir-tests-bb: *bb_acir_tests - barretenberg-acir-tests-bb-sol: requires: @@ -1113,19 +874,6 @@ workflows: - aztec-package - cli <<: *defaults - - e2e-tests: *e2e_test - - cli-docs-sandbox: *e2e_test - - e2e-docs-examples: *e2e_test - - e2e-browser: *e2e_test - - e2e-persistence: *e2e_test - - e2e-sandbox-example: *e2e_test - - integration-l1-publisher: *e2e_test - - pxe: *e2e_test - - uniswap-trade-on-l1-from-l2: *e2e_test - - guides-writing-an-account-contract: *e2e_test - - guides-dapp-testing: *e2e_test - - guides-sample-dapp: *e2e_test - - guides-up-quick-start: *e2e_test # Everything that must complete before deployment. - end: @@ -1136,8 +884,6 @@ workflows: - barretenberg-x86_64-linux-clang-fuzzing - barretenberg-wasm-linux-clang - barretenberg-x86_64-linux-clang-sol - - barretenberg-bench - - barretenberg-proof-system-tests - barretenberg-dsl-tests - barretenberg-tests - barretenberg-avm-tests @@ -1149,24 +895,12 @@ workflows: - barretenberg-docs - build-docs - mainnet-fork - - e2e-tests - - cli-docs-sandbox - - e2e-docs-examples - - e2e-browser - - e2e-persistence - - e2e-sandbox-example - - integration-l1-publisher - - pxe - - uniswap-trade-on-l1-from-l2 - - guides-writing-an-account-contract - - guides-dapp-testing - - guides-sample-dapp - - guides-up-quick-start - boxes-vanilla - boxes-react - noir-packages-tests - yarn-project-test - prover-client-test + - e2e-join <<: *defaults # Benchmark jobs. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ebe6980349d..68c34bf6a12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,6 @@ jobs: - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_token: "${{ secrets.AZTEC_GITHUB_TOKEN }}" - # must be globally unique for build x runner concurrency_key: build-${{ github.actor }}-x86 # prepare images locally, tagged by commit hash - name: "Build E2E Image" @@ -66,7 +64,6 @@ jobs: - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_token: "${{ secrets.AZTEC_GITHUB_TOKEN }}" # must be globally unique for build x runner concurrency_key: e2e-${{ github.actor }}-x86-${{ matrix.test }} - name: Test @@ -77,7 +74,7 @@ jobs: # - name: Upload logs # run: BRANCH=${{ github.ref_name }} PULL_REQUEST=${{ github.event.number }} scripts/ci/upload_logs_to_s3 ./yarn-project/end-to-end/log - # barretenberg (prover) native tests + # barretenberg (prover) native and AVM (public VM) tests # only ran on x86 for resource reasons (memory intensive) bb-native-tests: needs: setup @@ -90,7 +87,6 @@ jobs: - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_token: "${{ secrets.AZTEC_GITHUB_TOKEN }}" # must be globally unique for build x runner concurrency_key: bb-native-tests-${{ github.actor }}-x86 - name: "Native Prover Tests" @@ -108,8 +104,6 @@ jobs: - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_token: "${{ secrets.AZTEC_GITHUB_TOKEN }}" - # must be globally unique for build x runner concurrency_key: bb-bench-binaries-${{ github.actor }}-x86 - name: Build and Push Binaries if: ${{ github.event.inputs.just_start_spot != 'true' }} @@ -138,9 +132,6 @@ jobs: - uses: ./.github/ci-setup-action with: dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - concurrency_token: "${{ secrets.AZTEC_GITHUB_TOKEN }}" - # must be globally unique for build x runner - # technically not needed as we only make one GA runner, but a backup concurrency_key: bb-bench-${{ github.actor }}-bench-x86 # Use bench_mode=cache to read the pushed build above - name: Client IVC Bench From e52d5f190006251c97d5798bcd86d60143fb36be Mon Sep 17 00:00:00 2001 From: ludamad Date: Mon, 15 Apr 2024 21:30:05 +0000 Subject: [PATCH 11/11] fix ci --- .circleci/config.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a677fed2db5..4492449fa57 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -884,12 +884,6 @@ workflows: - barretenberg-x86_64-linux-clang-fuzzing - barretenberg-wasm-linux-clang - barretenberg-x86_64-linux-clang-sol - - barretenberg-dsl-tests - - barretenberg-tests - - barretenberg-avm-tests - - barretenberg-stdlib-tests - - barretenberg-stdlib-plonk-recursion-ultra-tests - - barretenberg-stdlib-honk-recursion-ultra-tests - barretenberg-acir-tests-bb - barretenberg-acir-tests-bb-sol - barretenberg-docs