@aztec/sequencer-client 0.41.0 → 0.42.0
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/client/sequencer-client.js +2 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +9 -12
- package/dest/publisher/l1-publisher.d.ts +4 -1
- package/dest/publisher/l1-publisher.d.ts.map +1 -1
- package/dest/publisher/l1-publisher.js +6 -3
- package/dest/publisher/viem-tx-sender.d.ts.map +1 -1
- package/dest/publisher/viem-tx-sender.js +2 -1
- package/dest/receiver.d.ts +4 -1
- package/dest/receiver.d.ts.map +1 -1
- package/dest/sequencer/sequencer.d.ts +5 -2
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +39 -10
- package/dest/tx_validator/gas_validator.d.ts +1 -1
- package/dest/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/tx_validator/gas_validator.js +29 -8
- package/dest/tx_validator/phases_validator.d.ts +2 -2
- package/dest/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/tx_validator/phases_validator.js +14 -9
- package/dest/tx_validator/test_utils.d.ts +21 -0
- package/dest/tx_validator/test_utils.d.ts.map +1 -0
- package/dest/tx_validator/test_utils.js +19 -0
- package/dest/tx_validator/tx_validator_factory.d.ts +2 -3
- package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
- package/dest/tx_validator/tx_validator_factory.js +4 -5
- package/package.json +14 -14
- package/src/client/sequencer-client.ts +1 -1
- package/src/config.ts +8 -13
- package/src/publisher/l1-publisher.ts +8 -2
- package/src/publisher/viem-tx-sender.ts +1 -0
- package/src/receiver.ts +4 -1
- package/src/sequencer/sequencer.ts +51 -11
- package/src/tx_validator/gas_validator.ts +36 -6
- package/src/tx_validator/phases_validator.ts +17 -10
- package/src/tx_validator/test_utils.ts +37 -0
- package/src/tx_validator/tx_validator_factory.ts +4 -8
|
@@ -3,9 +3,9 @@ import { type PublicCallRequest } from '@aztec/circuits.js';
|
|
|
3
3
|
import { type ContractDataSource } from '@aztec/types/contracts';
|
|
4
4
|
export declare class PhasesTxValidator implements TxValidator<Tx> {
|
|
5
5
|
#private;
|
|
6
|
-
private contractDataSource;
|
|
7
6
|
private setupAllowList;
|
|
8
|
-
|
|
7
|
+
private contractDataSource;
|
|
8
|
+
constructor(contracts: ContractDataSource, setupAllowList: AllowedFunction[]);
|
|
9
9
|
validateTxs(txs: Tx[]): Promise<[validTxs: Tx[], invalidTxs: Tx[]]>;
|
|
10
10
|
isOnAllowList(publicCall: PublicCallRequest, allowList: AllowedFunction[]): Promise<boolean>;
|
|
11
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phases_validator.d.ts","sourceRoot":"","sources":["../../src/tx_validator/phases_validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG5D,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,qBAAa,iBAAkB,YAAW,WAAW,CAAC,EAAE,CAAC;;
|
|
1
|
+
{"version":3,"file":"phases_validator.d.ts","sourceRoot":"","sources":["../../src/tx_validator/phases_validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG5D,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,qBAAa,iBAAkB,YAAW,WAAW,CAAC,EAAE,CAAC;;IAIZ,OAAO,CAAC,cAAc;IAFjE,OAAO,CAAC,kBAAkB,CAA8B;gBAE5C,SAAS,EAAE,kBAAkB,EAAU,cAAc,EAAE,eAAe,EAAE;IAI9E,WAAW,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;IA6CnE,aAAa,CAAC,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CAmCnG"}
|
|
@@ -2,24 +2,29 @@ var _PhasesTxValidator_instances, _PhasesTxValidator_log, _PhasesTxValidator_val
|
|
|
2
2
|
import { __classPrivateFieldGet } from "tslib";
|
|
3
3
|
import { Tx } from '@aztec/circuit-types';
|
|
4
4
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
5
|
-
import { AbstractPhaseManager, PublicKernelPhase } from '@aztec/simulator';
|
|
5
|
+
import { AbstractPhaseManager, ContractsDataSourcePublicDB, PublicKernelPhase } from '@aztec/simulator';
|
|
6
6
|
export class PhasesTxValidator {
|
|
7
|
-
constructor(
|
|
7
|
+
constructor(contracts, setupAllowList) {
|
|
8
8
|
_PhasesTxValidator_instances.add(this);
|
|
9
|
-
this.contractDataSource = contractDataSource;
|
|
10
9
|
this.setupAllowList = setupAllowList;
|
|
11
10
|
_PhasesTxValidator_log.set(this, createDebugLogger('aztec:sequencer:tx_validator:tx_phases'));
|
|
11
|
+
this.contractDataSource = new ContractsDataSourcePublicDB(contracts);
|
|
12
12
|
}
|
|
13
13
|
async validateTxs(txs) {
|
|
14
14
|
const validTxs = [];
|
|
15
15
|
const invalidTxs = [];
|
|
16
16
|
for (const tx of txs) {
|
|
17
|
+
// TODO(@spalladino): We add this just to handle public authwit-check calls during setup
|
|
18
|
+
// which are needed for public FPC flows, but fail if the account contract hasnt been deployed yet,
|
|
19
|
+
// which is what we're trying to do as part of the current txs.
|
|
20
|
+
await this.contractDataSource.addNewContracts(tx);
|
|
17
21
|
if (await __classPrivateFieldGet(this, _PhasesTxValidator_instances, "m", _PhasesTxValidator_validateTx).call(this, tx)) {
|
|
18
22
|
validTxs.push(tx);
|
|
19
23
|
}
|
|
20
24
|
else {
|
|
21
25
|
invalidTxs.push(tx);
|
|
22
26
|
}
|
|
27
|
+
await this.contractDataSource.removeNewContracts(tx);
|
|
23
28
|
}
|
|
24
29
|
return Promise.resolve([validTxs, invalidTxs]);
|
|
25
30
|
}
|
|
@@ -27,17 +32,17 @@ export class PhasesTxValidator {
|
|
|
27
32
|
if (publicCall.isEmpty()) {
|
|
28
33
|
return true;
|
|
29
34
|
}
|
|
30
|
-
const { contractAddress,
|
|
35
|
+
const { contractAddress, functionSelector } = publicCall;
|
|
31
36
|
// do these checks first since they don't require the contract class
|
|
32
37
|
for (const entry of allowList) {
|
|
33
38
|
if (!('address' in entry)) {
|
|
34
39
|
continue;
|
|
35
40
|
}
|
|
36
|
-
if (contractAddress.equals(entry.address) && entry.selector.equals(
|
|
41
|
+
if (contractAddress.equals(entry.address) && entry.selector.equals(functionSelector)) {
|
|
37
42
|
return true;
|
|
38
43
|
}
|
|
39
44
|
}
|
|
40
|
-
const contractClass = await this.contractDataSource.
|
|
45
|
+
const contractClass = await this.contractDataSource.getContractInstance(contractAddress);
|
|
41
46
|
if (!contractClass) {
|
|
42
47
|
throw new Error(`Contract not found: ${publicCall.contractAddress.toString()}`);
|
|
43
48
|
}
|
|
@@ -45,7 +50,7 @@ export class PhasesTxValidator {
|
|
|
45
50
|
if (!('classId' in entry)) {
|
|
46
51
|
continue;
|
|
47
52
|
}
|
|
48
|
-
if (contractClass.contractClassId.equals(entry.classId) && entry.selector.equals(
|
|
53
|
+
if (contractClass.contractClassId.equals(entry.classId) && entry.selector.equals(functionSelector)) {
|
|
49
54
|
return true;
|
|
50
55
|
}
|
|
51
56
|
}
|
|
@@ -60,10 +65,10 @@ _PhasesTxValidator_log = new WeakMap(), _PhasesTxValidator_instances = new WeakS
|
|
|
60
65
|
const { [PublicKernelPhase.SETUP]: setupFns } = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx);
|
|
61
66
|
for (const setupFn of setupFns) {
|
|
62
67
|
if (!(await this.isOnAllowList(setupFn, this.setupAllowList))) {
|
|
63
|
-
__classPrivateFieldGet(this, _PhasesTxValidator_log, "f").warn(`Rejecting tx ${Tx.getHash(tx)} because it calls setup function not on allow list: ${setupFn.contractAddress}:${setupFn.
|
|
68
|
+
__classPrivateFieldGet(this, _PhasesTxValidator_log, "f").warn(`Rejecting tx ${Tx.getHash(tx)} because it calls setup function not on allow list: ${setupFn.contractAddress}:${setupFn.functionSelector}`);
|
|
64
69
|
return false;
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
return true;
|
|
68
73
|
};
|
|
69
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
74
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGhhc2VzX3ZhbGlkYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eF92YWxpZGF0b3IvcGhhc2VzX3ZhbGlkYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFBd0IsRUFBRSxFQUFvQixNQUFNLHNCQUFzQixDQUFDO0FBRWxGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSwyQkFBMkIsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBR3hHLE1BQU0sT0FBTyxpQkFBaUI7SUFJNUIsWUFBWSxTQUE2QixFQUFVLGNBQWlDOztRQUFqQyxtQkFBYyxHQUFkLGNBQWMsQ0FBbUI7UUFIcEYsaUNBQU8saUJBQWlCLENBQUMsd0NBQXdDLENBQUMsRUFBQztRQUlqRSxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSwyQkFBMkIsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBRUQsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFTO1FBQ3pCLE1BQU0sUUFBUSxHQUFTLEVBQUUsQ0FBQztRQUMxQixNQUFNLFVBQVUsR0FBUyxFQUFFLENBQUM7UUFFNUIsS0FBSyxNQUFNLEVBQUUsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNyQix3RkFBd0Y7WUFDeEYsbUdBQW1HO1lBQ25HLCtEQUErRDtZQUMvRCxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLENBQUM7WUFFbEQsSUFBSSxNQUFNLHVCQUFBLElBQUksbUVBQVksTUFBaEIsSUFBSSxFQUFhLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQy9CLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdEIs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
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Tx } from '@aztec/circuit-types';
|
|
2
|
+
import { type AztecAddress, type Fr, type FunctionSelector } from '@aztec/circuits.js';
|
|
3
|
+
export declare function patchNonRevertibleFn(tx: Tx, index: number, overrides: {
|
|
4
|
+
address?: AztecAddress;
|
|
5
|
+
selector: FunctionSelector;
|
|
6
|
+
args?: Fr[];
|
|
7
|
+
msgSender?: AztecAddress;
|
|
8
|
+
}): {
|
|
9
|
+
address: AztecAddress;
|
|
10
|
+
selector: FunctionSelector;
|
|
11
|
+
};
|
|
12
|
+
export declare function patchRevertibleFn(tx: Tx, index: number, overrides: {
|
|
13
|
+
address?: AztecAddress;
|
|
14
|
+
selector: FunctionSelector;
|
|
15
|
+
args?: Fr[];
|
|
16
|
+
msgSender?: AztecAddress;
|
|
17
|
+
}): {
|
|
18
|
+
address: AztecAddress;
|
|
19
|
+
selector: FunctionSelector;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=test_utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test_utils.d.ts","sourceRoot":"","sources":["../../src/tx_validator/test_utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,EAAE,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,MAAM,EACb,SAAS,EAAE;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAC;IAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,YAAY,CAAA;CAAE,GACvG;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAEvD;AAED,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,MAAM,EACb,SAAS,EAAE;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAC;IAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,YAAY,CAAA;CAAE,GACvG;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAEvD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function patchNonRevertibleFn(tx, index, overrides) {
|
|
2
|
+
return patchFn('endNonRevertibleData', tx, index, overrides);
|
|
3
|
+
}
|
|
4
|
+
export function patchRevertibleFn(tx, index, overrides) {
|
|
5
|
+
return patchFn('end', tx, index, overrides);
|
|
6
|
+
}
|
|
7
|
+
function patchFn(where, tx, index, overrides) {
|
|
8
|
+
const fn = tx.enqueuedPublicFunctionCalls.at(-1 * index - 1);
|
|
9
|
+
fn.contractAddress = overrides.address ?? fn.contractAddress;
|
|
10
|
+
fn.functionSelector = overrides.selector;
|
|
11
|
+
fn.args = overrides.args ?? fn.args;
|
|
12
|
+
fn.callContext.msgSender = overrides.msgSender ?? fn.callContext.msgSender;
|
|
13
|
+
tx.data.forPublic[where].publicCallStack[index] = fn.toCallRequest();
|
|
14
|
+
return {
|
|
15
|
+
address: fn.contractAddress,
|
|
16
|
+
selector: fn.functionSelector,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF91dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eF92YWxpZGF0b3IvdGVzdF91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxNQUFNLFVBQVUsb0JBQW9CLENBQ2xDLEVBQU0sRUFDTixLQUFhLEVBQ2IsU0FBd0c7SUFFeEcsT0FBTyxPQUFPLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQztBQUMvRCxDQUFDO0FBRUQsTUFBTSxVQUFVLGlCQUFpQixDQUMvQixFQUFNLEVBQ04sS0FBYSxFQUNiLFNBQXdHO0lBRXhHLE9BQU8sT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRCxTQUFTLE9BQU8sQ0FDZCxLQUFxQyxFQUNyQyxFQUFNLEVBQ04sS0FBYSxFQUNiLFNBQXdHO0lBRXhHLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBRSxDQUFDO0lBQzlELEVBQUUsQ0FBQyxlQUFlLEdBQUcsU0FBUyxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUMsZUFBZSxDQUFDO0lBQzdELEVBQUUsQ0FBQyxnQkFBZ0IsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDO0lBQ3pDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsU0FBUyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDO0lBQ3BDLEVBQUUsQ0FBQyxXQUFXLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUM7SUFDM0UsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUV0RSxPQUFPO1FBQ0wsT0FBTyxFQUFFLEVBQUUsQ0FBQyxlQUFlO1FBQzNCLFFBQVEsRUFBRSxFQUFFLENBQUMsZ0JBQWdCO0tBQzlCLENBQUM7QUFDSixDQUFDIn0=
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { type AllowedFunction, type ProcessedTx, type Tx, type TxValidator } from '@aztec/circuit-types';
|
|
2
|
-
import { type
|
|
2
|
+
import { type GlobalVariables } from '@aztec/circuits.js';
|
|
3
3
|
import { type ContractDataSource } from '@aztec/types/contracts';
|
|
4
4
|
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
5
5
|
export declare class TxValidatorFactory {
|
|
6
6
|
private merkleTreeDb;
|
|
7
7
|
private contractDataSource;
|
|
8
|
-
|
|
9
|
-
constructor(merkleTreeDb: MerkleTreeOperations, contractDataSource: ContractDataSource, gasPortalAddress: EthAddress);
|
|
8
|
+
constructor(merkleTreeDb: MerkleTreeOperations, contractDataSource: ContractDataSource);
|
|
10
9
|
validatorForNewTxs(globalVariables: GlobalVariables, setupAllowList: AllowedFunction[]): TxValidator<Tx>;
|
|
11
10
|
validatorForProcessedTxs(): TxValidator<ProcessedTx>;
|
|
12
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tx_validator_factory.d.ts","sourceRoot":"","sources":["../../src/tx_validator/tx_validator_factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzG,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"tx_validator_factory.d.ts","sourceRoot":"","sources":["../../src/tx_validator/tx_validator_factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzG,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAQ/D,qBAAa,kBAAkB;IACjB,OAAO,CAAC,YAAY;IAAwB,OAAO,CAAC,kBAAkB;gBAA9D,YAAY,EAAE,oBAAoB,EAAU,kBAAkB,EAAE,kBAAkB;IAEtG,kBAAkB,CAAC,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC;IASxG,wBAAwB,IAAI,WAAW,CAAC,WAAW,CAAC;CAGrD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token';
|
|
2
2
|
import { WorldStateDB, WorldStatePublicDB } from '@aztec/simulator';
|
|
3
3
|
import { AggregateTxValidator } from './aggregate_tx_validator.js';
|
|
4
4
|
import { DoubleSpendTxValidator } from './double_spend_validator.js';
|
|
@@ -6,16 +6,15 @@ import { GasTxValidator } from './gas_validator.js';
|
|
|
6
6
|
import { MetadataTxValidator } from './metadata_validator.js';
|
|
7
7
|
import { PhasesTxValidator } from './phases_validator.js';
|
|
8
8
|
export class TxValidatorFactory {
|
|
9
|
-
constructor(merkleTreeDb, contractDataSource
|
|
9
|
+
constructor(merkleTreeDb, contractDataSource) {
|
|
10
10
|
this.merkleTreeDb = merkleTreeDb;
|
|
11
11
|
this.contractDataSource = contractDataSource;
|
|
12
|
-
this.gasPortalAddress = gasPortalAddress;
|
|
13
12
|
}
|
|
14
13
|
validatorForNewTxs(globalVariables, setupAllowList) {
|
|
15
|
-
return new AggregateTxValidator(new MetadataTxValidator(globalVariables), new DoubleSpendTxValidator(new WorldStateDB(this.merkleTreeDb)), new PhasesTxValidator(this.contractDataSource, setupAllowList), new GasTxValidator(new WorldStatePublicDB(this.merkleTreeDb),
|
|
14
|
+
return new AggregateTxValidator(new MetadataTxValidator(globalVariables), new DoubleSpendTxValidator(new WorldStateDB(this.merkleTreeDb)), new PhasesTxValidator(this.contractDataSource, setupAllowList), new GasTxValidator(new WorldStatePublicDB(this.merkleTreeDb), GasTokenAddress));
|
|
16
15
|
}
|
|
17
16
|
validatorForProcessedTxs() {
|
|
18
17
|
return new DoubleSpendTxValidator(new WorldStateDB(this.merkleTreeDb));
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhfdmFsaWRhdG9yX2ZhY3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHhfdmFsaWRhdG9yL3R4X3ZhbGlkYXRvcl9mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUN0RSxPQUFPLEVBQUUsWUFBWSxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFJcEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDbkUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDckUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzlELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTFELE1BQU0sT0FBTyxrQkFBa0I7SUFDN0IsWUFBb0IsWUFBa0MsRUFBVSxrQkFBc0M7UUFBbEYsaUJBQVksR0FBWixZQUFZLENBQXNCO1FBQVUsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtJQUFHLENBQUM7SUFFMUcsa0JBQWtCLENBQUMsZUFBZ0MsRUFBRSxjQUFpQztRQUNwRixPQUFPLElBQUksb0JBQW9CLENBQzdCLElBQUksbUJBQW1CLENBQUMsZUFBZSxDQUFDLEVBQ3hDLElBQUksc0JBQXNCLENBQUMsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLEVBQy9ELElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLGNBQWMsQ0FBQyxFQUM5RCxJQUFJLGNBQWMsQ0FBQyxJQUFJLGtCQUFrQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FDL0UsQ0FBQztJQUNKLENBQUM7SUFFRCx3QkFBd0I7UUFDdEIsT0FBTyxJQUFJLHNCQUFzQixDQUFDLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO0lBQ3pFLENBQUM7Q0FDRiJ9
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/sequencer-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": "./dest/index.js",
|
|
6
6
|
"typedocOptions": {
|
|
@@ -24,19 +24,19 @@
|
|
|
24
24
|
"test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@aztec/circuit-types": "0.
|
|
28
|
-
"@aztec/circuits.js": "0.
|
|
29
|
-
"@aztec/ethereum": "0.
|
|
30
|
-
"@aztec/foundation": "0.
|
|
31
|
-
"@aztec/l1-artifacts": "0.
|
|
32
|
-
"@aztec/merkle-tree": "0.
|
|
33
|
-
"@aztec/noir-contracts.js": "0.
|
|
34
|
-
"@aztec/noir-protocol-circuits-types": "0.
|
|
35
|
-
"@aztec/p2p": "0.
|
|
36
|
-
"@aztec/protocol-contracts": "0.
|
|
37
|
-
"@aztec/simulator": "0.
|
|
38
|
-
"@aztec/types": "0.
|
|
39
|
-
"@aztec/world-state": "0.
|
|
27
|
+
"@aztec/circuit-types": "0.42.0",
|
|
28
|
+
"@aztec/circuits.js": "0.42.0",
|
|
29
|
+
"@aztec/ethereum": "0.42.0",
|
|
30
|
+
"@aztec/foundation": "0.42.0",
|
|
31
|
+
"@aztec/l1-artifacts": "0.42.0",
|
|
32
|
+
"@aztec/merkle-tree": "0.42.0",
|
|
33
|
+
"@aztec/noir-contracts.js": "0.42.0",
|
|
34
|
+
"@aztec/noir-protocol-circuits-types": "0.42.0",
|
|
35
|
+
"@aztec/p2p": "0.42.0",
|
|
36
|
+
"@aztec/protocol-contracts": "0.42.0",
|
|
37
|
+
"@aztec/simulator": "0.42.0",
|
|
38
|
+
"@aztec/types": "0.42.0",
|
|
39
|
+
"@aztec/world-state": "0.42.0",
|
|
40
40
|
"@noir-lang/acvm_js": "portal:../../noir/packages/acvm_js",
|
|
41
41
|
"@noir-lang/types": "portal:../../noir/packages/types",
|
|
42
42
|
"lodash.chunk": "^4.2.0",
|
|
@@ -54,7 +54,7 @@ export class SequencerClient {
|
|
|
54
54
|
l2BlockSource,
|
|
55
55
|
l1ToL2MessageSource,
|
|
56
56
|
publicProcessorFactory,
|
|
57
|
-
new TxValidatorFactory(merkleTreeDb, contractDataSource
|
|
57
|
+
new TxValidatorFactory(merkleTreeDb, contractDataSource),
|
|
58
58
|
config,
|
|
59
59
|
);
|
|
60
60
|
|
package/src/config.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { type L1ContractAddresses, NULL_KEY } from '@aztec/ethereum';
|
|
|
4
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
5
|
import { EcdsaAccountContractArtifact } from '@aztec/noir-contracts.js/EcdsaAccount';
|
|
6
6
|
import { FPCContract } from '@aztec/noir-contracts.js/FPC';
|
|
7
|
-
import { GasTokenContract } from '@aztec/noir-contracts.js/GasToken';
|
|
8
7
|
import { SchnorrAccountContractArtifact } from '@aztec/noir-contracts.js/SchnorrAccount';
|
|
9
8
|
import { SchnorrHardcodedAccountContractArtifact } from '@aztec/noir-contracts.js/SchnorrHardcodedAccount';
|
|
10
9
|
import { SchnorrSingleKeyAccountContractArtifact } from '@aztec/noir-contracts.js/SchnorrSingleKeyAccount';
|
|
11
10
|
import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
|
|
11
|
+
import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token';
|
|
12
12
|
|
|
13
13
|
import { type Hex } from 'viem';
|
|
14
14
|
|
|
@@ -50,6 +50,7 @@ export function getConfigEnvVars(): SequencerClientConfig {
|
|
|
50
50
|
SEQ_MIN_TX_PER_BLOCK,
|
|
51
51
|
SEQ_ALLOWED_SETUP_FN,
|
|
52
52
|
SEQ_ALLOWED_TEARDOWN_FN,
|
|
53
|
+
SEQ_MAX_BLOCK_SIZE_IN_BYTES,
|
|
53
54
|
AVAILABILITY_ORACLE_CONTRACT_ADDRESS,
|
|
54
55
|
ROLLUP_CONTRACT_ADDRESS,
|
|
55
56
|
REGISTRY_CONTRACT_ADDRESS,
|
|
@@ -89,6 +90,7 @@ export function getConfigEnvVars(): SequencerClientConfig {
|
|
|
89
90
|
requiredConfirmations: SEQ_REQUIRED_CONFIRMATIONS ? +SEQ_REQUIRED_CONFIRMATIONS : 1,
|
|
90
91
|
l1BlockPublishRetryIntervalMS: SEQ_PUBLISH_RETRY_INTERVAL_MS ? +SEQ_PUBLISH_RETRY_INTERVAL_MS : 1_000,
|
|
91
92
|
transactionPollingIntervalMS: SEQ_TX_POLLING_INTERVAL_MS ? +SEQ_TX_POLLING_INTERVAL_MS : 1_000,
|
|
93
|
+
maxBlockSizeInBytes: SEQ_MAX_BLOCK_SIZE_IN_BYTES ? +SEQ_MAX_BLOCK_SIZE_IN_BYTES : undefined,
|
|
92
94
|
l1Contracts: addresses,
|
|
93
95
|
publisherPrivateKey,
|
|
94
96
|
maxTxsPerBlock: SEQ_MAX_TX_PER_BLOCK ? +SEQ_MAX_TX_PER_BLOCK : 32,
|
|
@@ -152,19 +154,16 @@ function getDefaultAllowedSetupFunctions(): AllowedFunction[] {
|
|
|
152
154
|
classId: getContractClassFromArtifact(EcdsaAccountContractArtifact).id,
|
|
153
155
|
selector: FunctionSelector.fromSignature('approve_public_authwit(Field)'),
|
|
154
156
|
},
|
|
155
|
-
|
|
156
|
-
// needed for native payments while they are not yet enshrined
|
|
157
|
+
// needed for claiming on the same tx as a spend
|
|
157
158
|
{
|
|
158
|
-
|
|
159
|
-
selector: FunctionSelector.fromSignature('
|
|
159
|
+
address: GasTokenAddress,
|
|
160
|
+
selector: FunctionSelector.fromSignature('_increase_public_balance((Field),Field)'),
|
|
160
161
|
},
|
|
161
|
-
|
|
162
162
|
// needed for private transfers via FPC
|
|
163
163
|
{
|
|
164
164
|
classId: getContractClassFromArtifact(TokenContractArtifact).id,
|
|
165
165
|
selector: FunctionSelector.fromSignature('_increase_public_balance((Field),Field)'),
|
|
166
166
|
},
|
|
167
|
-
|
|
168
167
|
{
|
|
169
168
|
classId: getContractClassFromArtifact(FPCContract.artifact).id,
|
|
170
169
|
selector: FunctionSelector.fromSignature('prepare_fee((Field),Field,(Field),Field)'),
|
|
@@ -174,17 +173,13 @@ function getDefaultAllowedSetupFunctions(): AllowedFunction[] {
|
|
|
174
173
|
|
|
175
174
|
function getDefaultAllowedTeardownFunctions(): AllowedFunction[] {
|
|
176
175
|
return [
|
|
177
|
-
{
|
|
178
|
-
classId: getContractClassFromArtifact(GasTokenContract.artifact).id,
|
|
179
|
-
selector: FunctionSelector.fromSignature('pay_fee(Field)'),
|
|
180
|
-
},
|
|
181
176
|
{
|
|
182
177
|
classId: getContractClassFromArtifact(FPCContract.artifact).id,
|
|
183
|
-
selector: FunctionSelector.fromSignature('
|
|
178
|
+
selector: FunctionSelector.fromSignature('pay_refund((Field),Field,(Field))'),
|
|
184
179
|
},
|
|
185
180
|
{
|
|
186
181
|
classId: getContractClassFromArtifact(FPCContract.artifact).id,
|
|
187
|
-
selector: FunctionSelector.fromSignature('
|
|
182
|
+
selector: FunctionSelector.fromSignature('pay_refund_with_shielded_rebate(Field,(Field),Field)'),
|
|
188
183
|
},
|
|
189
184
|
];
|
|
190
185
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type L2Block } from '@aztec/circuit-types';
|
|
2
2
|
import { type L1PublishStats } from '@aztec/circuit-types/stats';
|
|
3
|
+
import { type Fr, type Proof } from '@aztec/circuits.js';
|
|
3
4
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { serializeToBuffer } from '@aztec/foundation/serialize';
|
|
4
6
|
import { InterruptibleSleep } from '@aztec/foundation/sleep';
|
|
5
7
|
|
|
6
8
|
import pick from 'lodash.pick';
|
|
@@ -91,6 +93,8 @@ export type L1ProcessArgs = {
|
|
|
91
93
|
archive: Buffer;
|
|
92
94
|
/** L2 block body. */
|
|
93
95
|
body: Buffer;
|
|
96
|
+
/** Aggregation object needed to verify the proof */
|
|
97
|
+
aggregationObject: Buffer;
|
|
94
98
|
/** Root rollup proof of the L2 block. */
|
|
95
99
|
proof: Buffer;
|
|
96
100
|
};
|
|
@@ -118,7 +122,7 @@ export class L1Publisher implements L2BlockReceiver {
|
|
|
118
122
|
* @param block - L2 block to publish.
|
|
119
123
|
* @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise.
|
|
120
124
|
*/
|
|
121
|
-
public async processL2Block(block: L2Block): Promise<boolean> {
|
|
125
|
+
public async processL2Block(block: L2Block, aggregationObject: Fr[], proof: Proof): Promise<boolean> {
|
|
122
126
|
// TODO(#4148) Remove this block number check, it's here because we don't currently have proper genesis state on the contract
|
|
123
127
|
const lastArchive = block.header.lastArchive.root.toBuffer();
|
|
124
128
|
if (block.number != 1 && !(await this.checkLastArchiveHash(lastArchive))) {
|
|
@@ -166,7 +170,8 @@ export class L1Publisher implements L2BlockReceiver {
|
|
|
166
170
|
header: block.header.toBuffer(),
|
|
167
171
|
archive: block.archive.root.toBuffer(),
|
|
168
172
|
body: encodedBody,
|
|
169
|
-
|
|
173
|
+
aggregationObject: serializeToBuffer(aggregationObject),
|
|
174
|
+
proof: proof.withoutPublicInputs(),
|
|
170
175
|
};
|
|
171
176
|
|
|
172
177
|
// Process block
|
|
@@ -242,6 +247,7 @@ export class L1Publisher implements L2BlockReceiver {
|
|
|
242
247
|
private async sendPublishTx(encodedBody: Buffer): Promise<string | undefined> {
|
|
243
248
|
while (!this.interrupted) {
|
|
244
249
|
try {
|
|
250
|
+
this.log.info(`TxEffects size=${encodedBody.length} bytes`);
|
|
245
251
|
return await this.txSender.sendPublishTx(encodedBody);
|
|
246
252
|
} catch (err) {
|
|
247
253
|
this.log.error(`TxEffects publish failed`, err);
|
|
@@ -145,6 +145,7 @@ export class ViemTxSender implements L1PublisherTxSender {
|
|
|
145
145
|
const args = [
|
|
146
146
|
`0x${encodedData.header.toString('hex')}`,
|
|
147
147
|
`0x${encodedData.archive.toString('hex')}`,
|
|
148
|
+
`0x${encodedData.aggregationObject.toString('hex')}`,
|
|
148
149
|
`0x${encodedData.proof.toString('hex')}`,
|
|
149
150
|
] as const;
|
|
150
151
|
|
package/src/receiver.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type L2Block } from '@aztec/circuit-types';
|
|
2
|
+
import type { Fr, Proof } from '@aztec/circuits.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Given the necessary rollup data, verifies it, and updates the underlying state accordingly to advance the state of the system.
|
|
@@ -8,6 +9,8 @@ export interface L2BlockReceiver {
|
|
|
8
9
|
/**
|
|
9
10
|
* Receive and L2 block and process it, returns true if successful.
|
|
10
11
|
* @param l2BlockData - L2 block to process.
|
|
12
|
+
* @param aggregationObject - The aggregation object for the block's proof.
|
|
13
|
+
* @param proof - The proof for the block.
|
|
11
14
|
*/
|
|
12
|
-
processL2Block(l2BlockData: L2Block): Promise<boolean>;
|
|
15
|
+
processL2Block(l2BlockData: L2Block, aggregationObject: Fr[], proof: Proof): Promise<boolean>;
|
|
13
16
|
}
|
|
@@ -6,9 +6,14 @@ import {
|
|
|
6
6
|
Tx,
|
|
7
7
|
type TxValidator,
|
|
8
8
|
} from '@aztec/circuit-types';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
type AllowedFunction,
|
|
11
|
+
BlockProofError,
|
|
12
|
+
type BlockProver,
|
|
13
|
+
PROVING_STATUS,
|
|
14
|
+
} from '@aztec/circuit-types/interfaces';
|
|
10
15
|
import { type L2BlockBuiltStats } from '@aztec/circuit-types/stats';
|
|
11
|
-
import { AztecAddress, EthAddress } from '@aztec/circuits.js';
|
|
16
|
+
import { AztecAddress, EthAddress, type Proof } from '@aztec/circuits.js';
|
|
12
17
|
import { Fr } from '@aztec/foundation/fields';
|
|
13
18
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
14
19
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
@@ -43,6 +48,7 @@ export class Sequencer {
|
|
|
43
48
|
private state = SequencerState.STOPPED;
|
|
44
49
|
private allowedFunctionsInSetup: AllowedFunction[] = [];
|
|
45
50
|
private allowedFunctionsInTeardown: AllowedFunction[] = [];
|
|
51
|
+
private maxBlockSizeInBytes: number = 1024 * 1024;
|
|
46
52
|
|
|
47
53
|
constructor(
|
|
48
54
|
private publisher: L1Publisher,
|
|
@@ -84,6 +90,9 @@ export class Sequencer {
|
|
|
84
90
|
if (config.allowedFunctionsInSetup) {
|
|
85
91
|
this.allowedFunctionsInSetup = config.allowedFunctionsInSetup;
|
|
86
92
|
}
|
|
93
|
+
if (config.maxBlockSizeInBytes) {
|
|
94
|
+
this.maxBlockSizeInBytes = config.maxBlockSizeInBytes;
|
|
95
|
+
}
|
|
87
96
|
// TODO(#5917) remove this. it is no longer needed since we don't need to whitelist functions in teardown
|
|
88
97
|
if (config.allowedFunctionsInTeardown) {
|
|
89
98
|
this.allowedFunctionsInTeardown = config.allowedFunctionsInTeardown;
|
|
@@ -186,10 +195,18 @@ export class Sequencer {
|
|
|
186
195
|
);
|
|
187
196
|
|
|
188
197
|
// TODO: It should be responsibility of the P2P layer to validate txs before passing them on here
|
|
189
|
-
const
|
|
198
|
+
const allValidTxs = await this.takeValidTxs(
|
|
190
199
|
pendingTxs,
|
|
191
200
|
this.txValidatorFactory.validatorForNewTxs(newGlobalVariables, this.allowedFunctionsInSetup),
|
|
192
201
|
);
|
|
202
|
+
|
|
203
|
+
// TODO: We are taking the size of the tx from private-land, but we should be doing this after running
|
|
204
|
+
// public functions. Only reason why we do it here now is because the public processor and orchestrator
|
|
205
|
+
// are set up such that they require knowing the total number of txs in advance. Still, main reason for
|
|
206
|
+
// exceeding max block size in bytes is contract class registration, which happens in private-land. This
|
|
207
|
+
// may break if we start emitting lots of log data from public-land.
|
|
208
|
+
const validTxs = this.takeTxsWithinMaxSize(allValidTxs);
|
|
209
|
+
|
|
193
210
|
if (validTxs.length < this.minTxsPerBLock) {
|
|
194
211
|
return;
|
|
195
212
|
}
|
|
@@ -205,16 +222,15 @@ export class Sequencer {
|
|
|
205
222
|
// We create a fresh processor each time to reset any cached state (eg storage writes)
|
|
206
223
|
const processor = await this.publicProcessorFactory.create(historicalHeader, newGlobalVariables);
|
|
207
224
|
|
|
208
|
-
const emptyTx = processor.makeEmptyProcessedTx();
|
|
209
|
-
|
|
210
225
|
const blockBuildingTimer = new Timer();
|
|
211
226
|
|
|
212
227
|
// We must initialise the block to be a power of 2 in size
|
|
213
228
|
const numRealTxs = validTxs.length;
|
|
214
229
|
const pow2 = Math.log2(numRealTxs);
|
|
230
|
+
// TODO turn this back into a Math.ceil once we can pad blocks to the next-power-of-2 with empty txs
|
|
215
231
|
const totalTxs = 2 ** Math.ceil(pow2);
|
|
216
232
|
const blockSize = Math.max(2, totalTxs);
|
|
217
|
-
const blockTicket = await this.prover.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages
|
|
233
|
+
const blockTicket = await this.prover.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages);
|
|
218
234
|
|
|
219
235
|
const [publicProcessorDuration, [processedTxs, failedTxs]] = await elapsed(() =>
|
|
220
236
|
processor.process(validTxs, blockSize, this.prover, this.txValidatorFactory.validatorForProcessedTxs()),
|
|
@@ -247,8 +263,7 @@ export class Sequencer {
|
|
|
247
263
|
await assertBlockHeight();
|
|
248
264
|
|
|
249
265
|
// Block is proven, now finalise and publish!
|
|
250
|
-
const
|
|
251
|
-
const block = blockResult.block;
|
|
266
|
+
const { block, aggregationObject, proof } = await this.prover.finaliseBlock();
|
|
252
267
|
|
|
253
268
|
await assertBlockHeight();
|
|
254
269
|
|
|
@@ -260,9 +275,14 @@ export class Sequencer {
|
|
|
260
275
|
...block.getStats(),
|
|
261
276
|
} satisfies L2BlockBuiltStats);
|
|
262
277
|
|
|
263
|
-
await this.publishL2Block(block);
|
|
278
|
+
await this.publishL2Block(block, aggregationObject, proof);
|
|
264
279
|
this.log.info(`Submitted rollup block ${block.number} with ${processedTxs.length} transactions`);
|
|
265
280
|
} catch (err) {
|
|
281
|
+
if (BlockProofError.isBlockProofError(err)) {
|
|
282
|
+
const txHashes = err.txHashes.filter(h => !h.isZero());
|
|
283
|
+
this.log.warn(`Proving block failed, removing ${txHashes.length} txs from pool`);
|
|
284
|
+
await this.p2pClient.deleteTxs(txHashes);
|
|
285
|
+
}
|
|
266
286
|
this.log.error(`Rolling back world state DB due to error assembling block`, (err as any).stack);
|
|
267
287
|
// Cancel any further proving on the block
|
|
268
288
|
this.prover?.cancelBlock();
|
|
@@ -274,10 +294,10 @@ export class Sequencer {
|
|
|
274
294
|
* Publishes the L2Block to the rollup contract.
|
|
275
295
|
* @param block - The L2Block to be published.
|
|
276
296
|
*/
|
|
277
|
-
protected async publishL2Block(block: L2Block) {
|
|
297
|
+
protected async publishL2Block(block: L2Block, aggregationObject: Fr[], proof: Proof) {
|
|
278
298
|
// Publishes new block to the network and awaits the tx to be mined
|
|
279
299
|
this.state = SequencerState.PUBLISHING_BLOCK;
|
|
280
|
-
const publishedL2Block = await this.publisher.processL2Block(block);
|
|
300
|
+
const publishedL2Block = await this.publisher.processL2Block(block, aggregationObject, proof);
|
|
281
301
|
if (publishedL2Block) {
|
|
282
302
|
this.lastPublishedBlock = block.number;
|
|
283
303
|
} else {
|
|
@@ -295,6 +315,26 @@ export class Sequencer {
|
|
|
295
315
|
return valid.slice(0, this.maxTxsPerBlock);
|
|
296
316
|
}
|
|
297
317
|
|
|
318
|
+
protected takeTxsWithinMaxSize(txs: Tx[]): Tx[] {
|
|
319
|
+
const maxSize = this.maxBlockSizeInBytes;
|
|
320
|
+
let totalSize = 0;
|
|
321
|
+
|
|
322
|
+
const toReturn: Tx[] = [];
|
|
323
|
+
for (const tx of txs) {
|
|
324
|
+
const txSize = tx.getStats().size - tx.proof.toBuffer().length;
|
|
325
|
+
if (totalSize + txSize > maxSize) {
|
|
326
|
+
this.log.warn(
|
|
327
|
+
`Dropping tx ${tx.getTxHash()} with size ${txSize} due to exceeding ${maxSize} block size limit (currently at ${totalSize})`,
|
|
328
|
+
);
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
toReturn.push(tx);
|
|
332
|
+
totalSize += txSize;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return toReturn;
|
|
336
|
+
}
|
|
337
|
+
|
|
298
338
|
/**
|
|
299
339
|
* Returns whether the previous block sent has been mined, and all dependencies have caught up with it.
|
|
300
340
|
* @returns Boolean indicating if our dependencies are synced to the latest block.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type Tx, type TxValidator } from '@aztec/circuit-types';
|
|
2
2
|
import { type AztecAddress, type Fr } from '@aztec/circuits.js';
|
|
3
3
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
|
+
import { GasTokenArtifact } from '@aztec/protocol-contracts/gas-token';
|
|
5
|
+
import { AbstractPhaseManager, PublicKernelPhase, computeFeePayerBalanceStorageSlot } from '@aztec/simulator';
|
|
4
6
|
|
|
5
7
|
/** Provides a view into public contract state */
|
|
6
8
|
export interface PublicStateSource {
|
|
@@ -11,12 +13,10 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
11
13
|
#log = createDebugLogger('aztec:sequencer:tx_validator:tx_gas');
|
|
12
14
|
#publicDataSource: PublicStateSource;
|
|
13
15
|
#gasTokenAddress: AztecAddress;
|
|
14
|
-
#requireFees: boolean;
|
|
15
16
|
|
|
16
|
-
constructor(publicDataSource: PublicStateSource, gasTokenAddress: AztecAddress
|
|
17
|
+
constructor(publicDataSource: PublicStateSource, gasTokenAddress: AztecAddress) {
|
|
17
18
|
this.#publicDataSource = publicDataSource;
|
|
18
19
|
this.#gasTokenAddress = gasTokenAddress;
|
|
19
|
-
this.#requireFees = requireFees;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
async validateTxs(txs: Tx[]): Promise<[validTxs: Tx[], invalidTxs: Tx[]]> {
|
|
@@ -34,9 +34,39 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
34
34
|
return [validTxs, invalidTxs];
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
#validateTxFee(
|
|
38
|
-
|
|
37
|
+
async #validateTxFee(tx: Tx): Promise<boolean> {
|
|
38
|
+
const feePayer = tx.data.feePayer;
|
|
39
|
+
// TODO(@spalladino) Eventually remove the is_zero condition as we should always charge fees to every tx
|
|
40
|
+
if (feePayer.isZero()) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Compute the maximum fee that this tx may pay, based on its gasLimits and maxFeePerGas
|
|
45
|
+
const feeLimit = tx.data.constants.txContext.gasSettings.getFeeLimit();
|
|
46
|
+
|
|
47
|
+
// Read current balance of the feePayer
|
|
48
|
+
const initialBalance = await this.#publicDataSource.storageRead(
|
|
49
|
+
this.#gasTokenAddress,
|
|
50
|
+
computeFeePayerBalanceStorageSlot(feePayer),
|
|
51
|
+
);
|
|
39
52
|
|
|
40
|
-
//
|
|
53
|
+
// If there is a claim in this tx that increases the fee payer balance in gas token, add it to balance
|
|
54
|
+
const { [PublicKernelPhase.SETUP]: setupFns } = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx);
|
|
55
|
+
const claimFunctionCall = setupFns.find(
|
|
56
|
+
fn =>
|
|
57
|
+
fn.contractAddress.equals(this.#gasTokenAddress) &&
|
|
58
|
+
fn.callContext.msgSender.equals(this.#gasTokenAddress) &&
|
|
59
|
+
fn.functionSelector.equals(GasTokenArtifact.functions.find(f => f.name === '_increase_public_balance')!) &&
|
|
60
|
+
fn.args[0].equals(feePayer) &&
|
|
61
|
+
!fn.callContext.isStaticCall &&
|
|
62
|
+
!fn.callContext.isDelegateCall,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const balance = claimFunctionCall ? initialBalance.add(claimFunctionCall.args[1]) : initialBalance;
|
|
66
|
+
if (balance.lt(feeLimit)) {
|
|
67
|
+
this.#log.info(`Rejecting transaction due to not enough fee payer balance`, { feePayer, balance, feeLimit });
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
41
71
|
}
|
|
42
72
|
}
|