Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion yarn-project/aztec-node/src/aztec-node/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe('aztec node', () => {
let feePayer: AztecAddress;

const chainId = new Fr(12345);
const rollupVersion = new Fr(1);

const mockTxForRollup = async (seed: number) => {
return await mockTx(seed, {
Expand Down Expand Up @@ -117,7 +118,7 @@ describe('aztec node', () => {
undefined,
undefined,
12345,
1,
rollupVersion.toNumber(),
globalVariablesBuilder,
new TestCircuitVerifier(),
);
Expand All @@ -128,6 +129,7 @@ describe('aztec node', () => {
const txs = await Promise.all([mockTxForRollup(0x10000), mockTxForRollup(0x20000)]);
txs.forEach(tx => {
tx.data.constants.txContext.chainId = chainId;
tx.data.constants.txContext.version = rollupVersion;
});
const doubleSpendTx = txs[0];
const doubleSpendWithExistingTx = txs[1];
Expand Down Expand Up @@ -164,6 +166,7 @@ describe('aztec node', () => {
it('tests that the node correctly validates chain id', async () => {
const tx = await mockTxForRollup(0x10000);
tx.data.constants.txContext.chainId = chainId;
tx.data.constants.txContext.version = rollupVersion;

expect(await node.isValidTx(tx)).toEqual({ result: 'valid' });

Expand All @@ -173,10 +176,24 @@ describe('aztec node', () => {
expect(await node.isValidTx(tx)).toEqual({ result: 'invalid', reason: ['Incorrect chain id'] });
});

it('tests that the node correctly validates rollup version', async () => {
const tx = await mockTxForRollup(0x10000);
tx.data.constants.txContext.chainId = chainId;
tx.data.constants.txContext.version = rollupVersion;

expect(await node.isValidTx(tx)).toEqual({ result: 'valid' });

// We make the chain id on the tx not equal to the configured chain id
tx.data.constants.txContext.version = new Fr(1n + rollupVersion.toBigInt());

expect(await node.isValidTx(tx)).toEqual({ result: 'invalid', reason: ['Incorrect rollup version'] });
});

it('tests that the node correctly validates max block numbers', async () => {
const txs = await Promise.all([mockTxForRollup(0x10000), mockTxForRollup(0x20000), mockTxForRollup(0x30000)]);
txs.forEach(tx => {
tx.data.constants.txContext.chainId = chainId;
tx.data.constants.txContext.version = rollupVersion;
});

const noMaxBlockNumberMetadata = txs[0];
Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
const validator = createValidatorForAcceptingTxs(db, this.contractDataSource, verifier, {
blockNumber,
l1ChainId: this.l1ChainId,
rollupVersion: this.version,
setupAllowList: this.config.allowedInSetup ?? (await getDefaultAllowedSetupFunctions()),
gasFees: await this.getCurrentBaseFees(),
skipFeeEnforcement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import { MetadataTxValidator } from './metadata_validator.js';
describe('MetadataTxValidator', () => {
let blockNumber: Fr;
let chainId: Fr;
let rollupVersion: Fr;
let validator: MetadataTxValidator<AnyTx>;

beforeEach(() => {
chainId = new Fr(1);
blockNumber = new Fr(42);
validator = new MetadataTxValidator(chainId, blockNumber);
rollupVersion = new Fr(2);
validator = new MetadataTxValidator(chainId, rollupVersion, blockNumber);
});

const expectValid = async (tx: Tx) => {
Expand All @@ -30,10 +32,12 @@ describe('MetadataTxValidator', () => {

goodTxs.forEach(tx => {
tx.data.constants.txContext.chainId = chainId;
tx.data.constants.txContext.version = rollupVersion;
});

badTxs.forEach(tx => {
tx.data.constants.txContext.chainId = chainId.add(new Fr(1));
tx.data.constants.txContext.version = rollupVersion;
});

await expectValid(goodTxs[0]);
Expand All @@ -42,9 +46,30 @@ describe('MetadataTxValidator', () => {
await expectInvalid(badTxs[1], 'Incorrect chain id');
});

it('allows only transactions for the right rollup', async () => {
const goodTxs = await Promise.all([mockTx(1), mockTxForRollup(2)]);
const badTxs = await Promise.all([mockTx(3), mockTxForRollup(4)]);

goodTxs.forEach(tx => {
tx.data.constants.txContext.chainId = chainId;
tx.data.constants.txContext.version = rollupVersion;
});

badTxs.forEach(tx => {
tx.data.constants.txContext.chainId = chainId;
tx.data.constants.txContext.version = rollupVersion.add(Fr.ONE);
});

await expectValid(goodTxs[0]);
await expectValid(goodTxs[1]);
await expectInvalid(badTxs[0], 'Incorrect rollup version');
await expectInvalid(badTxs[1], 'Incorrect rollup version');
});

it.each([42, 43])('allows txs with valid max block number', async maxBlockNumber => {
const goodTx = await mockTxForRollup(1);
goodTx.data.constants.txContext.chainId = chainId;
goodTx.data.constants.txContext.version = rollupVersion;
goodTx.data.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber(true, new Fr(maxBlockNumber));

await expectValid(goodTx);
Expand All @@ -53,6 +78,7 @@ describe('MetadataTxValidator', () => {
it('allows txs with unset max block number', async () => {
const goodTx = await mockTxForRollup(1);
goodTx.data.constants.txContext.chainId = chainId;
goodTx.data.constants.txContext.version = rollupVersion;
goodTx.data.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber(false, Fr.ZERO);

await expectValid(goodTx);
Expand All @@ -61,6 +87,7 @@ describe('MetadataTxValidator', () => {
it('rejects txs with lower max block number', async () => {
const badTx = await mockTxForRollup(1);
badTx.data.constants.txContext.chainId = chainId;
badTx.data.constants.txContext.version = rollupVersion;
badTx.data.rollupValidationRequests.maxBlockNumber = new MaxBlockNumber(true, blockNumber.sub(new Fr(1)));

await expectInvalid(badTx, 'Invalid block number');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import { type AnyTx, Tx, type TxValidationResult, type TxValidator } from '@azte
export class MetadataTxValidator<T extends AnyTx> implements TxValidator<T> {
#log = createLogger('p2p:tx_validator:tx_metadata');

constructor(private chainId: Fr, private blockNumber: Fr) {}
constructor(private chainId: Fr, private rollupVersion: Fr, private blockNumber: Fr) {}

async validateTx(tx: T): Promise<TxValidationResult> {
const errors = [];
if (!(await this.#hasCorrectChainId(tx))) {
errors.push('Incorrect chain id');
}
if (!(await this.#hasCorrectRollupVersion(tx))) {
errors.push('Incorrect rollup version');
}
if (!(await this.#isValidForBlockNumber(tx))) {
errors.push('Invalid block number');
}
Expand Down Expand Up @@ -45,4 +48,17 @@ export class MetadataTxValidator<T extends AnyTx> implements TxValidator<T> {
return true;
}
}

async #hasCorrectRollupVersion(tx: T): Promise<boolean> {
if (!tx.data.constants.txContext.version.equals(this.rollupVersion)) {
this.#log.warn(
`Rejecting tx ${await Tx.getHash(
tx,
)} because of incorrect rollup version ${tx.data.constants.txContext.version.toNumber()} != ${this.rollupVersion.toNumber()}`,
);
return false;
} else {
return true;
}
}
}
6 changes: 5 additions & 1 deletion yarn-project/p2p/src/services/libp2p/libp2p_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,11 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
severity: PeerErrorSeverity.HighToleranceError,
},
metadataValidator: {
validator: new MetadataTxValidator(new Fr(this.config.l1ChainId), new Fr(blockNumber)),
validator: new MetadataTxValidator(
new Fr(this.config.l1ChainId),
new Fr(this.config.rollupVersion),
new Fr(blockNumber),
),
severity: PeerErrorSeverity.HighToleranceError,
},
proofValidator: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,22 @@ export function createValidatorForAcceptingTxs(
{
blockNumber,
l1ChainId,
rollupVersion,
setupAllowList,
gasFees,
skipFeeEnforcement,
}: {
blockNumber: number;
l1ChainId: number;
rollupVersion: number;
setupAllowList: AllowedElement[];
gasFees: GasFees;
skipFeeEnforcement?: boolean;
},
): TxValidator<Tx> {
const validators: TxValidator<Tx>[] = [
new DataTxValidator(),
new MetadataTxValidator(new Fr(l1ChainId), new Fr(blockNumber)),
new MetadataTxValidator(new Fr(l1ChainId), new Fr(rollupVersion), new Fr(blockNumber)),
new DoubleSpendTxValidator(new NullifierCache(db)),
new PhasesTxValidator(contractDataSource, setupAllowList, blockNumber),
new BlockHeaderTxValidator(new ArchiveCache(db)),
Expand Down Expand Up @@ -119,7 +121,7 @@ function preprocessValidator(
): TxValidator<Tx> {
// We don't include the TxProofValidator nor the DataTxValidator here because they are already checked by the time we get to block building.
return new AggregateTxValidator(
new MetadataTxValidator(globalVariables.chainId, globalVariables.blockNumber),
new MetadataTxValidator(globalVariables.chainId, globalVariables.version, globalVariables.blockNumber),
new DoubleSpendTxValidator(nullifierCache),
new PhasesTxValidator(contractDataSource, setupAllowList, globalVariables.blockNumber.toNumber()),
new GasTxValidator(publicStateSource, ProtocolContractAddress.FeeJuice, globalVariables.gasFees),
Expand Down