Skip to content

Commit 5b58db8

Browse files
authored
feat: ensuring PXE respects synced block (#17031)
Until know we didn't check that the functions fetching info from Aztec Node with block number on the input respect the PXE's view of the network - refuse to obtain info from a newer block than the one synced by PXE. In this PR I add the checks in those functions and I test it all behaves as expected. This should make the behavior of PXE more robust - you will not be able to receive info from an Aztec Node whose legitimacy you will not be able to prove against the anchor block (which seems like a very important property).
2 parents a6b66de + da47dfb commit 5b58db8

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

yarn-project/pxe/src/contract_function_simulator/pxe_oracle_interface.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,57 @@ describe('PXEOracleInterface', () => {
937937
});
938938
});
939939

940+
describe('Respects synced block number', () => {
941+
const syncedBlockNumber = 100;
942+
let contractAddress: AztecAddress;
943+
let nullifier: Fr;
944+
let leafSlot: Fr;
945+
946+
beforeEach(async () => {
947+
contractAddress = await AztecAddress.random();
948+
nullifier = Fr.random();
949+
leafSlot = Fr.random();
950+
await setSyncedBlockNumber(syncedBlockNumber);
951+
});
952+
953+
it('throws when getting low nullifier membership witness for future block', async () => {
954+
await expect(
955+
pxeOracleInterface.getLowNullifierMembershipWitness(syncedBlockNumber + 1, nullifier),
956+
).rejects.toThrow(`Block number ${syncedBlockNumber + 1} is higher than current block ${syncedBlockNumber}`);
957+
});
958+
959+
it('throws when getting block for future block number', async () => {
960+
await expect(pxeOracleInterface.getBlock(syncedBlockNumber + 1)).rejects.toThrow(
961+
`Block number ${syncedBlockNumber + 1} is higher than current block ${syncedBlockNumber}`,
962+
);
963+
});
964+
965+
it('throws when getting public data witness for future block', async () => {
966+
await expect(pxeOracleInterface.getPublicDataWitness(syncedBlockNumber + 1, leafSlot)).rejects.toThrow(
967+
`Block number ${syncedBlockNumber + 1} is higher than current block ${syncedBlockNumber}`,
968+
);
969+
});
970+
971+
it('throws when getting public storage for future block', async () => {
972+
await expect(
973+
pxeOracleInterface.getPublicStorageAt(syncedBlockNumber + 1, contractAddress, leafSlot),
974+
).rejects.toThrow(`Block number ${syncedBlockNumber + 1} is higher than current block ${syncedBlockNumber}`);
975+
});
976+
});
977+
978+
describe('getBlockHeader', () => {
979+
it('returns the synced block header and not header from aztec node', async () => {
980+
const blockNumber = 42;
981+
const header = BlockHeader.empty({
982+
globalVariables: GlobalVariables.empty({ blockNumber }),
983+
});
984+
await syncDataProvider.setHeader(header);
985+
986+
const result = await pxeOracleInterface.getBlockHeader();
987+
expect(result).toEqual(header);
988+
});
989+
});
990+
940991
const setSyncedBlockNumber = (blockNumber: number) => {
941992
return syncDataProvider.setHeader(
942993
BlockHeader.empty({

yarn-project/pxe/src/contract_function_simulator/pxe_oracle_interface.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,22 +203,38 @@ export class PXEOracleInterface implements ExecutionDataProvider {
203203
return this.aztecNode.getNullifierMembershipWitness(blockNumber, nullifier);
204204
}
205205

206-
public getLowNullifierMembershipWitness(
206+
public async getLowNullifierMembershipWitness(
207207
blockNumber: number,
208208
nullifier: Fr,
209209
): Promise<NullifierMembershipWitness | undefined> {
210+
const header = await this.getBlockHeader();
211+
if (blockNumber > header.globalVariables.blockNumber) {
212+
throw new Error(`Block number ${blockNumber} is higher than current block ${header.globalVariables.blockNumber}`);
213+
}
210214
return this.aztecNode.getLowNullifierMembershipWitness(blockNumber, nullifier);
211215
}
212216

213217
public async getBlock(blockNumber: number): Promise<L2Block | undefined> {
218+
const header = await this.getBlockHeader();
219+
if (blockNumber > header.globalVariables.blockNumber) {
220+
throw new Error(`Block number ${blockNumber} is higher than current block ${header.globalVariables.blockNumber}`);
221+
}
214222
return await this.aztecNode.getBlock(blockNumber);
215223
}
216224

217225
public async getPublicDataWitness(blockNumber: number, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
226+
const header = await this.getBlockHeader();
227+
if (blockNumber > header.globalVariables.blockNumber) {
228+
throw new Error(`Block number ${blockNumber} is higher than current block ${header.globalVariables.blockNumber}`);
229+
}
218230
return await this.aztecNode.getPublicDataWitness(blockNumber, leafSlot);
219231
}
220232

221233
public async getPublicStorageAt(blockNumber: number, contract: AztecAddress, slot: Fr): Promise<Fr> {
234+
const header = await this.getBlockHeader();
235+
if (blockNumber > header.globalVariables.blockNumber) {
236+
throw new Error(`Block number ${blockNumber} is higher than current block ${header.globalVariables.blockNumber}`);
237+
}
222238
return await this.aztecNode.getPublicStorageAt(blockNumber, contract, slot);
223239
}
224240

0 commit comments

Comments
 (0)