diff --git a/yarn-project/aztec.js/src/wallet/account_wallet.ts b/yarn-project/aztec.js/src/wallet/account_wallet.ts index 1a891160850..781b8ab454e 100644 --- a/yarn-project/aztec.js/src/wallet/account_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/account_wallet.ts @@ -34,6 +34,10 @@ export class AccountWallet extends BaseWallet { return this.account.getVersion(); } + override isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise { + return this.pxe.isL1ToL2MessageSynced(l1ToL2Message); + } + /** * Computes an authentication witness from either a message hash or an intent. * diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index aaf2bea1954..98e0d1451ae 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -44,6 +44,8 @@ import { type IntentAction, type IntentInnerHash } from '../utils/authwit.js'; export abstract class BaseWallet implements Wallet { constructor(protected readonly pxe: PXE, private scopes?: AztecAddress[]) {} + abstract isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise; + abstract getCompleteAddress(): CompleteAddress; abstract getChainId(): Fr; diff --git a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts index 0231d79b01a..2912d65e1d1 100644 --- a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts @@ -42,4 +42,8 @@ export class SignerlessWallet extends BaseWallet { createAuthWit(_intent: Fr | Buffer | IntentInnerHash | IntentAction): Promise { throw new Error('SignerlessWallet: Method createAuthWit not implemented.'); } + + override isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise { + return this.pxe.isL1ToL2MessageSynced(l1ToL2Message); + } } diff --git a/yarn-project/circuit-types/src/interfaces/pxe.test.ts b/yarn-project/circuit-types/src/interfaces/pxe.test.ts index 294ba519988..65976b07ac7 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.test.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.test.ts @@ -87,6 +87,10 @@ describe('PXESchema', () => { expect([...tested].sort()).toEqual(all.sort()); }); + it('isL1ToL2MessageSynced', async () => { + await context.client.isL1ToL2MessageSynced(Fr.random()); + }); + it('addAuthWitness', async () => { await context.client.addAuthWitness(AuthWitness.random()); }); @@ -326,6 +330,11 @@ class MockPXE implements PXE { private artifact: ContractArtifact, private instance: ContractInstanceWithAddress, ) {} + + isL1ToL2MessageSynced(_l1ToL2Message: Fr): Promise { + return Promise.resolve(false); + } + addAuthWitness(authWitness: AuthWitness): Promise { expect(authWitness).toBeInstanceOf(AuthWitness); return Promise.resolve(); diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 0ff0f322ecf..2ed9f7bea75 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -53,6 +53,13 @@ import { type SyncStatus, SyncStatusSchema } from './sync-status.js'; * is exposed to dapps for interacting with the network on behalf of the user. */ export interface PXE { + /** + * Returns whether an L1 to L2 message is synced by archiver and if it's ready to be included in a block. + * @param l1ToL2Message - The L1 to L2 message to check. + * @returns Whether the message is synced and ready to be included in a block. + */ + isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise; + /** * Insert an auth witness for a given message hash. Auth witnesses are used to authorize actions on * behalf of a user. For instance, a token transfer initiated by a different address may request @@ -470,6 +477,7 @@ const PXEInfoSchema = z.object({ }) satisfies ZodFor; export const PXESchema: ApiSchemaFor = { + isL1ToL2MessageSynced: z.function().args(schemas.Fr).returns(z.boolean()), addAuthWitness: z.function().args(AuthWitness.schema).returns(z.void()), getAuthWitness: z .function() diff --git a/yarn-project/cli/src/cmds/devnet/bootstrap_network.ts b/yarn-project/cli/src/cmds/devnet/bootstrap_network.ts index e91e2948644..de452290aad 100644 --- a/yarn-project/cli/src/cmds/devnet/bootstrap_network.ts +++ b/yarn-project/cli/src/cmds/devnet/bootstrap_network.ts @@ -1,5 +1,5 @@ import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { BatchCall, type PXE, type Wallet, createCompatibleClient } from '@aztec/aztec.js'; +import { BatchCall, type PXE, type Wallet, createCompatibleClient, retryUntil } from '@aztec/aztec.js'; import { L1FeeJuicePortalManager } from '@aztec/aztec.js'; import { type AztecAddress, type EthAddress, FEE_FUNDING_FOR_TESTER_ACCOUNT, Fq, Fr } from '@aztec/circuits.js'; import { @@ -34,7 +34,7 @@ export async function bootstrapNetwork( // setup a one-off account contract const account = getSchnorrAccount(pxe, Fr.random(), Fq.random(), Fr.random()); - const wallet = await account.deploy().getWallet({ proven: true, provenTimeout: 600 }); + const wallet = await account.deploy().getWallet(); const l1Clients = createL1Clients( l1Url, @@ -142,17 +142,17 @@ async function deployToken( const { TokenContract, TokenBridgeContract } = await import('@aztec/noir-contracts.js'); const devCoin = await TokenContract.deploy(wallet, wallet.getAddress(), 'DevCoin', 'DEV', 18) .send({ universalDeploy: true }) - .deployed({ proven: true, provenTimeout: 600 }); + .deployed(); const bridge = await TokenBridgeContract.deploy(wallet, devCoin.address, l1Portal) .send({ universalDeploy: true }) - .deployed({ proven: true, provenTimeout: 600 }); + .deployed(); await new BatchCall(wallet, [ devCoin.methods.set_minter(bridge.address, true).request(), devCoin.methods.set_admin(bridge.address).request(), ]) .send() - .wait({ proven: true, provenTimeout: 600 }); + .wait(); return { token: { @@ -202,9 +202,7 @@ async function deployFPC( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - Importing noir-contracts.js even in devDeps results in a circular dependency error. Need to ignore because this line doesn't cause an error in a dev environment const { FPCContract } = await import('@aztec/noir-contracts.js'); - const fpc = await FPCContract.deploy(wallet, tokenAddress, feeRecipient) - .send({ universalDeploy: true }) - .deployed({ proven: true, provenTimeout: 600 }); + const fpc = await FPCContract.deploy(wallet, tokenAddress, feeRecipient).send({ universalDeploy: true }).deployed(); const info: ContractDeploymentInfo = { address: fpc.address, initHash: fpc.instance.initializationHash, @@ -219,7 +217,7 @@ async function deployCounter(wallet: Wallet): Promise { const { CounterContract } = await import('@aztec/noir-contracts.js'); const counter = await CounterContract.deploy(wallet, 1, wallet.getAddress(), wallet.getAddress()) .send({ universalDeploy: true }) - .deployed({ proven: true, provenTimeout: 600 }); + .deployed(); const info: ContractDeploymentInfo = { address: counter.address, initHash: counter.instance.initializationHash, @@ -253,27 +251,23 @@ async function fundFPC( ); const amount = FEE_FUNDING_FOR_TESTER_ACCOUNT; - const { claimAmount, claimSecret, messageLeafIndex } = await feeJuicePortal.bridgeTokensPublic( + const { claimAmount, claimSecret, messageLeafIndex, messageHash } = await feeJuicePortal.bridgeTokensPublic( fpcAddress, amount, true, ); + await retryUntil(async () => await wallet.isL1ToL2MessageSynced(Fr.fromString(messageHash)), 'message sync', 600, 1); + const counter = await CounterContract.at(counterAddress, wallet); // TODO (alexg) remove this once sequencer builds blocks continuously // advance the chain - await counter.methods - .increment(wallet.getAddress(), wallet.getAddress()) - .send() - .wait({ proven: true, provenTimeout: 600 }); - await counter.methods - .increment(wallet.getAddress(), wallet.getAddress()) - .send() - .wait({ proven: true, provenTimeout: 600 }); + await counter.methods.increment(wallet.getAddress(), wallet.getAddress()).send().wait(); + await counter.methods.increment(wallet.getAddress(), wallet.getAddress()).send().wait(); await feeJuiceContract.methods .claim(fpcAddress, claimAmount, claimSecret, messageLeafIndex) .send() - .wait({ proven: true, provenTimeout: 600 }); + .wait({ proven: true }); } diff --git a/yarn-project/ethereum/src/utils.ts b/yarn-project/ethereum/src/utils.ts index 9b8f7837e98..2e66f6119fe 100644 --- a/yarn-project/ethereum/src/utils.ts +++ b/yarn-project/ethereum/src/utils.ts @@ -49,7 +49,7 @@ function tryExtractEvent< logger?: DebugLogger, ): TEventType | undefined { for (const log of logs) { - if (log.address === address) { + if (log.address.toLowerCase() === address.toLowerCase()) { try { const decodedEvent = decodeEventLog({ abi, ...log }); if (decodedEvent.eventName === eventName) { diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 201d69ba2b0..eadab26de2d 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -137,6 +137,10 @@ export class PXEService implements PXE { this.log.info('Stopped Synchronizer'); } + isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise { + return this.node.isL1ToL2MessageSynced(l1ToL2Message); + } + /** Returns an estimate of the db size in bytes. */ public estimateDbSize() { return this.db.estimateSize();