@aztec/sequencer-client 0.0.0-test.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.
Files changed (110) hide show
  1. package/README.md +45 -0
  2. package/dest/client/index.d.ts +2 -0
  3. package/dest/client/index.d.ts.map +1 -0
  4. package/dest/client/index.js +1 -0
  5. package/dest/client/sequencer-client.d.ts +71 -0
  6. package/dest/client/sequencer-client.d.ts.map +1 -0
  7. package/dest/client/sequencer-client.js +117 -0
  8. package/dest/config.d.ts +29 -0
  9. package/dest/config.d.ts.map +1 -0
  10. package/dest/config.js +143 -0
  11. package/dest/global_variable_builder/global_builder.d.ts +32 -0
  12. package/dest/global_variable_builder/global_builder.d.ts.map +1 -0
  13. package/dest/global_variable_builder/global_builder.js +79 -0
  14. package/dest/global_variable_builder/index.d.ts +2 -0
  15. package/dest/global_variable_builder/index.d.ts.map +1 -0
  16. package/dest/global_variable_builder/index.js +1 -0
  17. package/dest/index.d.ts +8 -0
  18. package/dest/index.d.ts.map +1 -0
  19. package/dest/index.js +9 -0
  20. package/dest/publisher/config.d.ts +31 -0
  21. package/dest/publisher/config.d.ts.map +1 -0
  22. package/dest/publisher/config.js +35 -0
  23. package/dest/publisher/index.d.ts +2 -0
  24. package/dest/publisher/index.d.ts.map +1 -0
  25. package/dest/publisher/index.js +1 -0
  26. package/dest/publisher/sequencer-publisher-metrics.d.ts +25 -0
  27. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -0
  28. package/dest/publisher/sequencer-publisher-metrics.js +129 -0
  29. package/dest/publisher/sequencer-publisher.d.ts +152 -0
  30. package/dest/publisher/sequencer-publisher.d.ts.map +1 -0
  31. package/dest/publisher/sequencer-publisher.js +481 -0
  32. package/dest/sequencer/allowed.d.ts +3 -0
  33. package/dest/sequencer/allowed.d.ts.map +1 -0
  34. package/dest/sequencer/allowed.js +27 -0
  35. package/dest/sequencer/config.d.ts +2 -0
  36. package/dest/sequencer/config.d.ts.map +1 -0
  37. package/dest/sequencer/config.js +1 -0
  38. package/dest/sequencer/index.d.ts +4 -0
  39. package/dest/sequencer/index.d.ts.map +1 -0
  40. package/dest/sequencer/index.js +3 -0
  41. package/dest/sequencer/metrics.d.ts +24 -0
  42. package/dest/sequencer/metrics.d.ts.map +1 -0
  43. package/dest/sequencer/metrics.js +102 -0
  44. package/dest/sequencer/sequencer.d.ts +180 -0
  45. package/dest/sequencer/sequencer.d.ts.map +1 -0
  46. package/dest/sequencer/sequencer.js +623 -0
  47. package/dest/sequencer/timetable.d.ts +38 -0
  48. package/dest/sequencer/timetable.d.ts.map +1 -0
  49. package/dest/sequencer/timetable.js +110 -0
  50. package/dest/sequencer/utils.d.ts +48 -0
  51. package/dest/sequencer/utils.d.ts.map +1 -0
  52. package/dest/sequencer/utils.js +53 -0
  53. package/dest/slasher/factory.d.ts +7 -0
  54. package/dest/slasher/factory.d.ts.map +1 -0
  55. package/dest/slasher/factory.js +8 -0
  56. package/dest/slasher/index.d.ts +3 -0
  57. package/dest/slasher/index.d.ts.map +1 -0
  58. package/dest/slasher/index.js +2 -0
  59. package/dest/slasher/slasher_client.d.ts +75 -0
  60. package/dest/slasher/slasher_client.d.ts.map +1 -0
  61. package/dest/slasher/slasher_client.js +132 -0
  62. package/dest/test/index.d.ts +17 -0
  63. package/dest/test/index.d.ts.map +1 -0
  64. package/dest/test/index.js +10 -0
  65. package/dest/tx_validator/archive_cache.d.ts +14 -0
  66. package/dest/tx_validator/archive_cache.d.ts.map +1 -0
  67. package/dest/tx_validator/archive_cache.js +22 -0
  68. package/dest/tx_validator/gas_validator.d.ts +14 -0
  69. package/dest/tx_validator/gas_validator.d.ts.map +1 -0
  70. package/dest/tx_validator/gas_validator.js +78 -0
  71. package/dest/tx_validator/nullifier_cache.d.ts +16 -0
  72. package/dest/tx_validator/nullifier_cache.d.ts.map +1 -0
  73. package/dest/tx_validator/nullifier_cache.js +24 -0
  74. package/dest/tx_validator/phases_validator.d.ts +12 -0
  75. package/dest/tx_validator/phases_validator.d.ts.map +1 -0
  76. package/dest/tx_validator/phases_validator.js +80 -0
  77. package/dest/tx_validator/test_utils.d.ts +23 -0
  78. package/dest/tx_validator/test_utils.d.ts.map +1 -0
  79. package/dest/tx_validator/test_utils.js +26 -0
  80. package/dest/tx_validator/tx_validator_factory.d.ts +18 -0
  81. package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -0
  82. package/dest/tx_validator/tx_validator_factory.js +50 -0
  83. package/package.json +121 -0
  84. package/src/client/index.ts +1 -0
  85. package/src/client/sequencer-client.ts +219 -0
  86. package/src/config.ts +179 -0
  87. package/src/global_variable_builder/global_builder.ts +108 -0
  88. package/src/global_variable_builder/index.ts +1 -0
  89. package/src/index.ts +10 -0
  90. package/src/publisher/config.ts +75 -0
  91. package/src/publisher/index.ts +1 -0
  92. package/src/publisher/sequencer-publisher-metrics.ts +176 -0
  93. package/src/publisher/sequencer-publisher.ts +625 -0
  94. package/src/sequencer/allowed.ts +36 -0
  95. package/src/sequencer/config.ts +1 -0
  96. package/src/sequencer/index.ts +3 -0
  97. package/src/sequencer/metrics.ts +137 -0
  98. package/src/sequencer/sequencer.ts +759 -0
  99. package/src/sequencer/timetable.ts +123 -0
  100. package/src/sequencer/utils.ts +74 -0
  101. package/src/slasher/factory.ts +15 -0
  102. package/src/slasher/index.ts +2 -0
  103. package/src/slasher/slasher_client.ts +193 -0
  104. package/src/test/index.ts +20 -0
  105. package/src/tx_validator/archive_cache.ts +28 -0
  106. package/src/tx_validator/gas_validator.ts +101 -0
  107. package/src/tx_validator/nullifier_cache.ts +30 -0
  108. package/src/tx_validator/phases_validator.ts +98 -0
  109. package/src/tx_validator/test_utils.ts +48 -0
  110. package/src/tx_validator/tx_validator_factory.ts +120 -0
