Skip to content

Commit d5ae38c

Browse files
authored
fix: wait for checkpoint during sandbox setup (#23834)
## Problem CI on `merge-train/fairies` failed on the boxes `react chromium` test ([log](http://ci.aztec-labs.com/1780510430908759), [failing test](http://ci.aztec-labs.com/243e7294cb8ba269)) with a timeout (code 124). The actual error was during `aztec start` / `createLocalNetwork`: ``` Error: Transaction 0x0826… was dropped. Reason: Tx dropped by P2P node at NodeEmbeddedWallet.sendTx at DeployAccountMethod.send at deployFundedSchnorrAccounts at createLocalNetwork at aztecStart ``` The local network never came up, so the browser test timed out. ## Root cause PR #23819 ("embedded wallet defaults to proposed") fixed the embedded wallet so its default wait status is *actually* `PROPOSED` — previously the default was a no-op that fell through to `waitForTx`'s `CHECKPOINTED` default. `PROPOSED` returns as soon as a tx lands in a proposed L2 block. In the serial sandbox setup that races against block pruning: a proposed-but-not-checkpointed block can be pruned by end of build slot (see #23606), and a tx in it is then neither in the archiver nor the pool, so `getTxReceipt` returns `DroppedTxReceipt("Tx dropped by P2P node")`. With the old broken default this path waited for `CHECKPOINTED` and was reliable. The real source of flakiness is the local network setup, not the boxes. ## Fix Thread an explicit `{ waitForStatus: TxStatus.CHECKPOINTED }` wait through the sandbox-setup sends: - `createLocalNetwork`: `deployFundedSchnorrAccounts`, `publishStandardAuthRegistry`, `setupBananaFPC` - `setup-l2-contracts` CLI wait options The intended product default of `PROPOSED` for normal wallet usage is unchanged; only the CI/sandbox bring-up that needs durable inclusion before the next serial tx is pinned to `CHECKPOINTED`. e2e fixtures use `TestWallet` (BaseWallet's `CHECKPOINTED` default) and are unaffected. Also reverts the per-box `CHECKPOINTED` waits that #23819 added to the react/vite/vanilla boxes: they didn't fix the flakiness (the local-network setup did), so the box sends go back to using the embedded wallet `PROPOSED` default. ## Verification TypeScript-only change in `yarn-project` plus box reverts; the box files now match their pre-#23819 state exactly. A full `./bootstrap.sh ci` could not be run in this container (clang 18 vs required 20, zig missing, no remote build cache; the suite is multi-hour). Confirmed by the merge-train CI re-run of the boxes tests.
1 parent fa66e7c commit d5ae38c

11 files changed

Lines changed: 39 additions & 44 deletions

File tree

boxes/boxes/react/src/hooks/useContract.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { deployerEnv } from '../config';
33

44
import { Contract } from '@aztec/aztec.js/contracts';
55
import { Fr } from '@aztec/aztec.js/fields';
6-
import { TxStatus } from '@aztec/aztec.js/tx';
76
import { toast } from 'react-toastify';
87

98
export function useContract() {
@@ -21,8 +20,6 @@ export function useContract() {
2120

2221
const deploymentPromise = BoxReactContract.deploy(wallet, Fr.random(), defaultAccountAddress).send({
2322
from: defaultAccountAddress,
24-
// PROPOSED (the wallet default) is flaky in boxes CI, so wait for the checkpoint.
25-
wait: { waitForStatus: TxStatus.CHECKPOINTED },
2623
});
2724

2825
const { contract } = await toast.promise(deploymentPromise, {

boxes/boxes/react/src/hooks/useNumber.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useState } from 'react';
22
import { Contract } from '@aztec/aztec.js/contracts';
3-
import { TxStatus } from '@aztec/aztec.js/tx';
43
import { toast } from 'react-toastify';
54
import { deployerEnv } from '../config';
65

@@ -29,10 +28,7 @@ export function useNumber({ contract }: { contract: Contract }) {
2928
const value = BigInt(el.value);
3029
const defaultAccountAddress = deployerEnv.getDefaultAccountAddress();
3130
await toast.promise(
32-
// PROPOSED (the wallet default) is flaky in boxes CI, so wait for the checkpoint.
33-
contract!.methods
34-
.setNumber(value, defaultAccountAddress)
35-
.send({ from: defaultAccountAddress, wait: { waitForStatus: TxStatus.CHECKPOINTED } }),
31+
contract!.methods.setNumber(value, defaultAccountAddress).send({ from: defaultAccountAddress }),
3632
{
3733
pending: 'Setting number...',
3834
success: `Number set to: ${value}`,

boxes/boxes/vanilla/app/embedded-wallet.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee';
77
import { Fr } from '@aztec/aztec.js/fields';
88
import { createLogger } from '@aztec/aztec.js/log';
9-
import { TxStatus } from '@aztec/aztec.js/tx';
109
import { DeployAccountOptions } from '@aztec/aztec.js/wallet';
1110
import type { AztecNode } from '@aztec/aztec.js/node';
1211
import {
@@ -144,8 +143,7 @@ export class EmbeddedWallet extends EmbeddedWalletBase {
144143
},
145144
skipClassPublication: true,
146145
skipInstancePublication: true,
147-
// PROPOSED (the wallet default) is flaky in boxes CI, so wait for the checkpoint.
148-
wait: { timeout: 120, waitForStatus: TxStatus.CHECKPOINTED },
146+
wait: { timeout: 120 },
149147
};
150148

151149
const { receipt } = await deployMethod.send(deployOpts);

boxes/boxes/vanilla/app/main.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
getContractInstanceFromInstantiationParams,
66
} from '@aztec/aztec.js/contracts';
77
import { Fr } from '@aztec/aztec.js/fields';
8-
import { TxStatus } from '@aztec/aztec.js/tx';
98
import type { Wallet } from '@aztec/aztec.js/wallet';
109
import { EmbeddedWallet } from './embedded-wallet';
1110
import { PrivateVotingContract } from '../artifacts/PrivateVoting';
@@ -163,11 +162,7 @@ voteButton.addEventListener('click', async (e) => {
163162
// Send tx
164163
await votingContract.methods
165164
.cast_vote({ id: electionId }, candidate)
166-
// PROPOSED (the wallet default) is flaky in boxes CI, so wait for the checkpoint.
167-
.send({
168-
from: connectedAccount,
169-
wait: { waitForStatus: TxStatus.CHECKPOINTED },
170-
});
165+
.send({ from: connectedAccount });
171166

172167
// Update tally
173168
displayStatusMessage('Updating vote tally...');
@@ -203,10 +198,7 @@ async function updateVoteTally(wallet: Wallet, from: AztecAddress) {
203198
)
204199
);
205200

206-
const { result: batchResult } = await new BatchCall(
207-
wallet,
208-
payloads
209-
).simulate({ from });
201+
const { result: batchResult } = await new BatchCall(wallet, payloads).simulate({ from });
210202

211203
batchResult.forEach(({ result: value }, i) => {
212204
results[i + 1] = value;

boxes/boxes/vanilla/scripts/deploy.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee';
99
import { Fr } from '@aztec/aztec.js/fields';
1010
import { PublicKeys } from '@aztec/aztec.js/keys';
11-
import { TxStatus } from '@aztec/aztec.js/tx';
1211
import { createAztecNodeClient } from '@aztec/aztec.js/node';
1312
import type { DeployAccountOptions, Wallet } from '@aztec/aztec.js/wallet';
1413
import { type AztecNode } from '@aztec/aztec.js/node';
@@ -61,8 +60,7 @@ async function createAccount(wallet: EmbeddedWallet) {
6160
},
6261
skipClassPublication: true,
6362
skipInstancePublication: true,
64-
// PROPOSED (the wallet default) is flaky in boxes CI, so wait for the checkpoint.
65-
wait: { timeout: 120, waitForStatus: TxStatus.CHECKPOINTED },
63+
wait: { timeout: 120 },
6664
};
6765
await deployMethod.send(deployOpts);
6866

@@ -83,8 +81,7 @@ async function deployContract(wallet: Wallet, deployer: AztecAddress) {
8381
sponsoredPFCContract.address
8482
),
8583
},
86-
// PROPOSED (the wallet default) is flaky in CI, so wait for the checkpoint.
87-
wait: { timeout: 120, waitForStatus: TxStatus.CHECKPOINTED },
84+
wait: { timeout: 120 },
8885
});
8986

9087
const electionId = new Fr(42);
@@ -96,8 +93,7 @@ async function deployContract(wallet: Wallet, deployer: AztecAddress) {
9693
sponsoredPFCContract.address
9794
),
9895
},
99-
// PROPOSED (the wallet default) is flaky in CI, so wait for the checkpoint.
100-
wait: { timeout: 120, waitForStatus: TxStatus.CHECKPOINTED },
96+
wait: { timeout: 120 },
10197
});
10298

10399
return {

boxes/boxes/vite/src/hooks/useContract.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { deployerEnv } from '../config';
33

44
import { Contract } from '@aztec/aztec.js/contracts';
55
import { Fr } from '@aztec/aztec.js/fields';
6-
import { TxStatus } from '@aztec/aztec.js/tx';
76
import { toast } from 'react-toastify';
87

98
export function useContract() {
@@ -21,8 +20,6 @@ export function useContract() {
2120

2221
const deploymentPromise = BoxReactContract.deploy(wallet, Fr.random(), defaultAccountAddress).send({
2322
from: defaultAccountAddress,
24-
// PROPOSED (the wallet default) is flaky in boxes CI, so wait for the checkpoint.
25-
wait: { waitForStatus: TxStatus.CHECKPOINTED },
2623
});
2724

2825
const { contract } = await toast.promise(deploymentPromise, {

boxes/boxes/vite/src/hooks/useNumber.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useState } from 'react';
22
import { Contract } from '@aztec/aztec.js/contracts';
3-
import { TxStatus } from '@aztec/aztec.js/tx';
43
import { toast } from 'react-toastify';
54
import { deployerEnv } from '../config';
65

@@ -29,10 +28,7 @@ export function useNumber({ contract }: { contract: Contract }) {
2928
const value = BigInt(el.value);
3029
const defaultAccountAddress = deployerEnv.getDefaultAccountAddress();
3130
await toast.promise(
32-
// PROPOSED (the wallet default) is flaky in boxes CI, so wait for the checkpoint.
33-
contract!.methods
34-
.setNumber(value, defaultAccountAddress)
35-
.send({ from: defaultAccountAddress, wait: { waitForStatus: TxStatus.CHECKPOINTED } }),
31+
contract!.methods.setNumber(value, defaultAccountAddress).send({ from: defaultAccountAddress }),
3632
{
3733
pending: 'Setting number...',
3834
success: `Number set to: ${value}`,
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
import type { WaitOpts } from '@aztec/aztec.js/contracts';
12
import { publishContractClass, publishInstance } from '@aztec/aztec.js/deployment';
23
import type { Wallet } from '@aztec/aztec.js/wallet';
34
import { AuthRegistryArtifact, getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry';
45
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
56

6-
export async function publishStandardAuthRegistry(wallet: Wallet, from: AztecAddress): Promise<void> {
7+
export async function publishStandardAuthRegistry(
8+
wallet: Wallet,
9+
from: AztecAddress,
10+
waitOpts?: WaitOpts,
11+
): Promise<void> {
712
const { instance, contractClass } = await getStandardAuthRegistry();
813
if (!(await wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered) {
9-
await (await publishContractClass(wallet, AuthRegistryArtifact)).send({ from });
14+
await (await publishContractClass(wallet, AuthRegistryArtifact)).send({ from, wait: waitOpts });
1015
}
1116
if (!(await wallet.getContractMetadata(instance.address)).isContractPublished) {
12-
await publishInstance(wallet, instance).send({ from });
17+
await publishInstance(wallet, instance).send({ from, wait: waitOpts });
1318
}
1419
}

yarn-project/aztec/src/local-network/banana_fpc.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type InitialAccountData, getInitialTestAccountsData } from '@aztec/accounts/testing';
2+
import type { WaitOpts } from '@aztec/aztec.js/contracts';
23
import type { Wallet } from '@aztec/aztec.js/wallet';
34
import { Fr } from '@aztec/foundation/curves/bn254';
45
import type { LogFn } from '@aztec/foundation/log';
@@ -45,16 +46,22 @@ export async function getBananaFPCAddress(initialAccounts: InitialAccountData[])
4546
return (await getBananaFPCInstance(initialAccounts)).address;
4647
}
4748

48-
export async function setupBananaFPC(initialAccounts: InitialAccountData[], wallet: Wallet, log: LogFn) {
49+
export async function setupBananaFPC(
50+
initialAccounts: InitialAccountData[],
51+
wallet: Wallet,
52+
log: LogFn,
53+
waitOpts?: WaitOpts,
54+
) {
4955
const bananaCoinAddress = await getBananaCoinAddress(initialAccounts);
5056
const admin = getBananaAdmin(initialAccounts);
5157
const [{ contract: bananaCoin }, { contract: fpc }] = await Promise.all([
5258
TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal, {
5359
salt: BANANA_COIN_SALT,
5460
universalDeploy: true,
55-
}).send({ from: admin }),
61+
}).send({ from: admin, wait: waitOpts }),
5662
FPCContract.deploy(wallet, bananaCoinAddress, admin, { salt: BANANA_FPC_SALT, universalDeploy: true }).send({
5763
from: admin,
64+
wait: waitOpts,
5865
}),
5966
]);
6067

yarn-project/aztec/src/local-network/local-network.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { protocolContractsHash } from '@aztec/protocol-contracts';
2222
import { SequencerState } from '@aztec/sequencer-client';
2323
import { AztecAddress } from '@aztec/stdlib/aztec-address';
2424
import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
25+
import { TxStatus } from '@aztec/stdlib/tx';
2526
import type { GenesisData } from '@aztec/stdlib/world-state';
2627
import {
2728
type TelemetryClient,
@@ -47,6 +48,12 @@ import { getSponsoredFPCAddress } from './sponsored_fpc.js';
4748

4849
const logger = createLogger('local-network');
4950

51+
// The embedded wallet defaults to waiting for PROPOSED, which returns as soon as a tx lands in a
52+
// proposed L2 block. That is flaky for the serial sandbox setup below: a proposed block can be
53+
// pruned before its checkpoint is published, dropping a tx we already moved on from ("Tx dropped by
54+
// P2P node"). Wait for the checkpoint so each setup tx is durably included before the next is sent.
55+
const setupWaitOpts = { waitForStatus: TxStatus.CHECKPOINTED };
56+
5057
const localAnvil = foundry;
5158

5259
/**
@@ -243,14 +250,14 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
243250
});
244251

245252
userLog('Setting up funded test accounts...');
246-
const accountManagers = await deployFundedSchnorrAccounts(wallet, initialAccounts);
253+
const accountManagers = await deployFundedSchnorrAccounts(wallet, initialAccounts, setupWaitOpts);
247254
const accLogs = await createAccountLogs(accountManagers, wallet);
248255
userLog(accLogs.join(''));
249256

250257
userLog('Publishing standard AuthRegistry contract...');
251-
await publishStandardAuthRegistry(wallet, initialAccounts[0].address);
258+
await publishStandardAuthRegistry(wallet, initialAccounts[0].address, setupWaitOpts);
252259

253-
await setupBananaFPC(initialAccounts, wallet, userLog);
260+
await setupBananaFPC(initialAccounts, wallet, userLog, setupWaitOpts);
254261

255262
userLog(`SponsoredFPC: ${await getSponsoredFPCAddress()}`);
256263

0 commit comments

Comments
 (0)