@aztec/p2p 5.2.0 → 5.3.0-nightly.20260819
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/msg_validators/tx_validator/factory.d.ts +3 -2
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +31 -13
- package/dest/msg_validators/tx_validator/gas_limits_validator.d.ts +73 -0
- package/dest/msg_validators/tx_validator/gas_limits_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/gas_limits_validator.js +107 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +11 -59
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +13 -100
- package/dest/msg_validators/tx_validator/index.d.ts +2 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +1 -0
- package/package.json +15 -15
- package/src/msg_validators/tx_validator/README.md +14 -9
- package/src/msg_validators/tx_validator/factory.ts +26 -11
- package/src/msg_validators/tx_validator/gas_limits_validator.ts +148 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +13 -128
- package/src/msg_validators/tx_validator/index.ts +1 -0
|
@@ -58,7 +58,8 @@ export interface TransactionValidator {
|
|
|
58
58
|
* without consulting the pool or running proof verification.
|
|
59
59
|
*
|
|
60
60
|
* The `doubleSpendValidator` failure is special-cased by the caller (`handleGossipedTx`)
|
|
61
|
-
* to determine severity based on how recently the nullifier appeared.
|
|
61
|
+
* to determine severity based on how recently the nullifier appeared. The caller reports the
|
|
62
|
+
* first failing entry among equally severe ones.
|
|
62
63
|
*/
|
|
63
64
|
export declare function createFirstStageTxValidationsForGossipedTransactions(timestamp: UInt64, blockNumber: BlockNumber, worldStateSynchronizer: WorldStateSynchronizer, gasFees: GasFees, l1ChainId: number, rollupVersion: number, protocolContractsHash: Fr, contractDataSource: ContractDataSource, txsPermitted: boolean, allowedInSetup?: AllowedElement[], bindings?: LoggerBindings, gasLimitOpts?: {
|
|
64
65
|
maxTxL2Gas?: number;
|
|
@@ -144,4 +145,4 @@ export declare function createTxValidatorForTransactionsEnteringPendingTxPool(wo
|
|
|
144
145
|
* migration validator can check it without needing the full Tx or its dependencies.
|
|
145
146
|
*/
|
|
146
147
|
export declare function createCheckAllowedSetupCalls(contractDataSource: ContractDataSource, setupAllowList: AllowedElement[], getTimestamp: () => UInt64): (tx: Tx) => Promise<boolean>;
|
|
147
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
148
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21zZ192YWxpZGF0b3JzL3R4X3ZhbGlkYXRvci9mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4Qkc7QUFDSCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDOUQsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3BELE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBSTVELE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDakQsT0FBTyxLQUFLLEVBQ1YsY0FBYyxFQUNkLDZCQUE2QixFQUM3Qix3QkFBd0IsRUFDeEIsd0JBQXdCLEVBQ3hCLHNCQUFzQixFQUN2QixNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXRELE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxFQUFFLEVBQUUsa0JBQWtCLEVBQUUsV0FBVyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDN0YsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFbEQsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFpQjVFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRTdEOzs7O0dBSUc7QUFDSCxNQUFNLFdBQVcsb0JBQW9CO0lBQ25DLFNBQVMsRUFBRTtRQUNULFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0tBQ2pELENB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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/tx_validator/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EACV,cAAc,EACd,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/tx_validator/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EACV,cAAc,EACd,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2CAA2C,CAAC;AAiB5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE;QACT,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;KACjD,CAAC;IACF,QAAQ,EAAE,iBAAiB,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,oDAAoD,CAClE,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,sBAAsB,EAAE,sBAAsB,EAC9C,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,qBAAqB,EAAE,EAAE,EACzB,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,OAAO,EACrB,cAAc,GAAE,cAAc,EAAO,EACrC,QAAQ,CAAC,EAAE,cAAc,EACzB,YAAY,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1D,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAiFtC;AAED;;;;;;GAMG;AACH,wBAAgB,qDAAqD,CACnE,aAAa,EAAE,6BAA6B,EAC5C,QAAQ,CAAC,EAAE,cAAc,GACxB,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAOtC;AAyCD;;;;;GAKG;AACH,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,6BAA6B,EACvC,EACE,SAAS,EACT,aAAa,EACd,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB,EACD,QAAQ,CAAC,EAAE,cAAc,EACzB,KAAK,CAAC,EAAE,iBAAiB,GACxB,WAAW,CAEb;AAED;;;;GAIG;AACH,wBAAgB,4CAA4C,CAC1D,QAAQ,EAAE,6BAA6B,EACvC,EACE,SAAS,EACT,aAAa,EACd,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB,EACD,QAAQ,CAAC,EAAE,cAAc,EACzB,KAAK,CAAC,EAAE,iBAAiB,GACxB,WAAW,CAEb;AAED;;;;;GAKG;AACH,wBAAgB,uCAAuC,CACrD,EAAE,EAAE,wBAAwB,EAC5B,kBAAkB,EAAE,kBAAkB,EACtC,QAAQ,EAAE,6BAA6B,GAAG,SAAS,EACnD,EACE,SAAS,EACT,aAAa,EACb,cAAc,EACd,OAAO,EACP,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,WAAW,EACX,YAAY,EACZ,UAAU,EACV,UAAU,EACX,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,cAAc,EAAE,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACD,QAAQ,CAAC,EAAE,cAAc,GACxB,WAAW,CAAC,EAAE,CAAC,CAiDjB;AAED;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAC/C,EAAE,EAAE,wBAAwB,EAC5B,kBAAkB,EAAE,kBAAkB,EACtC,eAAe,EAAE,eAAe,EAChC,cAAc,EAAE,cAAc,EAAE,EAChC,QAAQ,CAAC,EAAE,cAAc,GACxB,wBAAwB,CAiB1B;AA+BD;;;;;;;;;;;;GAYG;AACH,wBAAsB,qDAAqD,CACzE,sBAAsB,EAAE,sBAAsB,EAC9C,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAC1D,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAuBlC;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,kBAAkB,EAAE,kBAAkB,EACtC,cAAc,EAAE,cAAc,EAAE,EAChC,YAAY,EAAE,MAAM,MAAM,GACzB,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAM9B"}
|
|
@@ -40,7 +40,8 @@ import { CachedTxValidator } from './cached_tx_validator.js';
|
|
|
40
40
|
import { ContractInstanceTxValidator } from './contract_instance_validator.js';
|
|
41
41
|
import { DataTxValidator } from './data_validator.js';
|
|
42
42
|
import { DoubleSpendTxValidator } from './double_spend_validator.js';
|
|
43
|
-
import {
|
|
43
|
+
import { MaxGasLimitsValidator, MinGasLimitsValidator } from './gas_limits_validator.js';
|
|
44
|
+
import { GasTxValidator, MaxFeePerGasValidator } from './gas_validator.js';
|
|
44
45
|
import { MetadataTxValidator } from './metadata_validator.js';
|
|
45
46
|
import { NullifierCache } from './nullifier_cache.js';
|
|
46
47
|
import { AllowedSetupCallsMetaValidator, PhasesTxValidator } from './phases_validator.js';
|
|
@@ -55,7 +56,8 @@ import { TxProofValidator } from './tx_proof_validator.js';
|
|
|
55
56
|
* without consulting the pool or running proof verification.
|
|
56
57
|
*
|
|
57
58
|
* The `doubleSpendValidator` failure is special-cased by the caller (`handleGossipedTx`)
|
|
58
|
-
* to determine severity based on how recently the nullifier appeared.
|
|
59
|
+
* to determine severity based on how recently the nullifier appeared. The caller reports the
|
|
60
|
+
* first failing entry among equally severe ones.
|
|
59
61
|
*/ export function createFirstStageTxValidationsForGossipedTransactions(timestamp, blockNumber, worldStateSynchronizer, gasFees, l1ChainId, rollupVersion, protocolContractsHash, contractDataSource, txsPermitted, allowedInSetup = [], bindings, gasLimitOpts) {
|
|
60
62
|
const merkleTree = worldStateSynchronizer.getCommitted();
|
|
61
63
|
return {
|
|
@@ -101,8 +103,19 @@ import { TxProofValidator } from './tx_proof_validator.js';
|
|
|
101
103
|
}, bindings),
|
|
102
104
|
severity: PeerErrorSeverity.MidToleranceError
|
|
103
105
|
},
|
|
106
|
+
minGasLimitsValidator: {
|
|
107
|
+
validator: new MinGasLimitsValidator(bindings),
|
|
108
|
+
severity: PeerErrorSeverity.MidToleranceError
|
|
109
|
+
},
|
|
110
|
+
maxGasLimitsValidator: {
|
|
111
|
+
validator: new MaxGasLimitsValidator({
|
|
112
|
+
...gasLimitOpts,
|
|
113
|
+
bindings
|
|
114
|
+
}),
|
|
115
|
+
severity: PeerErrorSeverity.MidToleranceError
|
|
116
|
+
},
|
|
104
117
|
gasValidator: {
|
|
105
|
-
validator: new GasTxValidator(new DatabasePublicStateSource(merkleTree), ProtocolContractAddress.FeeJuice, gasFees, bindings
|
|
118
|
+
validator: new GasTxValidator(new DatabasePublicStateSource(merkleTree), ProtocolContractAddress.FeeJuice, gasFees, bindings),
|
|
106
119
|
severity: PeerErrorSeverity.MidToleranceError
|
|
107
120
|
},
|
|
108
121
|
dataValidator: {
|
|
@@ -189,16 +202,17 @@ import { TxProofValidator } from './tx_proof_validator.js';
|
|
|
189
202
|
new BlockHeaderTxValidator(new ArchiveCache(db), bindings),
|
|
190
203
|
new DoubleSpendTxValidator(new NullifierCache(db), bindings),
|
|
191
204
|
new DataTxValidator(bindings),
|
|
192
|
-
new ContractInstanceTxValidator(bindings)
|
|
205
|
+
new ContractInstanceTxValidator(bindings),
|
|
206
|
+
// Declared gas-limit admission is not fee enforcement, so it runs even when fees are skipped. The floor
|
|
207
|
+
// has no exemption: a tx declaring less than the fixed overheads can never be mined, so rejecting it
|
|
208
|
+
// during simulation is the earliest useful feedback rather than a surprise on sendTx.
|
|
209
|
+
new MinGasLimitsValidator(bindings)
|
|
193
210
|
];
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
// limit on the estimation tx would reject a valid estimation. The fee-balance check below stays behind
|
|
198
|
-
// `skipFeeEnforcement`, and GasTxValidator is constructed without the limit opts so it does not re-run
|
|
199
|
-
// this same check.
|
|
211
|
+
// Only the ceiling is exempted during simulation: gas estimation submits intentionally-inflated
|
|
212
|
+
// `forEstimation` limits (above the per-tx max) and the wallet clamps the real tx to the admission limit
|
|
213
|
+
// afterward, so enforcing the ceiling on the estimation tx would reject a valid estimation.
|
|
200
214
|
if (!isSimulation) {
|
|
201
|
-
validators.push(new
|
|
215
|
+
validators.push(new MaxGasLimitsValidator({
|
|
202
216
|
maxTxL2Gas,
|
|
203
217
|
maxTxDAGas,
|
|
204
218
|
bindings
|
|
@@ -233,7 +247,11 @@ function createTxValidatorForValidatingAgainstCurrentState(nullifierSource, arch
|
|
|
233
247
|
return new AggregateTxValidator(new TimestampTxValidator({
|
|
234
248
|
timestamp: globalVariables.timestamp,
|
|
235
249
|
blockNumber: globalVariables.blockNumber
|
|
236
|
-
}, bindings), new PhasesTxValidator(contractDataSource, setupAllowList, globalVariables.timestamp, bindings), new BlockHeaderTxValidator(archiveSource, bindings), new DoubleSpendTxValidator(nullifierSource, bindings), new
|
|
250
|
+
}, bindings), new PhasesTxValidator(contractDataSource, setupAllowList, globalVariables.timestamp, bindings), new BlockHeaderTxValidator(archiveSource, bindings), new DoubleSpendTxValidator(nullifierSource, bindings), new MinGasLimitsValidator(bindings), // No limit opts: enforce only the per-tx protocol ceiling. Network admission limits are relay policy and
|
|
251
|
+
// must not invalidate a proposed block.
|
|
252
|
+
new MaxGasLimitsValidator({
|
|
253
|
+
bindings
|
|
254
|
+
}), new GasTxValidator(publicStateSource, ProtocolContractAddress.FeeJuice, globalVariables.gasFees, bindings));
|
|
237
255
|
}
|
|
238
256
|
/**
|
|
239
257
|
* Validators for txs migrating to the pending pool.
|
|
@@ -261,7 +279,7 @@ function createTxValidatorForValidatingAgainstCurrentState(nullifierSource, arch
|
|
|
261
279
|
return merkleTree.findLeafIndices(MerkleTreeId.ARCHIVE, archives);
|
|
262
280
|
}
|
|
263
281
|
};
|
|
264
|
-
return new AggregateTxValidator(new
|
|
282
|
+
return new AggregateTxValidator(new MinGasLimitsValidator(bindings), new MaxGasLimitsValidator({
|
|
265
283
|
...gasLimitOpts,
|
|
266
284
|
bindings
|
|
267
285
|
}), new MaxFeePerGasValidator(gasFees, bindings), new TimestampTxValidator({
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type LoggerBindings } from '@aztec/foundation/log';
|
|
2
|
+
import { Gas } from '@aztec/stdlib/gas';
|
|
3
|
+
import { type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
4
|
+
/**
|
|
5
|
+
* Structural interface for types that carry gas limit data, used by {@link MinGasLimitsValidator} and
|
|
6
|
+
* {@link MaxGasLimitsValidator}.
|
|
7
|
+
*/
|
|
8
|
+
export interface HasGasLimitData {
|
|
9
|
+
txHash: {
|
|
10
|
+
toString(): string;
|
|
11
|
+
};
|
|
12
|
+
data: {
|
|
13
|
+
forPublic?: unknown;
|
|
14
|
+
constants: {
|
|
15
|
+
txContext: {
|
|
16
|
+
gasSettings: {
|
|
17
|
+
gasLimits: Gas;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Validates that a transaction declares at least the gas it is guaranteed to be charged.
|
|
25
|
+
*
|
|
26
|
+
* Rejects transactions whose gas limits fall below the fixed protocol overheads
|
|
27
|
+
* ({@link TX_DA_GAS_OVERHEAD} and {@link PRIVATE_TX_L2_GAS_OVERHEAD} / {@link PUBLIC_TX_L2_GAS_OVERHEAD}).
|
|
28
|
+
* This is a cheap, stateless check that operates on gas settings alone.
|
|
29
|
+
*
|
|
30
|
+
* The floor is a protocol property with no exemptions: a tx below it can never be mined, so every entry
|
|
31
|
+
* point applies it, including gas estimation.
|
|
32
|
+
*
|
|
33
|
+
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
34
|
+
* (used during pending pool migration).
|
|
35
|
+
*/
|
|
36
|
+
export declare class MinGasLimitsValidator<T extends HasGasLimitData> implements TxValidator<T> {
|
|
37
|
+
#private;
|
|
38
|
+
constructor(bindings?: LoggerBindings);
|
|
39
|
+
validateTx(tx: T): Promise<TxValidationResult>;
|
|
40
|
+
/** Checks gas limits are >= the fixed protocol overheads (L2 and DA). */
|
|
41
|
+
validateGasLimit(tx: T): TxValidationResult;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Validates that a transaction does not declare more gas than it is allowed to.
|
|
45
|
+
*
|
|
46
|
+
* Rejects transactions whose gas limits exceed the per-tx protocol maxima, optionally tightened to the
|
|
47
|
+
* network admission limits. This is a cheap, stateless check that operates on gas settings alone.
|
|
48
|
+
*
|
|
49
|
+
* Unlike the floor, the ceiling is exempted on the gas estimation path, where limits are deliberately
|
|
50
|
+
* inflated past what the protocol allows (see {@link GasSettings.forEstimation}).
|
|
51
|
+
*
|
|
52
|
+
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
53
|
+
* (used during pending pool migration).
|
|
54
|
+
*/
|
|
55
|
+
export declare class MaxGasLimitsValidator<T extends HasGasLimitData> implements TxValidator<T> {
|
|
56
|
+
#private;
|
|
57
|
+
/**
|
|
58
|
+
* @param maxTxL2Gas - The network admission limit on L2 gas a single tx may declare (the per-block mana
|
|
59
|
+
* allocation, see {@link computeNetworkTxGasLimits}). Defaults to the per-tx protocol maximum, so callers
|
|
60
|
+
* that pass nothing (e.g. block building) enforce only the protocol ceiling.
|
|
61
|
+
* @param maxTxDAGas - The network admission limit on DA gas a single tx may declare. Defaults to the
|
|
62
|
+
* per-tx protocol maximum {@link MAX_TX_DA_GAS}.
|
|
63
|
+
*/
|
|
64
|
+
constructor(opts?: {
|
|
65
|
+
maxTxL2Gas?: number;
|
|
66
|
+
maxTxDAGas?: number;
|
|
67
|
+
bindings?: LoggerBindings;
|
|
68
|
+
});
|
|
69
|
+
validateTx(tx: T): Promise<TxValidationResult>;
|
|
70
|
+
/** Checks gas limits are <= the effective max gas (L2 and DA). */
|
|
71
|
+
validateGasLimit(tx: T): TxValidationResult;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FzX2xpbWl0c192YWxpZGF0b3IuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tc2dfdmFsaWRhdG9ycy90eF92YWxpZGF0b3IvZ2FzX2xpbWl0c192YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBT0EsT0FBTyxFQUFlLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBQ3ZGLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN4QyxPQUFPLEVBR0wsS0FBSyxrQkFBa0IsRUFDdkIsS0FBSyxXQUFXLEVBQ2pCLE1BQU0sa0JBQWtCLENBQUM7QUFFMUI7OztHQUdHO0FBQ0gsTUFBTSxXQUFXLGVBQWU7SUFDOUIsTUFBTSxFQUFFO1FBQUUsUUFBUSxJQUFJLE1BQU0sQ0FBQTtLQUFFLENBQUM7SUFDL0IsSUFBSSxFQUFFO1FBRUosU0FBUyxDQUFDLEVBQUUsT0FBTyxDQUFDO1FBQ3BCLFNBQVMsRUFBRTtZQUNULFNBQVMsRUFBRTtnQkFDVCxXQUFXLEVBQUU7b0JBQUUsU0FBUyxFQUFFLEdBQUcsQ0FBQTtpQkFBRSxDQUFDO2FBQ2pDLENBQUM7U0FDSCxDQUFDO0tBQ0gsQ0FBQztDQUNIO0FBRUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gscUJBQWEscUJBQXFCLENBQUMsQ0FBQyxTQUFTLGVBQWUsQ0FBRSxZQUFXLFdBQVcsQ0FBQyxDQUFDLENBQUM7O0lBR3JGLFlBQVksUUFBUSxDQUFDLEVBQUUsY0FBYyxFQUVwQztJQUVELFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUU3QztJQUVELHlFQUF5RTtJQUN6RSxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLGtCQUFrQixDQXFCMUM7Q0FDRjtBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gscUJBQWEscUJBQXFCLENBQUMsQ0FBQyxTQUFTLGVBQWUsQ0FBRSxZQUFXLFdBQVcsQ0FBQyxDQUFDLENBQUM7O0lBS3JGOzs7Ozs7T0FNRztJQUNILFlBQVksSUFBSSxDQUFDLEVBQUU7UUFBRSxVQUFVLENBQUMsRUFBRSxNQUFNLENBQUM7UUFBQyxVQUFVLENBQUMsRUFBRSxNQUFNLENBQUM7UUFBQyxRQUFRLENBQUMsRUFBRSxjQUFjLENBQUE7S0FBRSxFQU96RjtJQUVELFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUU3QztJQUVELGtFQUFrRTtJQUNsRSxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLGtCQUFrQixDQTBCMUM7Q0FDRiJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gas_limits_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/tx_validator/gas_limits_validator.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAE1B;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,CAAC;IAC/B,IAAI,EAAE;QAEJ,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE;YACT,SAAS,EAAE;gBACT,WAAW,EAAE;oBAAE,SAAS,EAAE,GAAG,CAAA;iBAAE,CAAC;aACjC,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAqB,CAAC,CAAC,SAAS,eAAe,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;;IAGrF,YAAY,QAAQ,CAAC,EAAE,cAAc,EAEpC;IAED,UAAU,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAE7C;IAED,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,EAAE,CAAC,GAAG,kBAAkB,CAqB1C;CACF;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,qBAAqB,CAAC,CAAC,SAAS,eAAe,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;;IAKrF;;;;;;OAMG;IACH,YAAY,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE,EAOzF;IAED,UAAU,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAE7C;IAED,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,EAAE,CAAC,GAAG,kBAAkB,CA0B1C;CACF"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { MAX_PROCESSABLE_L2_GAS, MAX_TX_DA_GAS, PRIVATE_TX_L2_GAS_OVERHEAD, PUBLIC_TX_L2_GAS_OVERHEAD, TX_DA_GAS_OVERHEAD } from '@aztec/constants';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { Gas } from '@aztec/stdlib/gas';
|
|
4
|
+
import { TX_ERROR_GAS_LIMIT_TOO_HIGH, TX_ERROR_INSUFFICIENT_GAS_LIMIT } from '@aztec/stdlib/tx';
|
|
5
|
+
/**
|
|
6
|
+
* Validates that a transaction declares at least the gas it is guaranteed to be charged.
|
|
7
|
+
*
|
|
8
|
+
* Rejects transactions whose gas limits fall below the fixed protocol overheads
|
|
9
|
+
* ({@link TX_DA_GAS_OVERHEAD} and {@link PRIVATE_TX_L2_GAS_OVERHEAD} / {@link PUBLIC_TX_L2_GAS_OVERHEAD}).
|
|
10
|
+
* This is a cheap, stateless check that operates on gas settings alone.
|
|
11
|
+
*
|
|
12
|
+
* The floor is a protocol property with no exemptions: a tx below it can never be mined, so every entry
|
|
13
|
+
* point applies it, including gas estimation.
|
|
14
|
+
*
|
|
15
|
+
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
16
|
+
* (used during pending pool migration).
|
|
17
|
+
*/ export class MinGasLimitsValidator {
|
|
18
|
+
#log;
|
|
19
|
+
constructor(bindings){
|
|
20
|
+
this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
|
|
21
|
+
}
|
|
22
|
+
validateTx(tx) {
|
|
23
|
+
return Promise.resolve(this.validateGasLimit(tx));
|
|
24
|
+
}
|
|
25
|
+
/** Checks gas limits are >= the fixed protocol overheads (L2 and DA). */ validateGasLimit(tx) {
|
|
26
|
+
const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
27
|
+
const minGasLimits = new Gas(TX_DA_GAS_OVERHEAD, tx.data.forPublic ? PUBLIC_TX_L2_GAS_OVERHEAD : PRIVATE_TX_L2_GAS_OVERHEAD);
|
|
28
|
+
if (minGasLimits.gtAny(gasLimits)) {
|
|
29
|
+
this.#log.verbose(`Rejecting transaction due to the gas limit(s) not being above the minimum gas limit`, {
|
|
30
|
+
gasLimits,
|
|
31
|
+
minGasLimits
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
result: 'invalid',
|
|
35
|
+
reason: [
|
|
36
|
+
`${TX_ERROR_INSUFFICIENT_GAS_LIMIT} (required=da:${minGasLimits.daGas},l2:${minGasLimits.l2Gas} got=da:${gasLimits.daGas},l2:${gasLimits.l2Gas})`
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
result: 'valid'
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Validates that a transaction does not declare more gas than it is allowed to.
|
|
47
|
+
*
|
|
48
|
+
* Rejects transactions whose gas limits exceed the per-tx protocol maxima, optionally tightened to the
|
|
49
|
+
* network admission limits. This is a cheap, stateless check that operates on gas settings alone.
|
|
50
|
+
*
|
|
51
|
+
* Unlike the floor, the ceiling is exempted on the gas estimation path, where limits are deliberately
|
|
52
|
+
* inflated past what the protocol allows (see {@link GasSettings.forEstimation}).
|
|
53
|
+
*
|
|
54
|
+
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
55
|
+
* (used during pending pool migration).
|
|
56
|
+
*/ export class MaxGasLimitsValidator {
|
|
57
|
+
#log;
|
|
58
|
+
#effectiveMaxL2Gas;
|
|
59
|
+
#effectiveMaxDAGas;
|
|
60
|
+
/**
|
|
61
|
+
* @param maxTxL2Gas - The network admission limit on L2 gas a single tx may declare (the per-block mana
|
|
62
|
+
* allocation, see {@link computeNetworkTxGasLimits}). Defaults to the per-tx protocol maximum, so callers
|
|
63
|
+
* that pass nothing (e.g. block building) enforce only the protocol ceiling.
|
|
64
|
+
* @param maxTxDAGas - The network admission limit on DA gas a single tx may declare. Defaults to the
|
|
65
|
+
* per-tx protocol maximum {@link MAX_TX_DA_GAS}.
|
|
66
|
+
*/ constructor(opts){
|
|
67
|
+
this.#log = createLogger('sequencer:tx_validator:tx_gas', opts?.bindings);
|
|
68
|
+
// The passed limits are network admission limits; clamp to the per-tx protocol maxima as a hard ceiling.
|
|
69
|
+
// MAX_TX_DA_GAS bounds DA by what a single tx can actually post to a blob; declaring more is meaningless
|
|
70
|
+
// and would let a tx reserve checkpoint/block DA budget during proposal building it can't use.
|
|
71
|
+
this.#effectiveMaxL2Gas = Math.min(MAX_PROCESSABLE_L2_GAS, opts?.maxTxL2Gas ?? Infinity);
|
|
72
|
+
this.#effectiveMaxDAGas = Math.min(MAX_TX_DA_GAS, opts?.maxTxDAGas ?? Infinity);
|
|
73
|
+
}
|
|
74
|
+
validateTx(tx) {
|
|
75
|
+
return Promise.resolve(this.validateGasLimit(tx));
|
|
76
|
+
}
|
|
77
|
+
/** Checks gas limits are <= the effective max gas (L2 and DA). */ validateGasLimit(tx) {
|
|
78
|
+
const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
79
|
+
if (gasLimits.l2Gas > this.#effectiveMaxL2Gas) {
|
|
80
|
+
this.#log.verbose(`Rejecting transaction due to the L2 gas limit being higher than the effective maximum`, {
|
|
81
|
+
gasLimits,
|
|
82
|
+
effectiveMaxL2Gas: this.#effectiveMaxL2Gas
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
result: 'invalid',
|
|
86
|
+
reason: [
|
|
87
|
+
`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (l2Gas=${gasLimits.l2Gas}, max=${this.#effectiveMaxL2Gas})`
|
|
88
|
+
]
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (gasLimits.daGas > this.#effectiveMaxDAGas) {
|
|
92
|
+
this.#log.verbose(`Rejecting transaction due to the DA gas limit being higher than the effective maximum`, {
|
|
93
|
+
gasLimits,
|
|
94
|
+
effectiveMaxDAGas: this.#effectiveMaxDAGas
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
result: 'invalid',
|
|
98
|
+
reason: [
|
|
99
|
+
`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (daGas=${gasLimits.daGas}, max=${this.#effectiveMaxDAGas})`
|
|
100
|
+
]
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
result: 'valid'
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
import { type LoggerBindings } from '@aztec/foundation/log';
|
|
2
2
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
|
-
import {
|
|
3
|
+
import type { GasFees } from '@aztec/stdlib/gas';
|
|
4
4
|
import type { PublicStateSource } from '@aztec/stdlib/trees';
|
|
5
5
|
import { type Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
6
|
-
/** Structural interface for types that carry gas limit data, used by {@link GasLimitsValidator}. */
|
|
7
|
-
export interface HasGasLimitData {
|
|
8
|
-
txHash: {
|
|
9
|
-
toString(): string;
|
|
10
|
-
};
|
|
11
|
-
data: {
|
|
12
|
-
forPublic?: unknown;
|
|
13
|
-
constants: {
|
|
14
|
-
txContext: {
|
|
15
|
-
gasSettings: {
|
|
16
|
-
gasLimits: Gas;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
6
|
/** Structural interface for types that carry max fee per gas data, used by {@link MaxFeePerGasValidator}. */
|
|
23
7
|
export interface HasMaxFeePerGasData {
|
|
24
8
|
txHash: {
|
|
@@ -34,36 +18,6 @@ export interface HasMaxFeePerGasData {
|
|
|
34
18
|
};
|
|
35
19
|
};
|
|
36
20
|
}
|
|
37
|
-
/**
|
|
38
|
-
* Validates that a transaction's gas limits are within acceptable bounds.
|
|
39
|
-
*
|
|
40
|
-
* Rejects transactions whose gas limits fall below the fixed minimums (FIXED_DA_GAS,
|
|
41
|
-
* FIXED_L2_GAS) or exceed the AVM's maximum processable L2 gas. This is a cheap,
|
|
42
|
-
* stateless check that operates on gas settings alone.
|
|
43
|
-
*
|
|
44
|
-
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
45
|
-
* (used during pending pool migration).
|
|
46
|
-
*
|
|
47
|
-
* Used by: pending pool migration (via factory), and indirectly by {@link GasTxValidator}.
|
|
48
|
-
*/
|
|
49
|
-
export declare class GasLimitsValidator<T extends HasGasLimitData> implements TxValidator<T> {
|
|
50
|
-
#private;
|
|
51
|
-
/**
|
|
52
|
-
* @param maxTxL2Gas - The network admission limit on L2 gas a single tx may declare (the per-block mana
|
|
53
|
-
* allocation, see {@link computeNetworkTxGasLimits}). Defaults to the per-tx protocol maximum, so callers
|
|
54
|
-
* that pass nothing (e.g. block building) enforce only the protocol ceiling.
|
|
55
|
-
* @param maxTxDAGas - The network admission limit on DA gas a single tx may declare. Defaults to the
|
|
56
|
-
* per-tx protocol maximum {@link MAX_TX_DA_GAS}.
|
|
57
|
-
*/
|
|
58
|
-
constructor(opts?: {
|
|
59
|
-
maxTxL2Gas?: number;
|
|
60
|
-
maxTxDAGas?: number;
|
|
61
|
-
bindings?: LoggerBindings;
|
|
62
|
-
});
|
|
63
|
-
validateTx(tx: T): Promise<TxValidationResult>;
|
|
64
|
-
/** Checks gas limits are >= fixed minimums and <= effective max gas (L2 and DA). */
|
|
65
|
-
validateGasLimit(tx: T): TxValidationResult;
|
|
66
|
-
}
|
|
67
21
|
/**
|
|
68
22
|
* Validates that a transaction's max fee per gas meets the current block's gas fees.
|
|
69
23
|
*
|
|
@@ -85,24 +39,22 @@ export declare class MaxFeePerGasValidator<T extends HasMaxFeePerGasData> implem
|
|
|
85
39
|
/**
|
|
86
40
|
* Validates that a transaction can pay its gas fees.
|
|
87
41
|
*
|
|
88
|
-
* Runs
|
|
89
|
-
* 1. **
|
|
90
|
-
*
|
|
91
|
-
* 2. **
|
|
92
|
-
* the current block's gas fees.
|
|
93
|
-
* 3. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
|
|
42
|
+
* Runs two checks in order:
|
|
43
|
+
* 1. **Max fee per gas** (delegates to {@link MaxFeePerGasValidator}) — rejects the tx if its
|
|
44
|
+
* maxFeesPerGas is below the current block's gas fees.
|
|
45
|
+
* 2. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
|
|
94
46
|
* adds any pending claim from a setup-phase `_increase_public_balance` call, and
|
|
95
47
|
* rejects if the total is less than the tx's fee limit (gasLimits * maxFeePerGas).
|
|
96
48
|
*
|
|
49
|
+
* Gas limits are deliberately not checked here: they are owned by {@link MinGasLimitsValidator} and
|
|
50
|
+
* {@link MaxGasLimitsValidator}, which factories include separately so that exemptions (e.g. gas estimation)
|
|
51
|
+
* don't change fee enforcement.
|
|
52
|
+
*
|
|
97
53
|
* Used by: gossip (stage 1), RPC, and block building validators.
|
|
98
54
|
*/
|
|
99
55
|
export declare class GasTxValidator implements TxValidator<Tx> {
|
|
100
56
|
#private;
|
|
101
|
-
|
|
102
|
-
constructor(publicDataSource: PublicStateSource, feeJuiceAddress: AztecAddress, gasFees: GasFees, bindings?: LoggerBindings | undefined, opts?: {
|
|
103
|
-
maxTxL2Gas?: number;
|
|
104
|
-
maxTxDAGas?: number;
|
|
105
|
-
});
|
|
57
|
+
constructor(publicDataSource: PublicStateSource, feeJuiceAddress: AztecAddress, gasFees: GasFees, bindings?: LoggerBindings);
|
|
106
58
|
validateTx(tx: Tx): Promise<TxValidationResult>;
|
|
107
59
|
/**
|
|
108
60
|
* Checks the fee payer has enough FeeJuice balance to cover the tx's fee limit.
|
|
@@ -110,4 +62,4 @@ export declare class GasTxValidator implements TxValidator<Tx> {
|
|
|
110
62
|
*/
|
|
111
63
|
validateTxFee(tx: Tx): Promise<TxValidationResult>;
|
|
112
64
|
}
|
|
113
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FzX3ZhbGlkYXRvci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21zZ192YWxpZGF0b3JzL3R4X3ZhbGlkYXRvci9nYXNfdmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBZSxLQUFLLGNBQWMsRUFBZ0IsTUFBTSx1QkFBdUIsQ0FBQztBQUV2RixPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNqRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sRUFHTCxLQUFLLEVBQUUsRUFDUCxLQUFLLGtCQUFrQixFQUN2QixLQUFLLFdBQVcsRUFDakIsTUFBTSxrQkFBa0IsQ0FBQztBQUkxQiw2R0FBNkc7QUFDN0csTUFBTSxXQUFXLG1CQUFtQjtJQUNsQyxNQUFNLEVBQUU7UUFBRSxRQUFRLElBQUksTUFBTSxDQUFBO0tBQUUsQ0FBQztJQUMvQixJQUFJLEVBQUU7UUFDSixTQUFTLEVBQUU7WUFDVCxTQUFTLEVBQUU7Z0JBQ1QsV0FBVyxFQUFFO29CQUFFLGFBQWEsRUFBRSxPQUFPLENBQUE7aUJBQUUsQ0FBQzthQUN6QyxDQUFDO1NBQ0gsQ0FBQztLQUNILENBQUM7Q0FDSDtBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxxQkFBYSxxQkFBcUIsQ0FBQyxDQUFDLFNBQVMsbUJBQW1CLENBQUUsWUFBVyxXQUFXLENBQUMsQ0FBQyxDQUFDOztJQUl6RixZQUFZLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLEVBQUUsY0FBYyxFQUd0RDtJQUVELFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUU3QztJQUVELHlFQUF5RTtJQUN6RSxvQkFBb0IsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLGtCQUFrQixDQWtCOUM7Q0FDRjtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILHFCQUFhLGNBQWUsWUFBVyxXQUFXLENBQUMsRUFBRSxDQUFDOztJQU1wRCxZQUNFLGdCQUFnQixFQUFFLGlCQUFpQixFQUNuQyxlQUFlLEVBQUUsWUFBWSxFQUM3QixPQUFPLEVBQUUsT0FBTyxFQUNoQixRQUFRLENBQUMsRUFBRSxjQUFjLEVBTTFCO0lBRUssVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBTXBEO0lBRUQ7OztPQUdHO0lBQ1UsYUFBYSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBNEI5RDtDQUNGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/tx_validator/gas_validator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gas_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/tx_validator/gas_validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAGL,KAAK,EAAE,EACP,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAI1B,6GAA6G;AAC7G,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE;QAAE,QAAQ,IAAI,MAAM,CAAA;KAAE,CAAC;IAC/B,IAAI,EAAE;QACJ,SAAS,EAAE;YACT,SAAS,EAAE;gBACT,WAAW,EAAE;oBAAE,aAAa,EAAE,OAAO,CAAA;iBAAE,CAAC;aACzC,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED;;;;;;;;;;GAUG;AACH,qBAAa,qBAAqB,CAAC,CAAC,SAAS,mBAAmB,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;;IAIzF,YAAY,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,cAAc,EAGtD;IAED,UAAU,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAE7C;IAED,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,EAAE,CAAC,GAAG,kBAAkB,CAkB9C;CACF;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAe,YAAW,WAAW,CAAC,EAAE,CAAC;;IAMpD,YACE,gBAAgB,EAAE,iBAAiB,EACnC,eAAe,EAAE,YAAY,EAC7B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,cAAc,EAM1B;IAEK,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAMpD;IAED;;;OAGG;IACU,aAAa,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA4B9D;CACF"}
|
|
@@ -1,85 +1,7 @@
|
|
|
1
|
-
import { MAX_PROCESSABLE_L2_GAS, MAX_TX_DA_GAS, PRIVATE_TX_L2_GAS_OVERHEAD, PUBLIC_TX_L2_GAS_OVERHEAD, TX_DA_GAS_OVERHEAD } from '@aztec/constants';
|
|
2
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
2
|
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
4
|
-
import {
|
|
5
|
-
import { TX_ERROR_GAS_LIMIT_TOO_HIGH, TX_ERROR_INSUFFICIENT_FEE_PAYER_BALANCE, TX_ERROR_INSUFFICIENT_FEE_PER_GAS, TX_ERROR_INSUFFICIENT_GAS_LIMIT } from '@aztec/stdlib/tx';
|
|
3
|
+
import { TX_ERROR_INSUFFICIENT_FEE_PAYER_BALANCE, TX_ERROR_INSUFFICIENT_FEE_PER_GAS } from '@aztec/stdlib/tx';
|
|
6
4
|
import { getFeePayerClaimAmount, getTxFeeLimit } from './fee_payer_balance.js';
|
|
7
|
-
/**
|
|
8
|
-
* Validates that a transaction's gas limits are within acceptable bounds.
|
|
9
|
-
*
|
|
10
|
-
* Rejects transactions whose gas limits fall below the fixed minimums (FIXED_DA_GAS,
|
|
11
|
-
* FIXED_L2_GAS) or exceed the AVM's maximum processable L2 gas. This is a cheap,
|
|
12
|
-
* stateless check that operates on gas settings alone.
|
|
13
|
-
*
|
|
14
|
-
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
15
|
-
* (used during pending pool migration).
|
|
16
|
-
*
|
|
17
|
-
* Used by: pending pool migration (via factory), and indirectly by {@link GasTxValidator}.
|
|
18
|
-
*/ export class GasLimitsValidator {
|
|
19
|
-
#log;
|
|
20
|
-
#effectiveMaxL2Gas;
|
|
21
|
-
#effectiveMaxDAGas;
|
|
22
|
-
/**
|
|
23
|
-
* @param maxTxL2Gas - The network admission limit on L2 gas a single tx may declare (the per-block mana
|
|
24
|
-
* allocation, see {@link computeNetworkTxGasLimits}). Defaults to the per-tx protocol maximum, so callers
|
|
25
|
-
* that pass nothing (e.g. block building) enforce only the protocol ceiling.
|
|
26
|
-
* @param maxTxDAGas - The network admission limit on DA gas a single tx may declare. Defaults to the
|
|
27
|
-
* per-tx protocol maximum {@link MAX_TX_DA_GAS}.
|
|
28
|
-
*/ constructor(opts){
|
|
29
|
-
this.#log = createLogger('sequencer:tx_validator:tx_gas', opts?.bindings);
|
|
30
|
-
// The passed limits are network admission limits; clamp to the per-tx protocol maxima as a hard ceiling.
|
|
31
|
-
// MAX_TX_DA_GAS bounds DA by what a single tx can actually post to a blob; declaring more is meaningless
|
|
32
|
-
// and would let a tx reserve checkpoint/block DA budget during proposal building it can't use.
|
|
33
|
-
this.#effectiveMaxL2Gas = Math.min(MAX_PROCESSABLE_L2_GAS, opts?.maxTxL2Gas ?? Infinity);
|
|
34
|
-
this.#effectiveMaxDAGas = Math.min(MAX_TX_DA_GAS, opts?.maxTxDAGas ?? Infinity);
|
|
35
|
-
}
|
|
36
|
-
validateTx(tx) {
|
|
37
|
-
return Promise.resolve(this.validateGasLimit(tx));
|
|
38
|
-
}
|
|
39
|
-
/** Checks gas limits are >= fixed minimums and <= effective max gas (L2 and DA). */ validateGasLimit(tx) {
|
|
40
|
-
const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
41
|
-
const minGasLimits = new Gas(TX_DA_GAS_OVERHEAD, tx.data.forPublic ? PUBLIC_TX_L2_GAS_OVERHEAD : PRIVATE_TX_L2_GAS_OVERHEAD);
|
|
42
|
-
if (minGasLimits.gtAny(gasLimits)) {
|
|
43
|
-
this.#log.verbose(`Rejecting transaction due to the gas limit(s) not being above the minimum gas limit`, {
|
|
44
|
-
gasLimits,
|
|
45
|
-
minGasLimits
|
|
46
|
-
});
|
|
47
|
-
return {
|
|
48
|
-
result: 'invalid',
|
|
49
|
-
reason: [
|
|
50
|
-
`${TX_ERROR_INSUFFICIENT_GAS_LIMIT} (required=da:${minGasLimits.daGas},l2:${minGasLimits.l2Gas} got=da:${gasLimits.daGas},l2:${gasLimits.l2Gas})`
|
|
51
|
-
]
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
if (gasLimits.l2Gas > this.#effectiveMaxL2Gas) {
|
|
55
|
-
this.#log.verbose(`Rejecting transaction due to the L2 gas limit being higher than the effective maximum`, {
|
|
56
|
-
gasLimits,
|
|
57
|
-
effectiveMaxL2Gas: this.#effectiveMaxL2Gas
|
|
58
|
-
});
|
|
59
|
-
return {
|
|
60
|
-
result: 'invalid',
|
|
61
|
-
reason: [
|
|
62
|
-
`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (l2Gas=${gasLimits.l2Gas}, max=${this.#effectiveMaxL2Gas})`
|
|
63
|
-
]
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
if (gasLimits.daGas > this.#effectiveMaxDAGas) {
|
|
67
|
-
this.#log.verbose(`Rejecting transaction due to the DA gas limit being higher than the effective maximum`, {
|
|
68
|
-
gasLimits,
|
|
69
|
-
effectiveMaxDAGas: this.#effectiveMaxDAGas
|
|
70
|
-
});
|
|
71
|
-
return {
|
|
72
|
-
result: 'invalid',
|
|
73
|
-
reason: [
|
|
74
|
-
`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (daGas=${gasLimits.daGas}, max=${this.#effectiveMaxDAGas})`
|
|
75
|
-
]
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
return {
|
|
79
|
-
result: 'valid'
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
5
|
/**
|
|
84
6
|
* Validates that a transaction's max fee per gas meets the current block's gas fees.
|
|
85
7
|
*
|
|
@@ -123,40 +45,31 @@ import { getFeePayerClaimAmount, getTxFeeLimit } from './fee_payer_balance.js';
|
|
|
123
45
|
/**
|
|
124
46
|
* Validates that a transaction can pay its gas fees.
|
|
125
47
|
*
|
|
126
|
-
* Runs
|
|
127
|
-
* 1. **
|
|
128
|
-
*
|
|
129
|
-
* 2. **
|
|
130
|
-
* the current block's gas fees.
|
|
131
|
-
* 3. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
|
|
48
|
+
* Runs two checks in order:
|
|
49
|
+
* 1. **Max fee per gas** (delegates to {@link MaxFeePerGasValidator}) — rejects the tx if its
|
|
50
|
+
* maxFeesPerGas is below the current block's gas fees.
|
|
51
|
+
* 2. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
|
|
132
52
|
* adds any pending claim from a setup-phase `_increase_public_balance` call, and
|
|
133
53
|
* rejects if the total is less than the tx's fee limit (gasLimits * maxFeePerGas).
|
|
134
54
|
*
|
|
55
|
+
* Gas limits are deliberately not checked here: they are owned by {@link MinGasLimitsValidator} and
|
|
56
|
+
* {@link MaxGasLimitsValidator}, which factories include separately so that exemptions (e.g. gas estimation)
|
|
57
|
+
* don't change fee enforcement.
|
|
58
|
+
*
|
|
135
59
|
* Used by: gossip (stage 1), RPC, and block building validators.
|
|
136
60
|
*/ export class GasTxValidator {
|
|
137
|
-
bindings;
|
|
138
61
|
#log;
|
|
139
62
|
#publicDataSource;
|
|
140
63
|
#feeJuiceAddress;
|
|
141
|
-
#
|
|
142
|
-
|
|
143
|
-
constructor(publicDataSource, feeJuiceAddress, gasFees, bindings, opts){
|
|
144
|
-
this.bindings = bindings;
|
|
64
|
+
#maxFeePerGasValidator;
|
|
65
|
+
constructor(publicDataSource, feeJuiceAddress, gasFees, bindings){
|
|
145
66
|
this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
|
|
146
67
|
this.#publicDataSource = publicDataSource;
|
|
147
68
|
this.#feeJuiceAddress = feeJuiceAddress;
|
|
148
|
-
this.#
|
|
149
|
-
this.#gasLimitOpts = opts;
|
|
69
|
+
this.#maxFeePerGasValidator = new MaxFeePerGasValidator(gasFees, bindings);
|
|
150
70
|
}
|
|
151
71
|
async validateTx(tx) {
|
|
152
|
-
const
|
|
153
|
-
...this.#gasLimitOpts,
|
|
154
|
-
bindings: this.bindings
|
|
155
|
-
}).validateGasLimit(tx);
|
|
156
|
-
if (gasLimitValidation.result === 'invalid') {
|
|
157
|
-
return gasLimitValidation;
|
|
158
|
-
}
|
|
159
|
-
const maxFeeValidation = new MaxFeePerGasValidator(this.#gasFees, this.bindings).validateMaxFeePerGas(tx);
|
|
72
|
+
const maxFeeValidation = this.#maxFeePerGasValidator.validateMaxFeePerGas(tx);
|
|
160
73
|
if (maxFeeValidation.result === 'invalid') {
|
|
161
74
|
return maxFeeValidation;
|
|
162
75
|
}
|
|
@@ -4,6 +4,7 @@ export * from './double_spend_validator.js';
|
|
|
4
4
|
export * from './metadata_validator.js';
|
|
5
5
|
export * from './tx_proof_validator.js';
|
|
6
6
|
export * from './block_header_validator.js';
|
|
7
|
+
export * from './gas_limits_validator.js';
|
|
7
8
|
export * from './gas_validator.js';
|
|
8
9
|
export * from './phases_validator.js';
|
|
9
10
|
export * from './test_utils.js';
|
|
@@ -16,4 +17,4 @@ export * from './size_validator.js';
|
|
|
16
17
|
export * from './factory.js';
|
|
17
18
|
export * from './tx_validation_cache.js';
|
|
18
19
|
export * from './cached_tx_validator.js';
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tc2dfdmFsaWRhdG9ycy90eF92YWxpZGF0b3IvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYywyQkFBMkIsQ0FBQztBQUMxQyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsMEJBQTBCLENBQUMifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/tx_validator/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/tx_validator/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC"}
|
|
@@ -4,6 +4,7 @@ export * from './double_spend_validator.js';
|
|
|
4
4
|
export * from './metadata_validator.js';
|
|
5
5
|
export * from './tx_proof_validator.js';
|
|
6
6
|
export * from './block_header_validator.js';
|
|
7
|
+
export * from './gas_limits_validator.js';
|
|
7
8
|
export * from './gas_validator.js';
|
|
8
9
|
export * from './phases_validator.js';
|
|
9
10
|
export * from './test_utils.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/p2p",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0-nightly.20260819",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -67,18 +67,18 @@
|
|
|
67
67
|
]
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@aztec/constants": "5.
|
|
71
|
-
"@aztec/epoch-cache": "5.
|
|
72
|
-
"@aztec/ethereum": "5.
|
|
73
|
-
"@aztec/foundation": "5.
|
|
74
|
-
"@aztec/kv-store": "5.
|
|
75
|
-
"@aztec/noir-contracts.js": "5.
|
|
76
|
-
"@aztec/noir-protocol-circuits-types": "5.
|
|
77
|
-
"@aztec/protocol-contracts": "5.
|
|
78
|
-
"@aztec/simulator": "5.
|
|
79
|
-
"@aztec/standard-contracts": "5.
|
|
80
|
-
"@aztec/stdlib": "5.
|
|
81
|
-
"@aztec/telemetry-client": "5.
|
|
70
|
+
"@aztec/constants": "5.3.0-nightly.20260819",
|
|
71
|
+
"@aztec/epoch-cache": "5.3.0-nightly.20260819",
|
|
72
|
+
"@aztec/ethereum": "5.3.0-nightly.20260819",
|
|
73
|
+
"@aztec/foundation": "5.3.0-nightly.20260819",
|
|
74
|
+
"@aztec/kv-store": "5.3.0-nightly.20260819",
|
|
75
|
+
"@aztec/noir-contracts.js": "5.3.0-nightly.20260819",
|
|
76
|
+
"@aztec/noir-protocol-circuits-types": "5.3.0-nightly.20260819",
|
|
77
|
+
"@aztec/protocol-contracts": "5.3.0-nightly.20260819",
|
|
78
|
+
"@aztec/simulator": "5.3.0-nightly.20260819",
|
|
79
|
+
"@aztec/standard-contracts": "5.3.0-nightly.20260819",
|
|
80
|
+
"@aztec/stdlib": "5.3.0-nightly.20260819",
|
|
81
|
+
"@aztec/telemetry-client": "5.3.0-nightly.20260819",
|
|
82
82
|
"@chainsafe/libp2p-gossipsub": "13.0.0",
|
|
83
83
|
"@chainsafe/libp2p-noise": "^15.0.0",
|
|
84
84
|
"@chainsafe/libp2p-yamux": "^6.0.2",
|
|
@@ -104,8 +104,8 @@
|
|
|
104
104
|
"tslib": "^2.4.0"
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
|
-
"@aztec/archiver": "5.
|
|
108
|
-
"@aztec/world-state": "5.
|
|
107
|
+
"@aztec/archiver": "5.3.0-nightly.20260819",
|
|
108
|
+
"@aztec/world-state": "5.3.0-nightly.20260819",
|
|
109
109
|
"@jest/globals": "^30.0.0",
|
|
110
110
|
"@types/jest": "^30.0.0",
|
|
111
111
|
"@types/node": "^22.15.17",
|
|
@@ -19,7 +19,7 @@ Unsolicited transactions from any peer. Fully validated in two stages with a poo
|
|
|
19
19
|
|
|
20
20
|
| Step | What runs | On failure |
|
|
21
21
|
|------|-----------|------------|
|
|
22
|
-
| **Stage 1** (fast) | TxPermitted, Data, Metadata, Timestamp, DoubleSpend, Gas, Phases, BlockHeader | Penalize peer, reject tx |
|
|
22
|
+
| **Stage 1** (fast) | TxPermitted, Data, Metadata, Timestamp, DoubleSpend, MinGasLimits, MaxGasLimits, Gas, Phases, BlockHeader | Penalize peer, reject tx |
|
|
23
23
|
| **Pool pre-check** | `canAddPendingTx` — checks for duplicates, pool capacity | Ignore tx (no penalty) |
|
|
24
24
|
| **Stage 2** (slow) | Proof verification | Penalize peer, reject tx |
|
|
25
25
|
| **Pool add** | `addPendingTxs` | Accept, ignore, or reject |
|
|
@@ -34,6 +34,8 @@ Each stage-1 and stage-2 validator is paired with a `PeerErrorSeverity`. If a va
|
|
|
34
34
|
Unsolicited transactions from a local wallet/PXE. Runs the full set of checks as a single aggregate validator:
|
|
35
35
|
|
|
36
36
|
- TxPermitted, Size, Data, Metadata, Timestamp, DoubleSpend, Phases, BlockHeader
|
|
37
|
+
- MinGasLimits
|
|
38
|
+
- MaxGasLimits (skipped for simulations — gas estimation submits limits above the per-tx maximum)
|
|
37
39
|
- Gas (optional — skipped when `skipFeeEnforcement` is set)
|
|
38
40
|
- Proof verification (optional — skipped for simulations when no verifier is provided)
|
|
39
41
|
|
|
@@ -56,7 +58,7 @@ State-dependent checks are deferred to either the block building validator (for
|
|
|
56
58
|
Transactions already in the pool, about to be sequenced into a block. Re-validates against the current state of the block being built. **This is where invalid txs that entered via req/resp or block proposals are caught** — their invalidity is reported as part of block validation/attestation.
|
|
57
59
|
|
|
58
60
|
Runs:
|
|
59
|
-
- Timestamp, DoubleSpend, Phases, Gas, BlockHeader
|
|
61
|
+
- Timestamp, DoubleSpend, Phases, MinGasLimits, MaxGasLimits, Gas, BlockHeader
|
|
60
62
|
|
|
61
63
|
Does **not** run:
|
|
62
64
|
- Proof, Data — already verified on entry (by gossip, RPC, or req/resp validators)
|
|
@@ -75,7 +77,7 @@ This validator is invoked on **every** transaction potentially entering the pend
|
|
|
75
77
|
- Startup hydration — revalidating persisted non-mined txs on node restart
|
|
76
78
|
|
|
77
79
|
Runs:
|
|
78
|
-
- DoubleSpend, BlockHeader,
|
|
80
|
+
- DoubleSpend, BlockHeader, MinGasLimits, MaxGasLimits, MaxFeePerGas, Timestamp, AllowedSetupCalls
|
|
79
81
|
|
|
80
82
|
Operates on `TxMetaData` (pre-built by the pool) rather than full `Tx` objects.
|
|
81
83
|
|
|
@@ -91,8 +93,9 @@ The `AllowedSetupCallsMetaValidator` checks a precomputed boolean flag (`TxMetaD
|
|
|
91
93
|
| `MetadataTxValidator` | Chain ID, rollup version, protocol contracts hash, VK tree root | 4.18 us |
|
|
92
94
|
| `TimestampTxValidator` | Transaction has not expired (expiration timestamp vs next slot) | 1.56 us |
|
|
93
95
|
| `DoubleSpendTxValidator` | Nullifiers do not already exist in the nullifier tree | 106.08 us |
|
|
94
|
-
| `GasTxValidator` |
|
|
95
|
-
| `
|
|
96
|
+
| `GasTxValidator` | Max fee per gas meets current block fees (delegates to `MaxFeePerGasValidator`), and fee payer has sufficient FeeJuice balance | 1.02 ms |
|
|
97
|
+
| `MinGasLimitsValidator` | Gas limits are >= the fixed protocol overheads. Applies on every entry point, with no exemptions | 3–10 us |
|
|
98
|
+
| `MaxGasLimitsValidator` | Gas limits are <= AVM max processable L2 gas (optionally clamped further by network admission limits). Exempted on the gas estimation path | 3–10 us |
|
|
96
99
|
| `MaxFeePerGasValidator` | Max fee per gas >= current block gas fees on both dimensions (DA and L2). Used standalone in pool migration; also called internally by `GasTxValidator` | 3–10 us |
|
|
97
100
|
| `PhasesTxValidator` | Public function calls in setup phase are on the allow list | 10.12–13.12 us |
|
|
98
101
|
| `AllowedSetupCallsMetaValidator` | Checks the precomputed `allowedSetupCalls` flag on `TxMetaData`. Used in pool migration instead of the full `PhasesTxValidator` | — |
|
|
@@ -109,18 +112,20 @@ The `AllowedSetupCallsMetaValidator` checks a precomputed boolean flag (`TxMetaD
|
|
|
109
112
|
| Metadata | Stage 1 | Yes | Yes | — | — |
|
|
110
113
|
| Timestamp | Stage 1 | Yes | — | Yes | Yes |
|
|
111
114
|
| DoubleSpend | Stage 1 | Yes | — | Yes | Yes |
|
|
112
|
-
| Gas (balance
|
|
113
|
-
|
|
|
115
|
+
| Gas (fee balance) | Stage 1 | Optional* | — | Yes | — |
|
|
116
|
+
| MinGasLimits | Stage 1 | Yes | — | Yes | Yes |
|
|
117
|
+
| MaxGasLimits | Stage 1 | Yes*** | — | Yes | Yes |
|
|
114
118
|
| MaxFeePerGas (standalone) | — | — | — | — | Yes |
|
|
115
119
|
| Phases | Stage 1 | Yes | — | Yes | — |
|
|
116
120
|
| AllowedSetupCalls | — | — | — | — | Yes |
|
|
117
121
|
| BlockHeader | Stage 1 | Yes | — | Yes | Yes |
|
|
118
122
|
| Proof | Stage 2 | Optional** | Yes | — | — |
|
|
119
123
|
|
|
120
|
-
\* Gas balance check is skipped when `skipFeeEnforcement` is set (testing/dev). `GasTxValidator` internally delegates to `
|
|
124
|
+
\* Gas balance check is skipped when `skipFeeEnforcement` is set (testing/dev). `GasTxValidator` internally delegates to `MaxFeePerGasValidator` as its first step, so fee-per-gas is checked wherever `GasTxValidator` runs. Pool migration uses `MaxFeePerGasValidator` standalone because it doesn't need the balance check. Declared gas-limit validation is owned solely by `MinGasLimitsValidator` and `MaxGasLimitsValidator`.
|
|
121
125
|
\** Proof verification is skipped for simulations (no verifier provided).
|
|
126
|
+
\*** Only the ceiling is skipped for simulations: gas estimation submits limits above the per-tx maximum, and the wallet clamps the real tx to the admission limit afterward. The floor still applies, since a tx below it can never be mined.
|
|
122
127
|
|
|
123
|
-
The gas-limit bounds `
|
|
128
|
+
The gas-limit bounds `MaxGasLimitsValidator` enforces here — the per-tx protocol maxima and the network admission limits — are documented in [`stdlib/src/gas/README.md`](../../../../stdlib/src/gas/README.md) under "Gas and Data Limits".
|
|
124
129
|
|
|
125
130
|
## Fee-Per-Gas Rejection Strategy
|
|
126
131
|
|
|
@@ -57,7 +57,8 @@ import { CachedTxValidator } from './cached_tx_validator.js';
|
|
|
57
57
|
import { ContractInstanceTxValidator } from './contract_instance_validator.js';
|
|
58
58
|
import { DataTxValidator } from './data_validator.js';
|
|
59
59
|
import { DoubleSpendTxValidator, type NullifierSource } from './double_spend_validator.js';
|
|
60
|
-
import {
|
|
60
|
+
import { MaxGasLimitsValidator, MinGasLimitsValidator } from './gas_limits_validator.js';
|
|
61
|
+
import { GasTxValidator, MaxFeePerGasValidator } from './gas_validator.js';
|
|
61
62
|
import { MetadataTxValidator } from './metadata_validator.js';
|
|
62
63
|
import { NullifierCache } from './nullifier_cache.js';
|
|
63
64
|
import { AllowedSetupCallsMetaValidator, PhasesTxValidator } from './phases_validator.js';
|
|
@@ -86,7 +87,8 @@ export interface TransactionValidator {
|
|
|
86
87
|
* without consulting the pool or running proof verification.
|
|
87
88
|
*
|
|
88
89
|
* The `doubleSpendValidator` failure is special-cased by the caller (`handleGossipedTx`)
|
|
89
|
-
* to determine severity based on how recently the nullifier appeared.
|
|
90
|
+
* to determine severity based on how recently the nullifier appeared. The caller reports the
|
|
91
|
+
* first failing entry among equally severe ones.
|
|
90
92
|
*/
|
|
91
93
|
export function createFirstStageTxValidationsForGossipedTransactions(
|
|
92
94
|
timestamp: UInt64,
|
|
@@ -156,13 +158,20 @@ export function createFirstStageTxValidationsForGossipedTransactions(
|
|
|
156
158
|
),
|
|
157
159
|
severity: PeerErrorSeverity.MidToleranceError, // This is handled specifically at the point of rejection by considering a recent window where it may have been valid
|
|
158
160
|
},
|
|
161
|
+
minGasLimitsValidator: {
|
|
162
|
+
validator: new MinGasLimitsValidator<Tx>(bindings),
|
|
163
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
164
|
+
},
|
|
165
|
+
maxGasLimitsValidator: {
|
|
166
|
+
validator: new MaxGasLimitsValidator<Tx>({ ...gasLimitOpts, bindings }),
|
|
167
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
168
|
+
},
|
|
159
169
|
gasValidator: {
|
|
160
170
|
validator: new GasTxValidator(
|
|
161
171
|
new DatabasePublicStateSource(merkleTree),
|
|
162
172
|
ProtocolContractAddress.FeeJuice,
|
|
163
173
|
gasFees,
|
|
164
174
|
bindings,
|
|
165
|
-
gasLimitOpts,
|
|
166
175
|
),
|
|
167
176
|
severity: PeerErrorSeverity.MidToleranceError,
|
|
168
177
|
},
|
|
@@ -337,16 +346,17 @@ export function createTxValidatorForAcceptingTxsOverRPC(
|
|
|
337
346
|
new DoubleSpendTxValidator(new NullifierCache(db), bindings),
|
|
338
347
|
new DataTxValidator(bindings),
|
|
339
348
|
new ContractInstanceTxValidator(bindings),
|
|
349
|
+
// Declared gas-limit admission is not fee enforcement, so it runs even when fees are skipped. The floor
|
|
350
|
+
// has no exemption: a tx declaring less than the fixed overheads can never be mined, so rejecting it
|
|
351
|
+
// during simulation is the earliest useful feedback rather than a surprise on sendTx.
|
|
352
|
+
new MinGasLimitsValidator<Tx>(bindings),
|
|
340
353
|
];
|
|
341
354
|
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
//
|
|
345
|
-
// limit on the estimation tx would reject a valid estimation. The fee-balance check below stays behind
|
|
346
|
-
// `skipFeeEnforcement`, and GasTxValidator is constructed without the limit opts so it does not re-run
|
|
347
|
-
// this same check.
|
|
355
|
+
// Only the ceiling is exempted during simulation: gas estimation submits intentionally-inflated
|
|
356
|
+
// `forEstimation` limits (above the per-tx max) and the wallet clamps the real tx to the admission limit
|
|
357
|
+
// afterward, so enforcing the ceiling on the estimation tx would reject a valid estimation.
|
|
348
358
|
if (!isSimulation) {
|
|
349
|
-
validators.push(new
|
|
359
|
+
validators.push(new MaxGasLimitsValidator<Tx>({ maxTxL2Gas, maxTxDAGas, bindings }));
|
|
350
360
|
}
|
|
351
361
|
|
|
352
362
|
if (!skipFeeEnforcement) {
|
|
@@ -416,6 +426,10 @@ function createTxValidatorForValidatingAgainstCurrentState(
|
|
|
416
426
|
new PhasesTxValidator(contractDataSource, setupAllowList, globalVariables.timestamp, bindings),
|
|
417
427
|
new BlockHeaderTxValidator(archiveSource, bindings),
|
|
418
428
|
new DoubleSpendTxValidator(nullifierSource, bindings),
|
|
429
|
+
new MinGasLimitsValidator<Tx>(bindings),
|
|
430
|
+
// No limit opts: enforce only the per-tx protocol ceiling. Network admission limits are relay policy and
|
|
431
|
+
// must not invalidate a proposed block.
|
|
432
|
+
new MaxGasLimitsValidator<Tx>({ bindings }),
|
|
419
433
|
new GasTxValidator(publicStateSource, ProtocolContractAddress.FeeJuice, globalVariables.gasFees, bindings),
|
|
420
434
|
);
|
|
421
435
|
}
|
|
@@ -455,7 +469,8 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
|
|
|
455
469
|
},
|
|
456
470
|
};
|
|
457
471
|
return new AggregateTxValidator<TxMetaData>(
|
|
458
|
-
new
|
|
472
|
+
new MinGasLimitsValidator<TxMetaData>(bindings),
|
|
473
|
+
new MaxGasLimitsValidator<TxMetaData>({ ...gasLimitOpts, bindings }),
|
|
459
474
|
new MaxFeePerGasValidator<TxMetaData>(gasFees, bindings),
|
|
460
475
|
new TimestampTxValidator<TxMetaData>({ timestamp, blockNumber }, bindings),
|
|
461
476
|
new DoubleSpendTxValidator<TxMetaData>(nullifierSource, bindings),
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MAX_PROCESSABLE_L2_GAS,
|
|
3
|
+
MAX_TX_DA_GAS,
|
|
4
|
+
PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
5
|
+
PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
6
|
+
TX_DA_GAS_OVERHEAD,
|
|
7
|
+
} from '@aztec/constants';
|
|
8
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
9
|
+
import { Gas } from '@aztec/stdlib/gas';
|
|
10
|
+
import {
|
|
11
|
+
TX_ERROR_GAS_LIMIT_TOO_HIGH,
|
|
12
|
+
TX_ERROR_INSUFFICIENT_GAS_LIMIT,
|
|
13
|
+
type TxValidationResult,
|
|
14
|
+
type TxValidator,
|
|
15
|
+
} from '@aztec/stdlib/tx';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Structural interface for types that carry gas limit data, used by {@link MinGasLimitsValidator} and
|
|
19
|
+
* {@link MaxGasLimitsValidator}.
|
|
20
|
+
*/
|
|
21
|
+
export interface HasGasLimitData {
|
|
22
|
+
txHash: { toString(): string };
|
|
23
|
+
data: {
|
|
24
|
+
// We just need to know whether there is something here or not
|
|
25
|
+
forPublic?: unknown;
|
|
26
|
+
constants: {
|
|
27
|
+
txContext: {
|
|
28
|
+
gasSettings: { gasLimits: Gas };
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Validates that a transaction declares at least the gas it is guaranteed to be charged.
|
|
36
|
+
*
|
|
37
|
+
* Rejects transactions whose gas limits fall below the fixed protocol overheads
|
|
38
|
+
* ({@link TX_DA_GAS_OVERHEAD} and {@link PRIVATE_TX_L2_GAS_OVERHEAD} / {@link PUBLIC_TX_L2_GAS_OVERHEAD}).
|
|
39
|
+
* This is a cheap, stateless check that operates on gas settings alone.
|
|
40
|
+
*
|
|
41
|
+
* The floor is a protocol property with no exemptions: a tx below it can never be mined, so every entry
|
|
42
|
+
* point applies it, including gas estimation.
|
|
43
|
+
*
|
|
44
|
+
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
45
|
+
* (used during pending pool migration).
|
|
46
|
+
*/
|
|
47
|
+
export class MinGasLimitsValidator<T extends HasGasLimitData> implements TxValidator<T> {
|
|
48
|
+
#log: Logger;
|
|
49
|
+
|
|
50
|
+
constructor(bindings?: LoggerBindings) {
|
|
51
|
+
this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
validateTx(tx: T): Promise<TxValidationResult> {
|
|
55
|
+
return Promise.resolve(this.validateGasLimit(tx));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Checks gas limits are >= the fixed protocol overheads (L2 and DA). */
|
|
59
|
+
validateGasLimit(tx: T): TxValidationResult {
|
|
60
|
+
const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
61
|
+
const minGasLimits = new Gas(
|
|
62
|
+
TX_DA_GAS_OVERHEAD,
|
|
63
|
+
tx.data.forPublic ? PUBLIC_TX_L2_GAS_OVERHEAD : PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
if (minGasLimits.gtAny(gasLimits)) {
|
|
67
|
+
this.#log.verbose(`Rejecting transaction due to the gas limit(s) not being above the minimum gas limit`, {
|
|
68
|
+
gasLimits,
|
|
69
|
+
minGasLimits,
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
result: 'invalid',
|
|
73
|
+
reason: [
|
|
74
|
+
`${TX_ERROR_INSUFFICIENT_GAS_LIMIT} (required=da:${minGasLimits.daGas},l2:${minGasLimits.l2Gas} got=da:${gasLimits.daGas},l2:${gasLimits.l2Gas})`,
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { result: 'valid' };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Validates that a transaction does not declare more gas than it is allowed to.
|
|
85
|
+
*
|
|
86
|
+
* Rejects transactions whose gas limits exceed the per-tx protocol maxima, optionally tightened to the
|
|
87
|
+
* network admission limits. This is a cheap, stateless check that operates on gas settings alone.
|
|
88
|
+
*
|
|
89
|
+
* Unlike the floor, the ceiling is exempted on the gas estimation path, where limits are deliberately
|
|
90
|
+
* inflated past what the protocol allows (see {@link GasSettings.forEstimation}).
|
|
91
|
+
*
|
|
92
|
+
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
93
|
+
* (used during pending pool migration).
|
|
94
|
+
*/
|
|
95
|
+
export class MaxGasLimitsValidator<T extends HasGasLimitData> implements TxValidator<T> {
|
|
96
|
+
#log: Logger;
|
|
97
|
+
#effectiveMaxL2Gas: number;
|
|
98
|
+
#effectiveMaxDAGas: number;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param maxTxL2Gas - The network admission limit on L2 gas a single tx may declare (the per-block mana
|
|
102
|
+
* allocation, see {@link computeNetworkTxGasLimits}). Defaults to the per-tx protocol maximum, so callers
|
|
103
|
+
* that pass nothing (e.g. block building) enforce only the protocol ceiling.
|
|
104
|
+
* @param maxTxDAGas - The network admission limit on DA gas a single tx may declare. Defaults to the
|
|
105
|
+
* per-tx protocol maximum {@link MAX_TX_DA_GAS}.
|
|
106
|
+
*/
|
|
107
|
+
constructor(opts?: { maxTxL2Gas?: number; maxTxDAGas?: number; bindings?: LoggerBindings }) {
|
|
108
|
+
this.#log = createLogger('sequencer:tx_validator:tx_gas', opts?.bindings);
|
|
109
|
+
// The passed limits are network admission limits; clamp to the per-tx protocol maxima as a hard ceiling.
|
|
110
|
+
// MAX_TX_DA_GAS bounds DA by what a single tx can actually post to a blob; declaring more is meaningless
|
|
111
|
+
// and would let a tx reserve checkpoint/block DA budget during proposal building it can't use.
|
|
112
|
+
this.#effectiveMaxL2Gas = Math.min(MAX_PROCESSABLE_L2_GAS, opts?.maxTxL2Gas ?? Infinity);
|
|
113
|
+
this.#effectiveMaxDAGas = Math.min(MAX_TX_DA_GAS, opts?.maxTxDAGas ?? Infinity);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
validateTx(tx: T): Promise<TxValidationResult> {
|
|
117
|
+
return Promise.resolve(this.validateGasLimit(tx));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Checks gas limits are <= the effective max gas (L2 and DA). */
|
|
121
|
+
validateGasLimit(tx: T): TxValidationResult {
|
|
122
|
+
const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
123
|
+
|
|
124
|
+
if (gasLimits.l2Gas > this.#effectiveMaxL2Gas) {
|
|
125
|
+
this.#log.verbose(`Rejecting transaction due to the L2 gas limit being higher than the effective maximum`, {
|
|
126
|
+
gasLimits,
|
|
127
|
+
effectiveMaxL2Gas: this.#effectiveMaxL2Gas,
|
|
128
|
+
});
|
|
129
|
+
return {
|
|
130
|
+
result: 'invalid',
|
|
131
|
+
reason: [`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (l2Gas=${gasLimits.l2Gas}, max=${this.#effectiveMaxL2Gas})`],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (gasLimits.daGas > this.#effectiveMaxDAGas) {
|
|
136
|
+
this.#log.verbose(`Rejecting transaction due to the DA gas limit being higher than the effective maximum`, {
|
|
137
|
+
gasLimits,
|
|
138
|
+
effectiveMaxDAGas: this.#effectiveMaxDAGas,
|
|
139
|
+
});
|
|
140
|
+
return {
|
|
141
|
+
result: 'invalid',
|
|
142
|
+
reason: [`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (daGas=${gasLimits.daGas}, max=${this.#effectiveMaxDAGas})`],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return { result: 'valid' };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MAX_PROCESSABLE_L2_GAS,
|
|
3
|
-
MAX_TX_DA_GAS,
|
|
4
|
-
PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
5
|
-
PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
6
|
-
TX_DA_GAS_OVERHEAD,
|
|
7
|
-
} from '@aztec/constants';
|
|
8
1
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
9
2
|
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
10
3
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
11
|
-
import {
|
|
4
|
+
import type { GasFees } from '@aztec/stdlib/gas';
|
|
12
5
|
import type { PublicStateSource } from '@aztec/stdlib/trees';
|
|
13
6
|
import {
|
|
14
|
-
TX_ERROR_GAS_LIMIT_TOO_HIGH,
|
|
15
7
|
TX_ERROR_INSUFFICIENT_FEE_PAYER_BALANCE,
|
|
16
8
|
TX_ERROR_INSUFFICIENT_FEE_PER_GAS,
|
|
17
|
-
TX_ERROR_INSUFFICIENT_GAS_LIMIT,
|
|
18
9
|
type Tx,
|
|
19
10
|
type TxValidationResult,
|
|
20
11
|
type TxValidator,
|
|
@@ -22,20 +13,6 @@ import {
|
|
|
22
13
|
|
|
23
14
|
import { getFeePayerClaimAmount, getTxFeeLimit } from './fee_payer_balance.js';
|
|
24
15
|
|
|
25
|
-
/** Structural interface for types that carry gas limit data, used by {@link GasLimitsValidator}. */
|
|
26
|
-
export interface HasGasLimitData {
|
|
27
|
-
txHash: { toString(): string };
|
|
28
|
-
data: {
|
|
29
|
-
// We just need to know whether there is something here or not
|
|
30
|
-
forPublic?: unknown;
|
|
31
|
-
constants: {
|
|
32
|
-
txContext: {
|
|
33
|
-
gasSettings: { gasLimits: Gas };
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
16
|
/** Structural interface for types that carry max fee per gas data, used by {@link MaxFeePerGasValidator}. */
|
|
40
17
|
export interface HasMaxFeePerGasData {
|
|
41
18
|
txHash: { toString(): string };
|
|
@@ -48,90 +25,6 @@ export interface HasMaxFeePerGasData {
|
|
|
48
25
|
};
|
|
49
26
|
}
|
|
50
27
|
|
|
51
|
-
/**
|
|
52
|
-
* Validates that a transaction's gas limits are within acceptable bounds.
|
|
53
|
-
*
|
|
54
|
-
* Rejects transactions whose gas limits fall below the fixed minimums (FIXED_DA_GAS,
|
|
55
|
-
* FIXED_L2_GAS) or exceed the AVM's maximum processable L2 gas. This is a cheap,
|
|
56
|
-
* stateless check that operates on gas settings alone.
|
|
57
|
-
*
|
|
58
|
-
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
59
|
-
* (used during pending pool migration).
|
|
60
|
-
*
|
|
61
|
-
* Used by: pending pool migration (via factory), and indirectly by {@link GasTxValidator}.
|
|
62
|
-
*/
|
|
63
|
-
export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidator<T> {
|
|
64
|
-
#log: Logger;
|
|
65
|
-
#effectiveMaxL2Gas: number;
|
|
66
|
-
#effectiveMaxDAGas: number;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @param maxTxL2Gas - The network admission limit on L2 gas a single tx may declare (the per-block mana
|
|
70
|
-
* allocation, see {@link computeNetworkTxGasLimits}). Defaults to the per-tx protocol maximum, so callers
|
|
71
|
-
* that pass nothing (e.g. block building) enforce only the protocol ceiling.
|
|
72
|
-
* @param maxTxDAGas - The network admission limit on DA gas a single tx may declare. Defaults to the
|
|
73
|
-
* per-tx protocol maximum {@link MAX_TX_DA_GAS}.
|
|
74
|
-
*/
|
|
75
|
-
constructor(opts?: { maxTxL2Gas?: number; maxTxDAGas?: number; bindings?: LoggerBindings }) {
|
|
76
|
-
this.#log = createLogger('sequencer:tx_validator:tx_gas', opts?.bindings);
|
|
77
|
-
// The passed limits are network admission limits; clamp to the per-tx protocol maxima as a hard ceiling.
|
|
78
|
-
// MAX_TX_DA_GAS bounds DA by what a single tx can actually post to a blob; declaring more is meaningless
|
|
79
|
-
// and would let a tx reserve checkpoint/block DA budget during proposal building it can't use.
|
|
80
|
-
this.#effectiveMaxL2Gas = Math.min(MAX_PROCESSABLE_L2_GAS, opts?.maxTxL2Gas ?? Infinity);
|
|
81
|
-
this.#effectiveMaxDAGas = Math.min(MAX_TX_DA_GAS, opts?.maxTxDAGas ?? Infinity);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
validateTx(tx: T): Promise<TxValidationResult> {
|
|
85
|
-
return Promise.resolve(this.validateGasLimit(tx));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** Checks gas limits are >= fixed minimums and <= effective max gas (L2 and DA). */
|
|
89
|
-
validateGasLimit(tx: T): TxValidationResult {
|
|
90
|
-
const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
91
|
-
const minGasLimits = new Gas(
|
|
92
|
-
TX_DA_GAS_OVERHEAD,
|
|
93
|
-
tx.data.forPublic ? PUBLIC_TX_L2_GAS_OVERHEAD : PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
if (minGasLimits.gtAny(gasLimits)) {
|
|
97
|
-
this.#log.verbose(`Rejecting transaction due to the gas limit(s) not being above the minimum gas limit`, {
|
|
98
|
-
gasLimits,
|
|
99
|
-
minGasLimits,
|
|
100
|
-
});
|
|
101
|
-
return {
|
|
102
|
-
result: 'invalid',
|
|
103
|
-
reason: [
|
|
104
|
-
`${TX_ERROR_INSUFFICIENT_GAS_LIMIT} (required=da:${minGasLimits.daGas},l2:${minGasLimits.l2Gas} got=da:${gasLimits.daGas},l2:${gasLimits.l2Gas})`,
|
|
105
|
-
],
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (gasLimits.l2Gas > this.#effectiveMaxL2Gas) {
|
|
110
|
-
this.#log.verbose(`Rejecting transaction due to the L2 gas limit being higher than the effective maximum`, {
|
|
111
|
-
gasLimits,
|
|
112
|
-
effectiveMaxL2Gas: this.#effectiveMaxL2Gas,
|
|
113
|
-
});
|
|
114
|
-
return {
|
|
115
|
-
result: 'invalid',
|
|
116
|
-
reason: [`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (l2Gas=${gasLimits.l2Gas}, max=${this.#effectiveMaxL2Gas})`],
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (gasLimits.daGas > this.#effectiveMaxDAGas) {
|
|
121
|
-
this.#log.verbose(`Rejecting transaction due to the DA gas limit being higher than the effective maximum`, {
|
|
122
|
-
gasLimits,
|
|
123
|
-
effectiveMaxDAGas: this.#effectiveMaxDAGas,
|
|
124
|
-
});
|
|
125
|
-
return {
|
|
126
|
-
result: 'invalid',
|
|
127
|
-
reason: [`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (daGas=${gasLimits.daGas}, max=${this.#effectiveMaxDAGas})`],
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return { result: 'valid' };
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
28
|
/**
|
|
136
29
|
* Validates that a transaction's max fee per gas meets the current block's gas fees.
|
|
137
30
|
*
|
|
@@ -181,47 +74,39 @@ export class MaxFeePerGasValidator<T extends HasMaxFeePerGasData> implements TxV
|
|
|
181
74
|
/**
|
|
182
75
|
* Validates that a transaction can pay its gas fees.
|
|
183
76
|
*
|
|
184
|
-
* Runs
|
|
185
|
-
* 1. **
|
|
186
|
-
*
|
|
187
|
-
* 2. **
|
|
188
|
-
* the current block's gas fees.
|
|
189
|
-
* 3. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
|
|
77
|
+
* Runs two checks in order:
|
|
78
|
+
* 1. **Max fee per gas** (delegates to {@link MaxFeePerGasValidator}) — rejects the tx if its
|
|
79
|
+
* maxFeesPerGas is below the current block's gas fees.
|
|
80
|
+
* 2. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
|
|
190
81
|
* adds any pending claim from a setup-phase `_increase_public_balance` call, and
|
|
191
82
|
* rejects if the total is less than the tx's fee limit (gasLimits * maxFeePerGas).
|
|
192
83
|
*
|
|
84
|
+
* Gas limits are deliberately not checked here: they are owned by {@link MinGasLimitsValidator} and
|
|
85
|
+
* {@link MaxGasLimitsValidator}, which factories include separately so that exemptions (e.g. gas estimation)
|
|
86
|
+
* don't change fee enforcement.
|
|
87
|
+
*
|
|
193
88
|
* Used by: gossip (stage 1), RPC, and block building validators.
|
|
194
89
|
*/
|
|
195
90
|
export class GasTxValidator implements TxValidator<Tx> {
|
|
196
91
|
#log: Logger;
|
|
197
92
|
#publicDataSource: PublicStateSource;
|
|
198
93
|
#feeJuiceAddress: AztecAddress;
|
|
199
|
-
#
|
|
200
|
-
#gasLimitOpts?: { maxTxL2Gas?: number; maxTxDAGas?: number };
|
|
94
|
+
#maxFeePerGasValidator: MaxFeePerGasValidator<Tx>;
|
|
201
95
|
|
|
202
96
|
constructor(
|
|
203
97
|
publicDataSource: PublicStateSource,
|
|
204
98
|
feeJuiceAddress: AztecAddress,
|
|
205
99
|
gasFees: GasFees,
|
|
206
|
-
|
|
207
|
-
opts?: { maxTxL2Gas?: number; maxTxDAGas?: number },
|
|
100
|
+
bindings?: LoggerBindings,
|
|
208
101
|
) {
|
|
209
102
|
this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
|
|
210
103
|
this.#publicDataSource = publicDataSource;
|
|
211
104
|
this.#feeJuiceAddress = feeJuiceAddress;
|
|
212
|
-
this.#
|
|
213
|
-
this.#gasLimitOpts = opts;
|
|
105
|
+
this.#maxFeePerGasValidator = new MaxFeePerGasValidator(gasFees, bindings);
|
|
214
106
|
}
|
|
215
107
|
|
|
216
108
|
async validateTx(tx: Tx): Promise<TxValidationResult> {
|
|
217
|
-
const
|
|
218
|
-
...this.#gasLimitOpts,
|
|
219
|
-
bindings: this.bindings,
|
|
220
|
-
}).validateGasLimit(tx);
|
|
221
|
-
if (gasLimitValidation.result === 'invalid') {
|
|
222
|
-
return gasLimitValidation;
|
|
223
|
-
}
|
|
224
|
-
const maxFeeValidation = new MaxFeePerGasValidator(this.#gasFees, this.bindings).validateMaxFeePerGas(tx);
|
|
109
|
+
const maxFeeValidation = this.#maxFeePerGasValidator.validateMaxFeePerGas(tx);
|
|
225
110
|
if (maxFeeValidation.result === 'invalid') {
|
|
226
111
|
return maxFeeValidation;
|
|
227
112
|
}
|
|
@@ -4,6 +4,7 @@ export * from './double_spend_validator.js';
|
|
|
4
4
|
export * from './metadata_validator.js';
|
|
5
5
|
export * from './tx_proof_validator.js';
|
|
6
6
|
export * from './block_header_validator.js';
|
|
7
|
+
export * from './gas_limits_validator.js';
|
|
7
8
|
export * from './gas_validator.js';
|
|
8
9
|
export * from './phases_validator.js';
|
|
9
10
|
export * from './test_utils.js';
|