@@ -0,0 +1,16 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
3
+ import type { NullifierSource } from '@aztec/p2p';
4
+ import type { MerkleTreeReadOperations } from '@aztec/stdlib/interfaces/server';
5
+ /**
6
+ * Implements a nullifier source by checking a DB and an in-memory collection.
7
+ * Intended for validating transactions as they are added to a block.
8
+ */
9
+ export declare class NullifierCache implements NullifierSource {
10
+ private db;
11
+ nullifiers: Set<string>;
12
+ constructor(db: MerkleTreeReadOperations);
13
+ nullifiersExist(nullifiers: Buffer[]): Promise<boolean[]>;
14
+ addNullifiers(nullifiers: Buffer[]): void;
15
+ }
16
+ //# sourceMappingURL=nullifier_cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nullifier_cache.d.ts","sourceRoot":"","sources":["../../src/tx_validator/nullifier_cache.ts"],"names":[],"mappings":";;AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAGhF;;;GAGG;AACH,qBAAa,cAAe,YAAW,eAAe;IAGxC,OAAO,CAAC,EAAE;IAFtB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBAEJ,EAAE,EAAE,wBAAwB;IAInC,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAS/D,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE;CAK1C"}
@@ -0,0 +1,24 @@
1
+ import { MerkleTreeId } from '@aztec/stdlib/trees';
2
+ /**
3
+ * Implements a nullifier source by checking a DB and an in-memory collection.
4
+ * Intended for validating transactions as they are added to a block.
5
+ */ export class NullifierCache {
6
+ db;
7
+ nullifiers;
8
+ constructor(db){
9
+ this.db = db;
10
+ this.nullifiers = new Set();
11
+ }
12
+ async nullifiersExist(nullifiers) {
13
+ const cacheResults = nullifiers.map((n)=>this.nullifiers.has(n.toString()));
14
+ const toCheckDb = nullifiers.filter((_n, index)=>!cacheResults[index]);
15
+ const dbHits = await this.db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, toCheckDb);
16
+ let dbIndex = 0;
17
+ return nullifiers.map((_n, index)=>cacheResults[index] || dbHits[dbIndex++] !== undefined);
18
+ }
19
+ addNullifiers(nullifiers) {
20
+ for (const nullifier of nullifiers){
21
+ this.nullifiers.add(nullifier.toString());
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,12 @@
1
+ import type { ContractDataSource } from '@aztec/stdlib/contract';
2
+ import type { AllowedElement } from '@aztec/stdlib/interfaces/server';
3
+ import { type PublicExecutionRequest, Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
4
+ export declare class PhasesTxValidator implements TxValidator<Tx> {
5
+ #private;
6
+ private setupAllowList;
7
+ private contractDataSource;
8
+ constructor(contracts: ContractDataSource, setupAllowList: AllowedElement[]);
9
+ validateTx(tx: Tx): Promise<TxValidationResult>;
10
+ isOnAllowList(publicCall: PublicExecutionRequest, allowList: AllowedElement[]): Promise<boolean>;
11
+ }
12
+ //# sourceMappingURL=phases_validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phases_validator.d.ts","sourceRoot":"","sources":["../../src/tx_validator/phases_validator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EACL,KAAK,sBAAsB,EAC3B,EAAE,EAEF,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAE1B,qBAAa,iBAAkB,YAAW,WAAW,CAAC,EAAE,CAAC;;IAIZ,OAAO,CAAC,cAAc;IAFjE,OAAO,CAAC,kBAAkB,CAA8B;gBAE5C,SAAS,EAAE,kBAAkB,EAAU,cAAc,EAAE,cAAc,EAAE;IAI7E,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgC/C,aAAa,CAAC,UAAU,EAAE,sBAAsB,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CA6CvG"}
@@ -0,0 +1,80 @@
1
+ import { createLogger } from '@aztec/foundation/log';
2
+ import { ContractsDataSourcePublicDB, getExecutionRequestsByPhase } from '@aztec/simulator/server';
3
+ import { Tx, TxExecutionPhase } from '@aztec/stdlib/tx';
4
+ export class PhasesTxValidator {
5
+ setupAllowList;
6
+ #log;
7
+ contractDataSource;
8
+ constructor(contracts, setupAllowList){
9
+ this.setupAllowList = setupAllowList;
10
+ this.#log = createLogger('sequencer:tx_validator:tx_phases');
11
+ this.contractDataSource = new ContractsDataSourcePublicDB(contracts);
12
+ }
13
+ async validateTx(tx) {
14
+ try {
15
+ // TODO(@spalladino): We add this just to handle public authwit-check calls during setup
16
+ // which are needed for public FPC flows, but fail if the account contract hasnt been deployed yet,
17
+ // which is what we're trying to do as part of the current txs.
18
+ await this.contractDataSource.addNewContracts(tx);
19
+ if (!tx.data.forPublic) {
20
+ this.#log.debug(`Tx ${Tx.getHash(tx)} does not contain enqueued public functions. Skipping phases validation.`);
21
+ return {
22
+ result: 'valid'
23
+ };
24
+ }
25
+ const setupFns = getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP);
26
+ for (const setupFn of setupFns){
27
+ if (!await this.isOnAllowList(setupFn, this.setupAllowList)) {
28
+ this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} because it calls setup function not on allow list: ${setupFn.callContext.contractAddress}:${setupFn.callContext.functionSelector}`, {
29
+ allowList: this.setupAllowList
30
+ });
31
+ return {
32
+ result: 'invalid',
33
+ reason: [
34
+ 'Setup function not on allow list'
35
+ ]
36
+ };
37
+ }
38
+ }
39
+ return {
40
+ result: 'valid'
41
+ };
42
+ } finally{
43
+ this.contractDataSource.clearContractsForTx();
44
+ }
45
+ }
46
+ async isOnAllowList(publicCall, allowList) {
47
+ if (publicCall.isEmpty()) {
48
+ return true;
49
+ }
50
+ const { contractAddress, functionSelector } = publicCall.callContext;
51
+ // do these checks first since they don't require the contract class
52
+ for (const entry of allowList){
53
+ if ('address' in entry && !('selector' in entry)) {
54
+ if (contractAddress.equals(entry.address)) {
55
+ return true;
56
+ }
57
+ }
58
+ if ('address' in entry && 'selector' in entry) {
59
+ if (contractAddress.equals(entry.address) && entry.selector.equals(functionSelector)) {
60
+ return true;
61
+ }
62
+ }
63
+ const contractClass = await this.contractDataSource.getContractInstance(contractAddress);
64
+ if (!contractClass) {
65
+ throw new Error(`Contract not found: ${contractAddress}`);
66
+ }
67
+ if ('classId' in entry && !('selector' in entry)) {
68
+ if (contractClass.currentContractClassId.equals(entry.classId)) {
69
+ return true;
70
+ }
71
+ }
72
+ if ('classId' in entry && 'selector' in entry) {
73
+ if (contractClass.currentContractClassId.equals(entry.classId) && (entry.selector === undefined || entry.selector.equals(functionSelector))) {
74
+ return true;
75
+ }
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+ }
@@ -0,0 +1,23 @@
1
+ import type { Fr } from '@aztec/foundation/fields';
2
+ import type { FunctionSelector } from '@aztec/stdlib/abi';
3
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
4
+ import type { Tx } from '@aztec/stdlib/tx';
5
+ export declare function patchNonRevertibleFn(tx: Tx, index: number, overrides: {
6
+ address?: AztecAddress;
7
+ selector: FunctionSelector;
8
+ args?: Fr[];
9
+ msgSender?: AztecAddress;
10
+ }): Promise<{
11
+ address: AztecAddress;
12
+ selector: FunctionSelector;
13
+ }>;
14
+ export declare function patchRevertibleFn(tx: Tx, index: number, overrides: {
15
+ address?: AztecAddress;
16
+ selector: FunctionSelector;
17
+ args?: Fr[];
18
+ msgSender?: AztecAddress;
19
+ }): Promise<{
20
+ address: AztecAddress;
21
+ selector: FunctionSelector;
22
+ }>;
23
+ //# 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,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAE3C,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,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAEhE;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,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAEhE"}
@@ -0,0 +1,26 @@
1
+ import { computeVarArgsHash } from '@aztec/stdlib/hash';
2
+ export function patchNonRevertibleFn(tx, index, overrides) {
3
+ return patchFn('nonRevertibleAccumulatedData', tx, index, overrides);
4
+ }
5
+ export function patchRevertibleFn(tx, index, overrides) {
6
+ return patchFn('revertibleAccumulatedData', tx, index, overrides);
7
+ }
8
+ async function patchFn(where, tx, index, overrides) {
9
+ const fn = tx.enqueuedPublicFunctionCalls.at(-1 * index - 1);
10
+ fn.callContext.contractAddress = overrides.address ?? fn.callContext.contractAddress;
11
+ fn.callContext.functionSelector = overrides.selector;
12
+ fn.args = overrides.args ?? fn.args;
13
+ fn.callContext.msgSender = overrides.msgSender ?? fn.callContext.msgSender;
14
+ tx.enqueuedPublicFunctionCalls[index] = fn;
15
+ const request = tx.data.forPublic[where].publicCallRequests[index];
16
+ request.contractAddress = fn.callContext.contractAddress;
17
+ request.msgSender = fn.callContext.msgSender;
18
+ request.functionSelector = fn.callContext.functionSelector;
19
+ request.isStaticCall = fn.callContext.isStaticCall;
20
+ request.argsHash = await computeVarArgsHash(fn.args);
21
+ tx.data.forPublic[where].publicCallRequests[index] = request;
22
+ return {
23
+ address: fn.callContext.contractAddress,
24
+ selector: fn.callContext.functionSelector
25
+ };
26
+ }
@@ -0,0 +1,18 @@
1
+ import type { ContractDataSource } from '@aztec/stdlib/contract';
2
+ import type { GasFees } from '@aztec/stdlib/gas';
3
+ import type { AllowedElement, ClientProtocolCircuitVerifier, MerkleTreeReadOperations } from '@aztec/stdlib/interfaces/server';
4
+ import { GlobalVariables, type ProcessedTx, type Tx, type TxValidator } from '@aztec/stdlib/tx';
5
+ import { NullifierCache } from './nullifier_cache.js';
6
+ export declare function createValidatorForAcceptingTxs(db: MerkleTreeReadOperations, contractDataSource: ContractDataSource, verifier: ClientProtocolCircuitVerifier | undefined, { blockNumber, l1ChainId, setupAllowList, gasFees, skipFeeEnforcement, }: {
7
+ blockNumber: number;
8
+ l1ChainId: number;
9
+ setupAllowList: AllowedElement[];
10
+ gasFees: GasFees;
11
+ skipFeeEnforcement?: boolean;
12
+ }): TxValidator<Tx>;
13
+ export declare function createValidatorsForBlockBuilding(db: MerkleTreeReadOperations, contractDataSource: ContractDataSource, globalVariables: GlobalVariables, setupAllowList: AllowedElement[]): {
14
+ preprocessValidator: TxValidator<Tx>;
15
+ postprocessValidator: TxValidator<ProcessedTx>;
16
+ nullifierCache: NullifierCache;
17
+ };
18
+ //# sourceMappingURL=tx_validator_factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx_validator_factory.d.ts","sourceRoot":"","sources":["../../src/tx_validator/tx_validator_factory.ts"],"names":[],"mappings":"AAYA,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,EACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIhG,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,wBAAwB,EAC5B,kBAAkB,EAAE,kBAAkB,EACtC,QAAQ,EAAE,6BAA6B,GAAG,SAAS,EACnD,EACE,WAAW,EACX,SAAS,EACT,cAAc,EACd,OAAO,EACP,kBAAkB,GACnB,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,cAAc,EAAE,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,GACA,WAAW,CAAC,EAAE,CAAC,CAkBjB;AAED,wBAAgB,gCAAgC,CAC9C,EAAE,EAAE,wBAAwB,EAC5B,kBAAkB,EAAE,kBAAkB,EACtC,eAAe,EAAE,eAAe,EAChC,cAAc,EAAE,cAAc,EAAE,GAC/B;IACD,mBAAmB,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;IACrC,oBAAoB,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAC/C,cAAc,EAAE,cAAc,CAAC;CAChC,CAiBA"}
@@ -0,0 +1,50 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import { AggregateTxValidator, BlockHeaderTxValidator, DataTxValidator, DoubleSpendTxValidator, MetadataTxValidator, TxProofValidator } from '@aztec/p2p';
3
+ import { ProtocolContractAddress } from '@aztec/protocol-contracts';
4
+ import { readPublicState } from '@aztec/simulator/server';
5
+ import { ArchiveCache } from './archive_cache.js';
6
+ import { GasTxValidator } from './gas_validator.js';
7
+ import { NullifierCache } from './nullifier_cache.js';
8
+ import { PhasesTxValidator } from './phases_validator.js';
9
+ export function createValidatorForAcceptingTxs(db, contractDataSource, verifier, { blockNumber, l1ChainId, setupAllowList, gasFees, skipFeeEnforcement }) {
10
+ const validators = [
11
+ new DataTxValidator(),
12
+ new MetadataTxValidator(new Fr(l1ChainId), new Fr(blockNumber)),
13
+ new DoubleSpendTxValidator(new NullifierCache(db)),
14
+ new PhasesTxValidator(contractDataSource, setupAllowList),
15
+ new BlockHeaderTxValidator(new ArchiveCache(db))
16
+ ];
17
+ if (!skipFeeEnforcement) {
18
+ validators.push(new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, gasFees));
19
+ }
20
+ if (verifier) {
21
+ validators.push(new TxProofValidator(verifier));
22
+ }
23
+ return new AggregateTxValidator(...validators);
24
+ }
25
+ export function createValidatorsForBlockBuilding(db, contractDataSource, globalVariables, setupAllowList) {
26
+ const nullifierCache = new NullifierCache(db);
27
+ const archiveCache = new ArchiveCache(db);
28
+ const publicStateSource = new DatabasePublicStateSource(db);
29
+ return {
30
+ preprocessValidator: preprocessValidator(nullifierCache, archiveCache, publicStateSource, contractDataSource, globalVariables, setupAllowList),
31
+ postprocessValidator: postprocessValidator(nullifierCache),
32
+ nullifierCache
33
+ };
34
+ }
35
+ class DatabasePublicStateSource {
36
+ db;
37
+ constructor(db){
38
+ this.db = db;
39
+ }
40
+ storageRead(contractAddress, slot) {
41
+ return readPublicState(this.db, contractAddress, slot);
42
+ }
43
+ }
44
+ function preprocessValidator(nullifierCache, archiveCache, publicStateSource, contractDataSource, globalVariables, setupAllowList) {
45
+ // We don't include the TxProofValidator nor the DataTxValidator here because they are already checked by the time we get to block building.
46
+ return new AggregateTxValidator(new MetadataTxValidator(globalVariables.chainId, globalVariables.blockNumber), new DoubleSpendTxValidator(nullifierCache), new PhasesTxValidator(contractDataSource, setupAllowList), new GasTxValidator(publicStateSource, ProtocolContractAddress.FeeJuice, globalVariables.gasFees), new BlockHeaderTxValidator(archiveCache));
47
+ }
48
+ function postprocessValidator(nullifierCache) {
49
+ return new DoubleSpendTxValidator(nullifierCache);
50
+ }
package/package.json ADDED
@@ -0,0 +1,121 @@
1
+ {
2
+ "name": "@aztec/sequencer-client",
3
+ "version": "0.0.0-test.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./dest/index.js",
7
+ "./config": "./dest/config.js",
8
+ "./test": "./dest/test/index.js"
9
+ },
10
+ "typedocOptions": {
11
+ "entryPoints": [
12
+ "./src/index.ts"
13
+ ],
14
+ "name": "Sequencer Client",
15
+ "tsconfig": "./tsconfig.json"
16
+ },
17
+ "inherits": [
18
+ "../package.common.json"
19
+ ],
20
+ "scripts": {
21
+ "build": "yarn clean && tsc -b",
22
+ "build:dev": "tsc -b --watch",
23
+ "clean": "rm -rf ./dest .tsbuildinfo",
24
+ "formatting": "run -T prettier --check ./src && run -T eslint ./src",
25
+ "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
26
+ "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}",
27
+ "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"",
28
+ "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
29
+ },
30
+ "dependencies": {
31
+ "@aztec/aztec.js": "0.0.0-test.0",
32
+ "@aztec/bb-prover": "0.0.0-test.0",
33
+ "@aztec/blob-lib": "0.0.0-test.0",
34
+ "@aztec/blob-sink": "0.0.0-test.0",
35
+ "@aztec/constants": "0.0.0-test.0",
36
+ "@aztec/epoch-cache": "0.0.0-test.0",
37
+ "@aztec/ethereum": "0.0.0-test.0",
38
+ "@aztec/foundation": "0.0.0-test.0",
39
+ "@aztec/l1-artifacts": "0.0.0-test.0",
40
+ "@aztec/merkle-tree": "0.0.0-test.0",
41
+ "@aztec/noir-contracts.js": "0.0.0-test.0",
42
+ "@aztec/noir-protocol-circuits-types": "0.0.0-test.0",
43
+ "@aztec/p2p": "0.0.0-test.0",
44
+ "@aztec/protocol-contracts": "0.0.0-test.0",
45
+ "@aztec/prover-client": "0.0.0-test.0",
46
+ "@aztec/simulator": "0.0.0-test.0",
47
+ "@aztec/stdlib": "0.0.0-test.0",
48
+ "@aztec/telemetry-client": "0.0.0-test.0",
49
+ "@aztec/validator-client": "0.0.0-test.0",
50
+ "@aztec/world-state": "0.0.0-test.0",
51
+ "lodash.chunk": "^4.2.0",
52
+ "lodash.pick": "^4.4.0",
53
+ "tslib": "^2.4.0",
54
+ "viem": "2.22.8",
55
+ "@aztec/noir-acvm_js": "0.0.0-test.0",
56
+ "@aztec/noir-types": "0.0.0-test.0"
57
+ },
58
+ "devDependencies": {
59
+ "@aztec/archiver": "0.0.0-test.0",
60
+ "@aztec/kv-store": "0.0.0-test.0",
61
+ "@jest/globals": "^29.5.0",
62
+ "@types/jest": "^29.5.0",
63
+ "@types/levelup": "^5.1.2",
64
+ "@types/lodash.chunk": "^4.2.7",
65
+ "@types/lodash.pick": "^4.4.7",
66
+ "@types/memdown": "^3.0.0",
67
+ "@types/node": "^18.7.23",
68
+ "concurrently": "^7.6.0",
69
+ "eslint": "^8.37.0",
70
+ "express": "^4.21.1",
71
+ "jest": "^29.5.0",
72
+ "jest-mock-extended": "^3.0.3",
73
+ "levelup": "^5.1.1",
74
+ "memdown": "^6.1.1",
75
+ "prettier": "^2.8.7",
76
+ "ts-node": "^10.9.1",
77
+ "typescript": "^5.0.4"
78
+ },
79
+ "files": [
80
+ "dest",
81
+ "src",
82
+ "!*.test.*"
83
+ ],
84
+ "types": "./dest/index.d.ts",
85
+ "engines": {
86
+ "node": ">=18"
87
+ },
88
+ "jest": {
89
+ "extensionsToTreatAsEsm": [
90
+ ".ts"
91
+ ],
92
+ "transform": {
93
+ "^.+\\.tsx?$": [
94
+ "@swc/jest",
95
+ {
96
+ "jsc": {
97
+ "parser": {
98
+ "syntax": "typescript",
99
+ "decorators": true
100
+ },
101
+ "transform": {
102
+ "decoratorVersion": "2022-03"
103
+ }
104
+ }
105
+ }
106
+ ]
107
+ },
108
+ "moduleNameMapper": {
109
+ "^(\\.{1,2}/.*)\\.[cm]?js$": "$1"
110
+ },
111
+ "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$",
112
+ "rootDir": "./src",
113
+ "reporters": [
114
+ "default"
115
+ ],
116
+ "testTimeout": 120000,
117
+ "setupFiles": [
118
+ "../../foundation/src/jest/setup.mjs"
119
+ ]
120
+ }
121
+ }
@@ -0,0 +1 @@
1
+ export * from './sequencer-client.js';
@@ -0,0 +1,219 @@
1
+ import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
2
+ import { EpochCache } from '@aztec/epoch-cache';
3
+ import {
4
+ ForwarderContract,
5
+ GovernanceProposerContract,
6
+ RollupContract,
7
+ SlashingProposerContract,
8
+ createEthereumChain,
9
+ createL1Clients,
10
+ isAnvilTestChain,
11
+ } from '@aztec/ethereum';
12
+ import { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs';
13
+ import { EthAddress } from '@aztec/foundation/eth-address';
14
+ import { createLogger } from '@aztec/foundation/log';
15
+ import type { DateProvider } from '@aztec/foundation/timer';
16
+ import type { P2P } from '@aztec/p2p';
17
+ import { LightweightBlockBuilderFactory } from '@aztec/prover-client/block-builder';
18
+ import { PublicProcessorFactory } from '@aztec/simulator/server';
19
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
20
+ import type { L2BlockSource } from '@aztec/stdlib/block';
21
+ import type { ContractDataSource } from '@aztec/stdlib/contract';
22
+ import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
23
+ import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
24
+ import type { TelemetryClient } from '@aztec/telemetry-client';
25
+ import type { ValidatorClient } from '@aztec/validator-client';
26
+
27
+ import type { SequencerClientConfig } from '../config.js';
28
+ import { GlobalVariableBuilder } from '../global_variable_builder/index.js';
29
+ import { SequencerPublisher } from '../publisher/index.js';
30
+ import { Sequencer, type SequencerConfig } from '../sequencer/index.js';
31
+ import type { SlasherClient } from '../slasher/index.js';
32
+
33
+ /**
34
+ * Encapsulates the full sequencer and publisher.
35
+ */
36
+ export class SequencerClient {
37
+ constructor(protected sequencer: Sequencer) {}
38
+
39
+ /**
40
+ * Initializes and starts a new instance.
41
+ * @param config - Configuration for the sequencer, publisher, and L1 tx sender.
42
+ * @param p2pClient - P2P client that provides the txs to be sequenced.
43
+ * @param validatorClient - Validator client performs attestation duties when rotating proposers.
44
+ * @param worldStateSynchronizer - Provides access to world state.
45
+ * @param contractDataSource - Provides access to contract bytecode for public executions.
46
+ * @param l2BlockSource - Provides information about the previously published blocks.
47
+ * @param l1ToL2MessageSource - Provides access to L1 to L2 messages.
48
+ * @param prover - An instance of a block prover
49
+ * @param simulationProvider - An instance of a simulation provider
50
+ * @returns A new running instance.
51
+ */
52
+ public static async new(
53
+ config: SequencerClientConfig,
54
+ deps: {
55
+ validatorClient: ValidatorClient | undefined; // allowed to be undefined while we migrate
56
+ p2pClient: P2P;
57
+ worldStateSynchronizer: WorldStateSynchronizer;
58
+ slasherClient: SlasherClient;
59
+ contractDataSource: ContractDataSource;
60
+ l2BlockSource: L2BlockSource;
61
+ l1ToL2MessageSource: L1ToL2MessageSource;
62
+ telemetry: TelemetryClient;
63
+ publisher?: SequencerPublisher;
64
+ blobSinkClient?: BlobSinkClientInterface;
65
+ dateProvider: DateProvider;
66
+ epochCache?: EpochCache;
67
+ l1TxUtils?: L1TxUtilsWithBlobs;
68
+ },
69
+ ) {
70
+ const {
71
+ validatorClient,
72
+ p2pClient,
73
+ worldStateSynchronizer,
74
+ slasherClient,
75
+ contractDataSource,
76
+ l2BlockSource,
77
+ l1ToL2MessageSource,
78
+ telemetry: telemetryClient,
79
+ } = deps;
80
+ const { l1RpcUrls: rpcUrls, l1ChainId: chainId, publisherPrivateKey } = config;
81
+ const chain = createEthereumChain(rpcUrls, chainId);
82
+ const log = createLogger('sequencer-client');
83
+ const { publicClient, walletClient } = createL1Clients(rpcUrls, publisherPrivateKey, chain.chainInfo);
84
+ const l1TxUtils = deps.l1TxUtils ?? new L1TxUtilsWithBlobs(publicClient, walletClient, log, config);
85
+ const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString());
86
+ const [l1GenesisTime, slotDuration] = await Promise.all([
87
+ rollupContract.getL1GenesisTime(),
88
+ rollupContract.getSlotDuration(),
89
+ ] as const);
90
+ const forwarderContract =
91
+ config.customForwarderContractAddress && config.customForwarderContractAddress !== EthAddress.ZERO
92
+ ? new ForwarderContract(
93
+ publicClient,
94
+ config.customForwarderContractAddress.toString(),
95
+ config.l1Contracts.rollupAddress.toString(),
96
+ )
97
+ : await ForwarderContract.create(
98
+ walletClient.account.address,
99
+ walletClient,
100
+ publicClient,
101
+ log,
102
+ config.l1Contracts.rollupAddress.toString(),
103
+ );
104
+
105
+ const governanceProposerContract = new GovernanceProposerContract(
106
+ publicClient,
107
+ config.l1Contracts.governanceProposerAddress.toString(),
108
+ );
109
+ const slashingProposerAddress = await rollupContract.getSlashingProposerAddress();
110
+ const slashingProposerContract = new SlashingProposerContract(publicClient, slashingProposerAddress.toString());
111
+ const epochCache =
112
+ deps.epochCache ??
113
+ (await EpochCache.create(
114
+ config.l1Contracts.rollupAddress,
115
+ {
116
+ l1RpcUrls: rpcUrls,
117
+ l1ChainId: chainId,
118
+ viemPollingIntervalMS: config.viemPollingIntervalMS,
119
+ aztecSlotDuration: config.aztecSlotDuration,
120
+ ethereumSlotDuration: config.ethereumSlotDuration,
121
+ aztecEpochDuration: config.aztecEpochDuration,
122
+ },
123
+ { dateProvider: deps.dateProvider },
124
+ ));
125
+
126
+ const publisher =
127
+ deps.publisher ??
128
+ new SequencerPublisher(config, {
129
+ l1TxUtils,
130
+ telemetry: telemetryClient,
131
+ blobSinkClient: deps.blobSinkClient,
132
+ rollupContract,
133
+ epochCache,
134
+ forwarderContract,
135
+ governanceProposerContract,
136
+ slashingProposerContract,
137
+ });
138
+ const globalsBuilder = new GlobalVariableBuilder(config);
139
+
140
+ const publicProcessorFactory = new PublicProcessorFactory(contractDataSource, deps.dateProvider, telemetryClient);
141
+
142
+ const ethereumSlotDuration = config.ethereumSlotDuration;
143
+
144
+ // When running in anvil, assume we can post a tx up until the very last second of an L1 slot.
145
+ // Otherwise, assume we must have broadcasted the tx before the slot started (we use a default
146
+ // maxL1TxInclusionTimeIntoSlot of zero) to get the tx into that L1 slot.
147
+ // In theory, the L1 slot has an initial 4s phase where the block is propagated, so we could
148
+ // make it with a propagation time into slot equal to 4s. However, we prefer being conservative.
149
+ // See https://www.blocknative.com/blog/anatomy-of-a-slot#7 for more info.
150
+ const maxL1TxInclusionTimeIntoSlot =
151
+ config.maxL1TxInclusionTimeIntoSlot ?? isAnvilTestChain(config.l1ChainId) ? ethereumSlotDuration : 0;
152
+
153
+ const l1Constants = {
154
+ l1GenesisTime,
155
+ slotDuration: Number(slotDuration),
156
+ ethereumSlotDuration,
157
+ };
158
+
159
+ const sequencer = new Sequencer(
160
+ publisher,
161
+ validatorClient,
162
+ globalsBuilder,
163
+ p2pClient,
164
+ worldStateSynchronizer,
165
+ slasherClient,
166
+ new LightweightBlockBuilderFactory(telemetryClient),
167
+ l2BlockSource,
168
+ l1ToL2MessageSource,
169
+ publicProcessorFactory,
170
+ contractDataSource,
171
+ l1Constants,
172
+ deps.dateProvider,
173
+ { ...config, maxL1TxInclusionTimeIntoSlot },
174
+ telemetryClient,
175
+ );
176
+ await validatorClient?.start();
177
+ await sequencer.start();
178
+ return new SequencerClient(sequencer);
179
+ }
180
+
181
+ /**
182
+ * Updates sequencer config.
183
+ * @param config - New parameters.
184
+ */
185
+ public updateSequencerConfig(config: SequencerConfig) {
186
+ return this.sequencer.updateConfig(config);
187
+ }
188
+
189
+ /**
190
+ * Stops the sequencer from processing new txs.
191
+ */
192
+ public async stop() {
193
+ await this.sequencer.stop();
194
+ }
195
+
196
+ /** Forces the sequencer to bypass all time and tx count checks for the next block and build anyway. */
197
+ public flush() {
198
+ this.sequencer.flush();
199
+ }
200
+
201
+ /**
202
+ * Restarts the sequencer after being stopped.
203
+ */
204
+ public restart() {
205
+ this.sequencer.restart();
206
+ }
207
+
208
+ get coinbase(): EthAddress {
209
+ return this.sequencer.coinbase;
210
+ }
211
+
212
+ get feeRecipient(): AztecAddress {
213
+ return this.sequencer.feeRecipient;
214
+ }
215
+
216
+ get forwarderAddress(): EthAddress {
217
+ return this.sequencer.getForwarderAddress();
218
+ }
219
+ }