@aztec/sequencer-client 0.29.0 → 0.30.1
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.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +2 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +6 -2
- package/dest/sequencer/sequencer.d.ts +4 -15
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +19 -82
- package/dest/sequencer/tx_validator.d.ts +22 -0
- package/dest/sequencer/tx_validator.d.ts.map +1 -0
- package/dest/sequencer/tx_validator.js +125 -0
- package/package.json +13 -13
- package/src/client/sequencer-client.ts +1 -0
- package/src/config.ts +6 -0
- package/src/sequencer/sequencer.ts +23 -91
- package/src/sequencer/tx_validator.ts +189 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequencer-client.d.ts","sourceRoot":"","sources":["../../src/client/sequencer-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAK5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAKrD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA6BnE;;GAEG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,SAAS;IAExC;;;;;;;;;OASG;WACiB,GAAG,CACrB,MAAM,EAAE,qBAAqB,EAC7B,SAAS,EAAE,GAAG,EACd,sBAAsB,EAAE,sBAAsB,EAC9C,kBAAkB,EAAE,kBAAkB,EACtC,aAAa,EAAE,aAAa,EAC5B,mBAAmB,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"sequencer-client.d.ts","sourceRoot":"","sources":["../../src/client/sequencer-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAK5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAKrD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA6BnE;;GAEG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,SAAS;IAExC;;;;;;;;;OASG;WACiB,GAAG,CACrB,MAAM,EAAE,qBAAqB,EAC7B,SAAS,EAAE,GAAG,EACd,sBAAsB,EAAE,sBAAsB,EAC9C,kBAAkB,EAAE,kBAAkB,EACtC,aAAa,EAAE,aAAa,EAC5B,mBAAmB,EAAE,mBAAmB;IAuC1C;;;OAGG;IACI,qBAAqB,CAAC,MAAM,EAAE,eAAe;IAIpD;;OAEG;IACU,IAAI;IAIjB;;OAEG;IACI,OAAO;IAId,IAAI,QAAQ,4CAEX;IAED,IAAI,YAAY,8CAEf;CACF"}
|
|
@@ -55,7 +55,7 @@ export class SequencerClient {
|
|
|
55
55
|
const simulationProvider = await getSimulationProvider(config);
|
|
56
56
|
const blockBuilder = new SoloBlockBuilder(merkleTreeDb, getVerificationKeys(), new RealRollupCircuitSimulator(simulationProvider), new EmptyRollupProver());
|
|
57
57
|
const publicProcessorFactory = new PublicProcessorFactory(merkleTreeDb, contractDataSource, l1ToL2MessageSource, simulationProvider);
|
|
58
|
-
const sequencer = new Sequencer(publisher, globalsBuilder, p2pClient, worldStateSynchronizer, blockBuilder, l2BlockSource, l1ToL2MessageSource, publicProcessorFactory, config);
|
|
58
|
+
const sequencer = new Sequencer(publisher, globalsBuilder, p2pClient, worldStateSynchronizer, blockBuilder, l2BlockSource, l1ToL2MessageSource, publicProcessorFactory, config, config.l1Contracts.gasPortalAddress);
|
|
59
59
|
await sequencer.start();
|
|
60
60
|
return new SequencerClient(sequencer);
|
|
61
61
|
}
|
|
@@ -85,4 +85,4 @@ export class SequencerClient {
|
|
|
85
85
|
return this.sequencer.feeRecipient;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVuY2VyLWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGllbnQvc2VxdWVuY2VyLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUsxRCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVsQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUUxRSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUMvRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFNBQVMsRUFBbUIsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUMxRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDMUQsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFHcEUsTUFBTSxNQUFNLEdBQUcsaUJBQWlCLENBQUMsd0JBQXdCLENBQUMsQ0FBQztBQUUzRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLHFCQUFxQixDQUFDLE1BQTZCO0lBQ2hFLElBQUksTUFBTSxDQUFDLGNBQWMsSUFBSSxNQUFNLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUN6RCxJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzFELE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsb0JBQW9CLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUNqRSxNQUFNLENBQUMsd0JBQXdCLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO1lBQ3hELE9BQU8sSUFBSSxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsb0JBQW9CLEVBQUUsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3JGLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxNQUFNLENBQUMsNEJBQTRCLE1BQU0sQ0FBQyxjQUFjLHdCQUF3QixDQUFDLENBQUM7UUFDcEYsQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLENBQUMsNEJBQTRCLENBQUMsQ0FBQztJQUNyQyxPQUFPLElBQUksYUFBYSxFQUFFLENBQUM7QUFDN0IsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFDMUIsWUFBb0IsU0FBb0I7UUFBcEIsY0FBUyxHQUFULFNBQVMsQ0FBVztJQUFHLENBQUM7SUFFNUM7Ozs7Ozs7OztPQVNHO0lBQ0ksTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQ3JCLE1BQTZCLEVBQzdCLFNBQWMsRUFDZCxzQkFBOEMsRUFDOUMsa0JBQXNDLEVBQ3RDLGFBQTRCLEVBQzVCLG1CQUF3QztRQUV4QyxNQUFNLFNBQVMsR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDekMsTUFBTSxjQUFjLEdBQUcsd0JBQXdCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDeEQsTUFBTSxZQUFZLEdBQUcsc0JBQXNCLENBQUMsU0FBUyxFQUFFLENBQUM7UUFFeEQsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRS9ELE1BQU0sWUFBWSxHQUFHLElBQUksZ0JBQWdCLENBQ3ZDLFlBQVksRUFDWixtQkFBbUIsRUFBRSxFQUNyQixJQUFJLDBCQUEwQixDQUFDLGtCQUFrQixDQUFDLEVBQ2xELElBQUksaUJBQWlCLEVBQUUsQ0FDeEIsQ0FBQztRQUVGLE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxzQkFBc0IsQ0FDdkQsWUFBWSxFQUNaLGtCQUFrQixFQUNsQixtQkFBbUIsRUFDbkIsa0JBQWtCLENBQ25CLENBQUM7UUFFRixNQUFNLFNBQVMsR0FBRyxJQUFJLFNBQVMsQ0FDN0IsU0FBUyxFQUNULGNBQWMsRUFDZCxTQUFTLEVBQ1Qsc0JBQXNCLEVBQ3RCLFlBQVksRUFDWixhQUFhLEVBQ2IsbUJBQW1CLEVBQ25CLHNCQUFzQixFQUN0QixNQUFNLEVBQ04sTUFBTSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FDcEMsQ0FBQztRQUVGLE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3hCLE9BQU8sSUFBSSxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVEOzs7T0FHRztJQUNJLHFCQUFxQixDQUFDLE1BQXVCO1FBQ2xELElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRDs7T0FFRztJQUNJLE9BQU87UUFDWixJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCxJQUFJLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDO0lBQ2pDLENBQUM7SUFFRCxJQUFJLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDO0lBQ3JDLENBQUM7Q0FDRiJ9
|
package/dest/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,2BAA2B;AAC3B,KAAK,WAAW,GAAG;IACjB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,eAAe,GACjD,cAAc,GACd,eAAe,GACf,kBAAkB,GAClB,WAAW,CAAC;AAEd;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,2BAA2B;AAC3B,KAAK,WAAW,GAAG;IACjB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,eAAe,GACjD,cAAc,GACd,eAAe,GACf,kBAAkB,GAClB,WAAW,CAAC;AAEd;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CA6DxD"}
|
package/dest/config.js
CHANGED
|
@@ -5,7 +5,7 @@ import { EthAddress } from '@aztec/foundation/eth-address';
|
|
|
5
5
|
* Creates an instance of SequencerClientConfig out of environment variables using sensible defaults for integration testing if not set.
|
|
6
6
|
*/
|
|
7
7
|
export function getConfigEnvVars() {
|
|
8
|
-
const { SEQ_PUBLISHER_PRIVATE_KEY, ETHEREUM_HOST, CHAIN_ID, VERSION, API_KEY, SEQ_REQUIRED_CONFIRMATIONS, SEQ_PUBLISH_RETRY_INTERVAL_MS, SEQ_TX_POLLING_INTERVAL_MS, SEQ_MAX_TX_PER_BLOCK, SEQ_MIN_TX_PER_BLOCK, AVAILABILITY_ORACLE_CONTRACT_ADDRESS, ROLLUP_CONTRACT_ADDRESS, REGISTRY_CONTRACT_ADDRESS, INBOX_CONTRACT_ADDRESS, OUTBOX_CONTRACT_ADDRESS, COINBASE, FEE_RECIPIENT, ACVM_WORKING_DIRECTORY, ACVM_BINARY_PATH, } = process.env;
|
|
8
|
+
const { SEQ_PUBLISHER_PRIVATE_KEY, ETHEREUM_HOST, CHAIN_ID, VERSION, API_KEY, SEQ_REQUIRED_CONFIRMATIONS, SEQ_PUBLISH_RETRY_INTERVAL_MS, SEQ_TX_POLLING_INTERVAL_MS, SEQ_MAX_TX_PER_BLOCK, SEQ_MIN_TX_PER_BLOCK, AVAILABILITY_ORACLE_CONTRACT_ADDRESS, ROLLUP_CONTRACT_ADDRESS, REGISTRY_CONTRACT_ADDRESS, INBOX_CONTRACT_ADDRESS, OUTBOX_CONTRACT_ADDRESS, GAS_TOKEN_CONTRACT_ADDRESS, GAS_PORTAL_CONTRACT_ADDRESS, COINBASE, FEE_RECIPIENT, ACVM_WORKING_DIRECTORY, ACVM_BINARY_PATH, } = process.env;
|
|
9
9
|
const publisherPrivateKey = SEQ_PUBLISHER_PRIVATE_KEY
|
|
10
10
|
? `0x${SEQ_PUBLISHER_PRIVATE_KEY.replace('0x', '')}`
|
|
11
11
|
: NULL_KEY;
|
|
@@ -18,6 +18,10 @@ export function getConfigEnvVars() {
|
|
|
18
18
|
registryAddress: REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
19
19
|
inboxAddress: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
20
20
|
outboxAddress: OUTBOX_CONTRACT_ADDRESS ? EthAddress.fromString(OUTBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
21
|
+
gasTokenAddress: GAS_TOKEN_CONTRACT_ADDRESS ? EthAddress.fromString(GAS_TOKEN_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
22
|
+
gasPortalAddress: GAS_PORTAL_CONTRACT_ADDRESS
|
|
23
|
+
? EthAddress.fromString(GAS_PORTAL_CONTRACT_ADDRESS)
|
|
24
|
+
: EthAddress.ZERO,
|
|
21
25
|
};
|
|
22
26
|
return {
|
|
23
27
|
rpcUrl: ETHEREUM_HOST ? ETHEREUM_HOST : '',
|
|
@@ -38,4 +42,4 @@ export function getConfigEnvVars() {
|
|
|
38
42
|
acvmBinaryPath: ACVM_BINARY_PATH ? ACVM_BINARY_PATH : undefined,
|
|
39
43
|
};
|
|
40
44
|
}
|
|
41
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
45
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUF1QixRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUF5QjNEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQjtJQUM5QixNQUFNLEVBQ0oseUJBQXlCLEVBQ3pCLGFBQWEsRUFDYixRQUFRLEVBQ1IsT0FBTyxFQUNQLE9BQU8sRUFDUCwwQkFBMEIsRUFDMUIsNkJBQTZCLEVBQzdCLDBCQUEwQixFQUMxQixvQkFBb0IsRUFDcEIsb0JBQW9CLEVBQ3BCLG9DQUFvQyxFQUNwQyx1QkFBdUIsRUFDdkIseUJBQXlCLEVBQ3pCLHNCQUFzQixFQUN0Qix1QkFBdUIsRUFDdkIsMEJBQTBCLEVBQzFCLDJCQUEyQixFQUMzQixRQUFRLEVBQ1IsYUFBYSxFQUNiLHNCQUFzQixFQUN0QixnQkFBZ0IsR0FDakIsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDO0lBRWhCLE1BQU0sbUJBQW1CLEdBQVEseUJBQXlCO1FBQ3hELENBQUMsQ0FBQyxLQUFLLHlCQUF5QixDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUU7UUFDcEQsQ0FBQyxDQUFDLFFBQVEsQ0FBQztJQUNiLDJEQUEyRDtJQUMzRCxNQUFNLFNBQVMsR0FBd0I7UUFDckMseUJBQXlCLEVBQUUsb0NBQW9DO1lBQzdELENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLG9DQUFvQyxDQUFDO1lBQzdELENBQUMsQ0FBQyxVQUFVLENBQUMsSUFBSTtRQUNuQixhQUFhLEVBQUUsdUJBQXVCLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxD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
|
|
@@ -9,6 +9,7 @@ import { L1Publisher } from '../publisher/l1-publisher.js';
|
|
|
9
9
|
import { SequencerConfig } from './config.js';
|
|
10
10
|
import { ProcessedTx } from './processed_tx.js';
|
|
11
11
|
import { PublicProcessorFactory } from './public_processor.js';
|
|
12
|
+
import { TxValidator } from './tx_validator.js';
|
|
12
13
|
/**
|
|
13
14
|
* Sequencer client
|
|
14
15
|
* - Wins a period of time to become the sequencer (depending on finalized protocol).
|
|
@@ -27,6 +28,7 @@ export declare class Sequencer {
|
|
|
27
28
|
private l2BlockSource;
|
|
28
29
|
private l1ToL2MessageSource;
|
|
29
30
|
private publicProcessorFactory;
|
|
31
|
+
private gasPortalAddress;
|
|
30
32
|
private log;
|
|
31
33
|
private runningPromise?;
|
|
32
34
|
private pollingIntervalMs;
|
|
@@ -36,7 +38,7 @@ export declare class Sequencer {
|
|
|
36
38
|
private _feeRecipient;
|
|
37
39
|
private lastPublishedBlock;
|
|
38
40
|
private state;
|
|
39
|
-
constructor(publisher: L1Publisher, globalsBuilder: GlobalVariableBuilder, p2pClient: P2P, worldState: WorldStateSynchronizer, blockBuilder: BlockBuilder, l2BlockSource: L2BlockSource, l1ToL2MessageSource: L1ToL2MessageSource, publicProcessorFactory: PublicProcessorFactory, config?: SequencerConfig, log?: import("@aztec/foundation/log").DebugLogger);
|
|
41
|
+
constructor(publisher: L1Publisher, globalsBuilder: GlobalVariableBuilder, p2pClient: P2P, worldState: WorldStateSynchronizer, blockBuilder: BlockBuilder, l2BlockSource: L2BlockSource, l1ToL2MessageSource: L1ToL2MessageSource, publicProcessorFactory: PublicProcessorFactory, config?: SequencerConfig, gasPortalAddress?: EthAddress, log?: import("@aztec/foundation/log").DebugLogger);
|
|
40
42
|
/**
|
|
41
43
|
* Updates sequencer config.
|
|
42
44
|
* @param config - New parameters.
|
|
@@ -71,7 +73,7 @@ export declare class Sequencer {
|
|
|
71
73
|
* @param block - The L2Block to be published.
|
|
72
74
|
*/
|
|
73
75
|
protected publishL2Block(block: L2Block): Promise<void>;
|
|
74
|
-
protected takeValidTxs<T extends Tx | ProcessedTx>(txs: T[],
|
|
76
|
+
protected takeValidTxs<T extends Tx | ProcessedTx>(txs: T[], validator: TxValidator): Promise<T[]>;
|
|
75
77
|
/**
|
|
76
78
|
* Returns whether the previous block sent has been mined, and all dependencies have caught up with it.
|
|
77
79
|
* @returns Boolean indicating if our dependencies are synced to the latest block.
|
|
@@ -86,19 +88,6 @@ export declare class Sequencer {
|
|
|
86
88
|
* @returns The new block.
|
|
87
89
|
*/
|
|
88
90
|
protected buildBlock(txs: ProcessedTx[], l1ToL2Messages: Fr[], emptyTx: ProcessedTx, globalVariables: GlobalVariables): Promise<L2Block>;
|
|
89
|
-
/**
|
|
90
|
-
* Returns true if one of the tx nullifiers exist on the block being built.
|
|
91
|
-
* @param tx - The tx to test.
|
|
92
|
-
* @param thisBlockNullifiers - The nullifiers added so far.
|
|
93
|
-
*/
|
|
94
|
-
protected isTxDoubleSpendSameBlock(tx: Tx | ProcessedTx, thisBlockNullifiers: Set<bigint>): boolean;
|
|
95
|
-
/**
|
|
96
|
-
* Returns true if one of the transaction nullifiers exist.
|
|
97
|
-
* Nullifiers prevent double spends in a private context.
|
|
98
|
-
* @param tx - The transaction.
|
|
99
|
-
* @returns Whether this is a problematic double spend that the L1 contract would reject.
|
|
100
|
-
*/
|
|
101
|
-
protected isTxDoubleSpend(tx: Tx | ProcessedTx): Promise<boolean>;
|
|
102
91
|
get coinbase(): EthAddress;
|
|
103
92
|
get feeRecipient(): AztecAddress;
|
|
104
93
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,aAAa,EAAgB,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAErG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE/E,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAI9C,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAoB,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,9 @@ import { Fr } from '@aztec/foundation/fields';
|
|
|
5
5
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
6
6
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
7
7
|
import { Timer, elapsed } from '@aztec/foundation/timer';
|
|
8
|
+
import { WorldStatePublicDB } from '../simulator/public_executor.js';
|
|
8
9
|
import { ceilPowerOfTwo } from '../utils.js';
|
|
10
|
+
import { TxValidator } from './tx_validator.js';
|
|
9
11
|
/**
|
|
10
12
|
* Sequencer client
|
|
11
13
|
* - Wins a period of time to become the sequencer (depending on finalized protocol).
|
|
@@ -16,7 +18,7 @@ import { ceilPowerOfTwo } from '../utils.js';
|
|
|
16
18
|
* - Publishes L1 tx(s) to the rollup contract via RollupPublisher.
|
|
17
19
|
*/
|
|
18
20
|
export class Sequencer {
|
|
19
|
-
constructor(publisher, globalsBuilder, p2pClient, worldState, blockBuilder, l2BlockSource, l1ToL2MessageSource, publicProcessorFactory, config = {}, log = createDebugLogger('aztec:sequencer')) {
|
|
21
|
+
constructor(publisher, globalsBuilder, p2pClient, worldState, blockBuilder, l2BlockSource, l1ToL2MessageSource, publicProcessorFactory, config = {}, gasPortalAddress = EthAddress.ZERO, log = createDebugLogger('aztec:sequencer')) {
|
|
20
22
|
this.publisher = publisher;
|
|
21
23
|
this.globalsBuilder = globalsBuilder;
|
|
22
24
|
this.p2pClient = p2pClient;
|
|
@@ -25,6 +27,7 @@ export class Sequencer {
|
|
|
25
27
|
this.l2BlockSource = l2BlockSource;
|
|
26
28
|
this.l1ToL2MessageSource = l1ToL2MessageSource;
|
|
27
29
|
this.publicProcessorFactory = publicProcessorFactory;
|
|
30
|
+
this.gasPortalAddress = gasPortalAddress;
|
|
28
31
|
this.log = log;
|
|
29
32
|
this.pollingIntervalMs = 1000;
|
|
30
33
|
this.maxTxsPerBlock = 32;
|
|
@@ -136,8 +139,14 @@ export class Sequencer {
|
|
|
136
139
|
};
|
|
137
140
|
const newGlobalVariables = await this.globalsBuilder.buildGlobalVariables(new Fr(newBlockNumber), this._coinbase, this._feeRecipient);
|
|
138
141
|
// Filter out invalid txs
|
|
142
|
+
const trees = this.worldState.getLatest();
|
|
143
|
+
const txValidator = new TxValidator({
|
|
144
|
+
getNullifierIndex(nullifier) {
|
|
145
|
+
return trees.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
146
|
+
},
|
|
147
|
+
}, new WorldStatePublicDB(trees), this.gasPortalAddress, newGlobalVariables);
|
|
139
148
|
// TODO: It should be responsibility of the P2P layer to validate txs before passing them on here
|
|
140
|
-
const validTxs = await this.takeValidTxs(pendingTxs,
|
|
149
|
+
const validTxs = await this.takeValidTxs(pendingTxs, txValidator);
|
|
141
150
|
if (validTxs.length < this.minTxsPerBLock) {
|
|
142
151
|
return;
|
|
143
152
|
}
|
|
@@ -155,7 +164,7 @@ export class Sequencer {
|
|
|
155
164
|
// public functions emitting nullifiers would pass earlier check but fail here.
|
|
156
165
|
// Note that we're checking all nullifiers generated in the private execution twice,
|
|
157
166
|
// we could store the ones already checked and skip them here as an optimization.
|
|
158
|
-
const processedValidTxs = await this.takeValidTxs(processedTxs,
|
|
167
|
+
const processedValidTxs = await this.takeValidTxs(processedTxs, txValidator);
|
|
159
168
|
if (processedValidTxs.length === 0) {
|
|
160
169
|
this.log('No txs processed correctly to build block. Exiting');
|
|
161
170
|
return;
|
|
@@ -202,40 +211,13 @@ export class Sequencer {
|
|
|
202
211
|
throw new Error(`Failed to publish block`);
|
|
203
212
|
}
|
|
204
213
|
}
|
|
205
|
-
async takeValidTxs(txs,
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
for (const tx of txs) {
|
|
211
|
-
if (tx.data.constants.txContext.chainId.value !== globalVariables.chainId.value) {
|
|
212
|
-
this.log(`Deleting tx for incorrect chain ${tx.data.constants.txContext.chainId.toString()}, tx hash ${Tx.getHash(tx)}`);
|
|
213
|
-
txsToDelete.push(tx);
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
if (await this.isTxDoubleSpend(tx)) {
|
|
217
|
-
this.log(`Deleting double spend tx ${Tx.getHash(tx)}`);
|
|
218
|
-
txsToDelete.push(tx);
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
else if (this.isTxDoubleSpendSameBlock(tx, thisBlockNullifiers)) {
|
|
222
|
-
// We don't drop these txs from the p2p pool immediately since they become valid
|
|
223
|
-
// again if the current block fails to be published for some reason.
|
|
224
|
-
this.log(`Skipping tx with double-spend for this same block ${Tx.getHash(tx)}`);
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
tx.data.end.newNullifiers.forEach(n => thisBlockNullifiers.add(n.value.toBigInt()));
|
|
228
|
-
tx.data.endNonRevertibleData.newNullifiers.forEach(n => thisBlockNullifiers.add(n.value.toBigInt()));
|
|
229
|
-
validTxs.push(tx);
|
|
230
|
-
if (validTxs.length >= this.maxTxsPerBlock) {
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
214
|
+
async takeValidTxs(txs, validator) {
|
|
215
|
+
const [valid, invalid] = await validator.validateTxs(txs);
|
|
216
|
+
if (invalid.length > 0) {
|
|
217
|
+
this.log(`Dropping invalid txs from the p2p pool ${Tx.getHashes(invalid).join(', ')}`);
|
|
218
|
+
await this.p2pClient.deleteTxs(Tx.getHashes(invalid));
|
|
233
219
|
}
|
|
234
|
-
|
|
235
|
-
if (txsToDelete.length > 0) {
|
|
236
|
-
await this.p2pClient.deleteTxs(Tx.getHashes([...txsToDelete]));
|
|
237
|
-
}
|
|
238
|
-
return validTxs;
|
|
220
|
+
return valid.slice(0, this.maxTxsPerBlock);
|
|
239
221
|
}
|
|
240
222
|
/**
|
|
241
223
|
* Returns whether the previous block sent has been mined, and all dependencies have caught up with it.
|
|
@@ -268,51 +250,6 @@ export class Sequencer {
|
|
|
268
250
|
const [block] = await this.blockBuilder.buildL2Block(globalVariables, allTxs, l1ToL2Messages);
|
|
269
251
|
return block;
|
|
270
252
|
}
|
|
271
|
-
/**
|
|
272
|
-
* Returns true if one of the tx nullifiers exist on the block being built.
|
|
273
|
-
* @param tx - The tx to test.
|
|
274
|
-
* @param thisBlockNullifiers - The nullifiers added so far.
|
|
275
|
-
*/
|
|
276
|
-
isTxDoubleSpendSameBlock(tx, thisBlockNullifiers) {
|
|
277
|
-
// We only consider non-empty nullifiers
|
|
278
|
-
const newNullifiers = [
|
|
279
|
-
...tx.data.endNonRevertibleData.newNullifiers.filter(n => !n.isEmpty()),
|
|
280
|
-
...tx.data.end.newNullifiers.filter(n => !n.isEmpty()),
|
|
281
|
-
];
|
|
282
|
-
for (const nullifier of newNullifiers) {
|
|
283
|
-
if (thisBlockNullifiers.has(nullifier.value.toBigInt())) {
|
|
284
|
-
return true;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
return false;
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Returns true if one of the transaction nullifiers exist.
|
|
291
|
-
* Nullifiers prevent double spends in a private context.
|
|
292
|
-
* @param tx - The transaction.
|
|
293
|
-
* @returns Whether this is a problematic double spend that the L1 contract would reject.
|
|
294
|
-
*/
|
|
295
|
-
async isTxDoubleSpend(tx) {
|
|
296
|
-
// We only consider non-empty nullifiers
|
|
297
|
-
const newNullifiers = [
|
|
298
|
-
...tx.data.endNonRevertibleData.newNullifiers.filter(n => !n.isEmpty()),
|
|
299
|
-
...tx.data.end.newNullifiers.filter(n => !n.isEmpty()),
|
|
300
|
-
];
|
|
301
|
-
// Ditch this tx if it has a repeated nullifiers
|
|
302
|
-
const uniqNullifiers = new Set(newNullifiers.map(n => n.value.toBigInt()));
|
|
303
|
-
if (uniqNullifiers.size !== newNullifiers.length) {
|
|
304
|
-
return true;
|
|
305
|
-
}
|
|
306
|
-
for (const nullifier of newNullifiers) {
|
|
307
|
-
// TODO(AD): this is an exhaustive search currently
|
|
308
|
-
const db = this.worldState.getLatest();
|
|
309
|
-
const indexInDb = await db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
310
|
-
if (indexInDb !== undefined) {
|
|
311
|
-
return true;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
return false;
|
|
315
|
-
}
|
|
316
253
|
get coinbase() {
|
|
317
254
|
return this._coinbase;
|
|
318
255
|
}
|
|
@@ -350,4 +287,4 @@ export var SequencerState;
|
|
|
350
287
|
*/
|
|
351
288
|
SequencerState[SequencerState["STOPPED"] = 5] = "STOPPED";
|
|
352
289
|
})(SequencerState || (SequencerState = {}));
|
|
353
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVuY2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9zZXF1ZW5jZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUErQyxZQUFZLEVBQUUsRUFBRSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFckcsT0FBTyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQW1CLE1BQU0sb0JBQW9CLENBQUM7QUFDL0UsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDbkUsT0FBTyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQU96RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBSzdDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxPQUFPLFNBQVM7SUFXcEIsWUFDVSxTQUFzQixFQUN0QixjQUFxQyxFQUNyQyxTQUFjLEVBQ2QsVUFBa0MsRUFDbEMsWUFBMEIsRUFDMUIsYUFBNEIsRUFDNUIsbUJBQXdDLEVBQ3hDLHNCQUE4QyxFQUN0RCxTQUEwQixFQUFFLEVBQ3BCLE1BQU0saUJBQWlCLENBQUMsaUJBQWlCLENBQUM7UUFUMUMsY0FBUyxHQUFULFNBQVMsQ0FBYTtRQUN0QixtQkFBYyxHQUFkLGNBQWMsQ0FBdUI7UUFDckMsY0FBUyxHQUFULFNBQVMsQ0FBSztRQUNkLGVBQVUsR0FBVixVQUFVLENBQXdCO1FBQ2xDLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7UUFDeEMsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUF3QjtRQUU5QyxRQUFHLEdBQUgsR0FBRyxDQUF1QztRQW5CNUMsc0JBQWlCLEdBQVcsSUFBSSxDQUFDO1FBQ2pDLG1CQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLG1CQUFjLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLDZFQUE2RTtRQUNyRSxjQUFTLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQztRQUM1QixrQkFBYSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUM7UUFDbEMsdUJBQWtCLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZCLFVBQUssR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDO1FBY3JDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyw4QkFBOEIsSUFBSSxDQUFDLGNBQWMsSUFBSSxJQUFJLENBQUMsY0FBYyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3RHLENBQUM7SUFFRDs7O09BR0c7SUFDSSxZQUFZLENBQUMsTUFBdUI7UUFDekMsSUFBSSxNQUFNLENBQUMsNEJBQTRCLEVBQUUsQ0FBQztZQUN4QyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsTUFBTSxDQUFDLDRCQUE0QixDQUFDO1FBQy9ELENBQUM7UUFDRCxJQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUM7UUFDOUMsQ0FBQztRQUNELElBQUksTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQztRQUM5QyxDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO1FBQ25DLENBQUM7UUFDRCxJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUM7UUFDM0MsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxLQUFLO1FBQ2hCLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRXpCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDdkYsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsS0FBSyxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUM7UUFDakMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQy9CLE1BQU0sSUFBSSxDQUFDLGNBQWMsRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUNsQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxLQUFLLEdBQUcsY0FBYyxDQUFDLE9BQU8sQ0FBQztRQUNwQyxJQUFJLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksT0FBTztRQUNaLElBQUksQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxjQUFlLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLEtBQUssR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDO0lBQ25DLENBQUM7SUFFRDs7O09BR0c7SUFDSSxNQUFNO1FBQ1gsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVTLEtBQUssQ0FBQyxXQUFXO1FBQ3pCLGtHQUFrRztRQUNsRyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQW1CLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM1RyxDQUFDO0lBRUQ7O09BRUc7SUFDTyxLQUFLLENBQUMsSUFBSTtRQUNsQixJQUFJLENBQUM7WUFDSCx1REFBdUQ7WUFDdkQsTUFBTSxlQUFlLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDbkQsSUFBSSxlQUFlLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDdEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO2dCQUNsQyxJQUFJLENBQUMsS0FBSyxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUM7WUFDbkMsQ0FBQztZQUVELHdGQUF3RjtZQUN4RixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3JCLE9BQU87WUFDVCxDQUFDO1lBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsS0FBSyxHQUFHLGNBQWMsQ0FBQyxlQUFlLENBQUM7WUFFNUMsaUNBQWlDO1lBQ2pDLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqRCxJQUFJLFVBQVUsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUM1QyxPQUFPO1lBQ1QsQ0FBQztZQUNELElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsVUFBVSxDQUFDLE1BQU0sb0JBQW9CLENBQUMsQ0FBQztZQUVsRSxNQUFNLGdCQUFnQixHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDO1lBQ3pFLE1BQU0sY0FBYyxHQUNsQixDQUFDLGdCQUFnQixLQUFLLFNBQVM7Z0JBQzdCLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxFQUFFO2dCQUMzQyxDQUFDLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUUzRTs7ZUFFRztZQUNILE1BQU0saUJBQWlCLEdBQUcsS0FBSyxJQUFJLEVBQUU7Z0JBQ25DLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUNyRSxJQUFJLGtCQUFrQixHQUFHLENBQUMsS0FBSyxjQUFjLEVBQUUsQ0FBQztvQkFDOUMsTUFBTSxJQUFJLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO2dCQUNoRSxDQUFDO1lBQ0gsQ0FBQyxDQUFDO1lBRUYsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQ3ZFLElBQUksRUFBRSxDQUFDLGNBQWMsQ0FBQyxFQUN0QixJQUFJLENBQUMsU0FBUyxFQUNkLElBQUksQ0FBQyxhQUFhLENBQ25CLENBQUM7WUFFRix5QkFBeUI7WUFDekIsaUdBQWlHO1lBQ2pHLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztZQUN6RSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUMxQyxPQUFPO1lBQ1QsQ0FBQztZQUVELElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGtCQUFrQixjQUFjLFNBQVMsUUFBUSxDQUFDLE1BQU0sZUFBZSxDQUFDLENBQUM7WUFDdkYsSUFBSSxDQUFDLEtBQUssR0FBRyxjQUFjLENBQUMsY0FBYyxDQUFDO1lBRTNDLHNGQUFzRjtZQUN0RixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztZQUNqRyxNQUFNLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxZQUFZLEVBQUUsU0FBUyxDQUFDLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDOUcsSUFBSSxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN6QixNQUFNLFlBQVksR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNwRCxJQUFJLENBQUMsR0FBRyxDQUFDLHVCQUF1QixFQUFFLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3pFLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQzdELENBQUM7WUFFRCxpRUFBaUU7WUFDakUsK0VBQStFO1lBQy9FLG9GQUFvRjtZQUNwRixpRkFBaUY7WUFDakYsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLGtCQUFrQixDQUFDLENBQUM7WUFFcEYsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ25DLElBQUksQ0FBQyxHQUFHLENBQUMsb0RBQW9ELENBQUMsQ0FBQztnQkFDL0QsT0FBTztZQUNULENBQUM7WUFFRCxNQUFNLGlCQUFpQixFQUFFLENBQUM7WUFFMUIsMENBQTBDO1lBQzFDLElBQUksQ0FBQyxHQUFHLENBQUMsNENBQTRDLENBQUMsQ0FBQztZQUN2RCxNQUFNLGNBQWMsR0FBRyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztZQUNoRyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsY0FBYyxDQUFDLE1BQU0sZ0NBQWdDLGNBQWMsRUFBRSxDQUFDLENBQUM7WUFFN0YscURBQXFEO1lBQ3JELElBQUksQ0FBQyxHQUFHLENBQUMsNkJBQTZCLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBRXpGLE1BQU0saUJBQWlCLEVBQUUsQ0FBQztZQUUxQixNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztZQUNqRCxNQUFNLENBQUMsc0JBQXNCLEVBQUUsS0FBSyxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxFQUFFLENBQ3pELElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLE9BQU8sRUFBRSxrQkFBa0IsQ0FBQyxDQUNoRixDQUFDO1lBRUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUFFO2dCQUMxQyxTQUFTLEVBQUUsZ0JBQWdCO2dCQUMzQixRQUFRLEVBQUUsU0FBUyxDQUFDLEVBQUUsRUFBRTtnQkFDeEIscUJBQXFCLEVBQUUsdUJBQXVCO2dCQUM5QyxzQkFBc0IsRUFBRSxzQkFBc0I7Z0JBQzlDLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRTthQUNRLENBQUMsQ0FBQztZQUUvQixNQUFNLGlCQUFpQixFQUFFLENBQUM7WUFFMUIsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLDBCQUEwQixLQUFLLENBQUMsTUFBTSxTQUFTLGlCQUFpQixDQUFDLE1BQU0sZUFBZSxDQUFDLENBQUM7UUFDeEcsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQywyREFBMkQsRUFBRyxHQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQy9DLENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ08sS0FBSyxDQUFDLGNBQWMsQ0FBQyxLQUFjO1FBQzNDLG1FQUFtRTtRQUNuRSxJQUFJLENBQUMsS0FBSyxHQUFHLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQztRQUM3QyxNQUFNLGdCQUFnQixHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEUsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQ3pELElBQUksQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ3pDLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQzdDLENBQUM7SUFDSCxDQUFDO0lBRVMsS0FBSyxDQUFDLFlBQVksQ0FBNkIsR0FBUSxFQUFFLGVBQWdDO1FBQ2pHLE1BQU0sUUFBUSxHQUFRLEVBQUUsQ0FBQztRQUN6QixNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUM7UUFDdkIsTUFBTSxtQkFBbUIsR0FBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUVuRCxxRkFBcUY7UUFDckYsS0FBSyxNQUFNLEVBQUUsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNyQixJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsS0FBSyxLQUFLLGVBQWUsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2hGLElBQUksQ0FBQyxHQUFHLENBQ04sbUNBQW1DLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLGFBQWEsRUFBRSxDQUFDLE9BQU8sQ0FDdEcsRUFBRSxDQUNILEVBQUUsQ0FDSixDQUFDO2dCQUNGLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3JCLFNBQVM7WUFDWCxDQUFDO1lBQ0QsSUFBSSxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyw0QkFBNEIsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3ZELFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3JCLFNBQVM7WUFDWCxDQUFDO2lCQUFNLElBQUksSUFBSSxDQUFDLHdCQUF3QixDQUFDLEVBQUUsRUFBRSxtQkFBbUIsQ0FBQyxFQUFFLENBQUM7Z0JBQ2xFLGdGQUFnRjtnQkFDaEYsb0VBQW9FO2dCQUNwRSxJQUFJLENBQUMsR0FBRyxDQUFDLHFEQUFxRCxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDaEYsU0FBUztZQUNYLENBQUM7WUFFRCxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3BGLEVBQUUsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNyRyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2xCLElBQUksUUFBUSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7Z0JBQzNDLE1BQU07WUFDUixDQUFDO1FBQ0gsQ0FBQztRQUVELDRFQUE0RTtRQUM1RSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDM0IsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7O09BR0c7SUFDTyxLQUFLLENBQUMsYUFBYTtRQUMzQixNQUFNLFlBQVksR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDckMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFtQixFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDO1lBQ3pFLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQztZQUN2RCxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsRUFBRTtZQUNuQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsY0FBYyxFQUFFO1NBQzFDLENBQUMsQ0FBQztRQUNILE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxZQUFZLENBQUMsQ0FBQztRQUN0QyxPQUFPLEdBQUcsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDeEMsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDTyxLQUFLLENBQUMsVUFBVSxDQUN4QixHQUFrQixFQUNsQixjQUFvQixFQUNwQixPQUFvQixFQUNwQixlQUFnQztRQUVoQyxvRUFBb0U7UUFDcEUsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzlELE1BQU0sWUFBWSxHQUFHLGFBQWEsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO1FBRWhELE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUUsR0FBRyxLQUFLLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDL0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsZUFBZSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFckUsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLE1BQU0sRUFBRSxjQUFjLENBQUMsQ0FBQztRQUM5RixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7OztPQUlHO0lBQ08sd0JBQXdCLENBQUMsRUFBb0IsRUFBRSxtQkFBZ0M7UUFDdkYsd0NBQXdDO1FBQ3hDLE1BQU0sYUFBYSxHQUFHO1lBQ3BCLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDdkUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDdkQsQ0FBQztRQUVGLEtBQUssTUFBTSxTQUFTLElBQUksYUFBYSxFQUFFLENBQUM7WUFDdEMsSUFBSSxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ3hELE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNPLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBb0I7UUFDbEQsd0NBQXdDO1FBQ3hDLE1BQU0sYUFBYSxHQUFHO1lBQ3BCLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDdkUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDdkQsQ0FBQztRQUVGLGdEQUFnRDtRQUNoRCxNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0UsSUFBSSxjQUFjLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxLQUFLLE1BQU0sU0FBUyxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ3RDLG1EQUFtRDtZQUNuRCxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sU0FBUyxHQUFHLE1BQU0sRUFBRSxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQzVGLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUM1QixPQUFPLElBQUksQ0FBQztZQUNkLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3hCLENBQUM7SUFFRCxJQUFJLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxjQXlCWDtBQXpCRCxXQUFZLGNBQWM7SUFDeEI7O09BRUc7SUFDSCxtREFBSSxDQUFBO0lBQ0o7O09BRUc7SUFDSCx5RUFBZSxDQUFBO0lBQ2Y7O09BRUc7SUFDSCx1RUFBYyxDQUFBO0lBQ2Q7O09BRUc7SUFDSCwyRkFBd0IsQ0FBQTtJQUN4Qjs7T0FFRztJQUNILDJFQUFnQixDQUFBO0lBQ2hCOztPQUVHO0lBQ0gseURBQU8sQ0FBQTtBQUNULENBQUMsRUF6QlcsY0FBYyxLQUFkLGNBQWMsUUF5QnpCIn0=
|
|
290
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVuY2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9zZXF1ZW5jZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUErQyxZQUFZLEVBQUUsRUFBRSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFckcsT0FBTyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQW1CLE1BQU0sb0JBQW9CLENBQUM7QUFDL0UsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDbkUsT0FBTyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQU96RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNyRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBSTdDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUVoRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sT0FBTyxTQUFTO0lBV3BCLFlBQ1UsU0FBc0IsRUFDdEIsY0FBcUMsRUFDckMsU0FBYyxFQUNkLFVBQWtDLEVBQ2xDLFlBQTBCLEVBQzFCLGFBQTRCLEVBQzVCLG1CQUF3QyxFQUN4QyxzQkFBOEMsRUFDdEQsU0FBMEIsRUFBRSxFQUNwQixtQkFBbUIsVUFBVSxDQUFDLElBQUksRUFDbEMsTUFBTSxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQztRQVYxQyxjQUFTLEdBQVQsU0FBUyxDQUFhO1FBQ3RCLG1CQUFjLEdBQWQsY0FBYyxDQUF1QjtRQUNyQyxjQUFTLEdBQVQsU0FBUyxDQUFLO1FBQ2QsZUFBVSxHQUFWLFVB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
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Tx } from '@aztec/circuit-types';
|
|
2
|
+
import { AztecAddress, EthAddress, Fr, GlobalVariables } from '@aztec/circuits.js';
|
|
3
|
+
import { ProcessedTx } from './processed_tx.js';
|
|
4
|
+
/** A source of what nullifiers have been committed to the state trees */
|
|
5
|
+
export interface NullifierSource {
|
|
6
|
+
getNullifierIndex: (nullifier: Fr) => Promise<bigint | undefined>;
|
|
7
|
+
}
|
|
8
|
+
/** Provides a view into public contract state */
|
|
9
|
+
export interface PublicStateSource {
|
|
10
|
+
storageRead: (contractAddress: AztecAddress, slot: Fr) => Promise<Fr>;
|
|
11
|
+
}
|
|
12
|
+
export declare class TxValidator {
|
|
13
|
+
#private;
|
|
14
|
+
constructor(nullifierSource: NullifierSource, publicStateSource: PublicStateSource, gasPortalAddress: EthAddress, globalVariables: GlobalVariables, log?: import("@aztec/foundation/log").DebugLogger);
|
|
15
|
+
/**
|
|
16
|
+
* Validates a list of transactions.
|
|
17
|
+
* @param txs - The transactions to validate.
|
|
18
|
+
* @returns A tuple of valid and invalid transactions.
|
|
19
|
+
*/
|
|
20
|
+
validateTxs<T extends Tx | ProcessedTx>(txs: T[]): Promise<[validTxs: T[], invalidTxs: T[]]>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=tx_validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tx_validator.d.ts","sourceRoot":"","sources":["../../src/sequencer/tx_validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAMnF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,iBAAiB,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACnE;AAED,iDAAiD;AACjD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,CAAC,eAAe,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;CACvE;AAaD,qBAAa,WAAW;;gBAQpB,eAAe,EAAE,eAAe,EAChC,iBAAiB,EAAE,iBAAiB,EACpC,gBAAgB,EAAE,UAAU,EAC5B,eAAe,EAAE,eAAe,EAChC,GAAG,8CAAoD;IAUzD;;;;OAIG;IACU,WAAW,CAAC,CAAC,SAAS,EAAE,GAAG,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;CAmI1G"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
var _TxValidator_instances, _TxValidator_log, _TxValidator_globalVariables, _TxValidator_nullifierSource, _TxValidator_publicStateSource, _TxValidator_gasPortalAddress, _TxValidator_validateMetadata, _TxValidator_validateNullifiers, _TxValidator_validateFee;
|
|
2
|
+
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
|
+
import { Tx } from '@aztec/circuit-types';
|
|
4
|
+
import { Fr } from '@aztec/circuits.js';
|
|
5
|
+
import { pedersenHash } from '@aztec/foundation/crypto';
|
|
6
|
+
import { createDebugLogger } from '@aztec/foundation/log';
|
|
7
|
+
import { getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token';
|
|
8
|
+
import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
|
|
9
|
+
// prefer symbols over booleans so it's clear what the intention is
|
|
10
|
+
// vs returning true/false is tied to the function name
|
|
11
|
+
// eg. isDoubleSpend vs isValidChain assign different meanings to booleans
|
|
12
|
+
const VALID_TX = Symbol('valid_tx');
|
|
13
|
+
const INVALID_TX = Symbol('invalid_tx');
|
|
14
|
+
// the storage slot associated with "storage.balances"
|
|
15
|
+
const GAS_TOKEN_BALANCES_SLOT = new Fr(1);
|
|
16
|
+
export class TxValidator {
|
|
17
|
+
constructor(nullifierSource, publicStateSource, gasPortalAddress, globalVariables, log = createDebugLogger('aztec:sequencer:tx_validator')) {
|
|
18
|
+
_TxValidator_instances.add(this);
|
|
19
|
+
_TxValidator_log.set(this, void 0);
|
|
20
|
+
_TxValidator_globalVariables.set(this, void 0);
|
|
21
|
+
_TxValidator_nullifierSource.set(this, void 0);
|
|
22
|
+
_TxValidator_publicStateSource.set(this, void 0);
|
|
23
|
+
_TxValidator_gasPortalAddress.set(this, void 0);
|
|
24
|
+
__classPrivateFieldSet(this, _TxValidator_nullifierSource, nullifierSource, "f");
|
|
25
|
+
__classPrivateFieldSet(this, _TxValidator_globalVariables, globalVariables, "f");
|
|
26
|
+
__classPrivateFieldSet(this, _TxValidator_publicStateSource, publicStateSource, "f");
|
|
27
|
+
__classPrivateFieldSet(this, _TxValidator_gasPortalAddress, gasPortalAddress, "f");
|
|
28
|
+
__classPrivateFieldSet(this, _TxValidator_log, log, "f");
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validates a list of transactions.
|
|
32
|
+
* @param txs - The transactions to validate.
|
|
33
|
+
* @returns A tuple of valid and invalid transactions.
|
|
34
|
+
*/
|
|
35
|
+
async validateTxs(txs) {
|
|
36
|
+
const validTxs = [];
|
|
37
|
+
const invalidTxs = [];
|
|
38
|
+
const thisBlockNullifiers = new Set();
|
|
39
|
+
for (const tx of txs) {
|
|
40
|
+
if (__classPrivateFieldGet(this, _TxValidator_instances, "m", _TxValidator_validateMetadata).call(this, tx) === INVALID_TX) {
|
|
41
|
+
invalidTxs.push(tx);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if ((await __classPrivateFieldGet(this, _TxValidator_instances, "m", _TxValidator_validateNullifiers).call(this, tx, thisBlockNullifiers)) === INVALID_TX) {
|
|
45
|
+
invalidTxs.push(tx);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
// skip already processed transactions
|
|
49
|
+
if (tx instanceof Tx && (await __classPrivateFieldGet(this, _TxValidator_instances, "m", _TxValidator_validateFee).call(this, tx)) === INVALID_TX) {
|
|
50
|
+
invalidTxs.push(tx);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
validTxs.push(tx);
|
|
54
|
+
}
|
|
55
|
+
return [validTxs, invalidTxs];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
_TxValidator_log = new WeakMap(), _TxValidator_globalVariables = new WeakMap(), _TxValidator_nullifierSource = new WeakMap(), _TxValidator_publicStateSource = new WeakMap(), _TxValidator_gasPortalAddress = new WeakMap(), _TxValidator_instances = new WeakSet(), _TxValidator_validateMetadata = function _TxValidator_validateMetadata(tx) {
|
|
59
|
+
if (!tx.data.constants.txContext.chainId.equals(__classPrivateFieldGet(this, _TxValidator_globalVariables, "f").chainId)) {
|
|
60
|
+
__classPrivateFieldGet(this, _TxValidator_log, "f").warn(`Rejecting tx ${Tx.getHash(tx)} because of incorrect chain ${tx.data.constants.txContext.chainId.toString()} != ${__classPrivateFieldGet(this, _TxValidator_globalVariables, "f").chainId.toString()}`);
|
|
61
|
+
return INVALID_TX;
|
|
62
|
+
}
|
|
63
|
+
return VALID_TX;
|
|
64
|
+
}, _TxValidator_validateNullifiers =
|
|
65
|
+
/**
|
|
66
|
+
* It looks for duplicate nullifiers:
|
|
67
|
+
* - in the same transaction
|
|
68
|
+
* - in the same block
|
|
69
|
+
* - in the nullifier tree
|
|
70
|
+
*
|
|
71
|
+
* Nullifiers prevent double spends in a private context.
|
|
72
|
+
*
|
|
73
|
+
* @param tx - The transaction.
|
|
74
|
+
* @returns Whether this is a problematic double spend that the L1 contract would reject.
|
|
75
|
+
*/
|
|
76
|
+
async function _TxValidator_validateNullifiers(tx, thisBlockNullifiers) {
|
|
77
|
+
const newNullifiers = [...tx.data.endNonRevertibleData.newNullifiers, ...tx.data.end.newNullifiers]
|
|
78
|
+
.filter(x => !x.isEmpty())
|
|
79
|
+
.map(x => x.value.toBigInt());
|
|
80
|
+
// Ditch this tx if it has repeated nullifiers
|
|
81
|
+
const uniqueNullifiers = new Set(newNullifiers);
|
|
82
|
+
if (uniqueNullifiers.size !== newNullifiers.length) {
|
|
83
|
+
__classPrivateFieldGet(this, _TxValidator_log, "f").warn(`Rejecting tx ${Tx.getHash(tx)} for emitting duplicate nullifiers`);
|
|
84
|
+
return INVALID_TX;
|
|
85
|
+
}
|
|
86
|
+
for (const nullifier of newNullifiers) {
|
|
87
|
+
if (thisBlockNullifiers.has(nullifier)) {
|
|
88
|
+
__classPrivateFieldGet(this, _TxValidator_log, "f").warn(`Rejecting tx ${Tx.getHash(tx)} for repeating a nullifier in the same block`);
|
|
89
|
+
return INVALID_TX;
|
|
90
|
+
}
|
|
91
|
+
thisBlockNullifiers.add(nullifier);
|
|
92
|
+
}
|
|
93
|
+
const nullifierIndexes = await Promise.all(newNullifiers.map(n => __classPrivateFieldGet(this, _TxValidator_nullifierSource, "f").getNullifierIndex(new Fr(n))));
|
|
94
|
+
const hasDuplicates = nullifierIndexes.some(index => index !== undefined);
|
|
95
|
+
if (hasDuplicates) {
|
|
96
|
+
__classPrivateFieldGet(this, _TxValidator_log, "f").warn(`Rejecting tx ${Tx.getHash(tx)} for repeating nullifiers present in state trees`);
|
|
97
|
+
return INVALID_TX;
|
|
98
|
+
}
|
|
99
|
+
return VALID_TX;
|
|
100
|
+
}, _TxValidator_validateFee = async function _TxValidator_validateFee(tx) {
|
|
101
|
+
if (!tx.data.needsTeardown) {
|
|
102
|
+
// TODO check if fees are mandatory and reject this tx
|
|
103
|
+
__classPrivateFieldGet(this, _TxValidator_log, "f").debug(`Tx ${Tx.getHash(tx)} doesn't pay for gas`);
|
|
104
|
+
return VALID_TX;
|
|
105
|
+
}
|
|
106
|
+
const {
|
|
107
|
+
// TODO what if there's more than one function call?
|
|
108
|
+
// if we're to enshrine that teardown = 1 function call, then we should turn this into a single function call
|
|
109
|
+
[PublicKernelPhase.TEARDOWN]: [teardownFn], } = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx.data, tx.enqueuedPublicFunctionCalls);
|
|
110
|
+
if (!teardownFn) {
|
|
111
|
+
__classPrivateFieldGet(this, _TxValidator_log, "f").warn(`Rejecting tx ${Tx.getHash(tx)} because it should pay for gas but has no enqueued teardown function call`);
|
|
112
|
+
return INVALID_TX;
|
|
113
|
+
}
|
|
114
|
+
// TODO(#1204) if a generator index is used for the derived storage slot of a map, update it here as well
|
|
115
|
+
const slot = pedersenHash([GAS_TOKEN_BALANCES_SLOT.toBuffer(), teardownFn.callContext.msgSender.toBuffer()]);
|
|
116
|
+
const gasBalance = await __classPrivateFieldGet(this, _TxValidator_publicStateSource, "f").storageRead(getCanonicalGasTokenAddress(__classPrivateFieldGet(this, _TxValidator_gasPortalAddress, "f")), slot);
|
|
117
|
+
// TODO(#5004) calculate fee needed based on tx limits and gas prices
|
|
118
|
+
const gasAmountNeeded = new Fr(1);
|
|
119
|
+
if (gasBalance.lt(gasAmountNeeded)) {
|
|
120
|
+
__classPrivateFieldGet(this, _TxValidator_log, "f").warn(`Rejecting tx ${Tx.getHash(tx)} because it should pay for gas but has insufficient balance ${gasBalance.toShortString()} < ${gasAmountNeeded.toShortString()}`);
|
|
121
|
+
return INVALID_TX;
|
|
122
|
+
}
|
|
123
|
+
return VALID_TX;
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhfdmFsaWRhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci90eF92YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDMUMsT0FBTyxFQUE0QixFQUFFLEVBQW1CLE1BQU0sb0JBQW9CLENBQUM7QUFDbkYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3hELE9BQU8sRUFBVSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBRWxGLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBYXRGLG1FQUFtRTtBQUNuRSx1REFBdUQ7QUFDdkQsMEVBQTBFO0FBQzFFLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUNwQyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7QUFJeEMsc0RBQXNEO0FBQ3RELE1BQU0sdUJBQXVCLEdBQUcsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFMUMsTUFBTSxPQUFPLFdBQVc7SUFPdEIsWUFDRSxlQUFnQyxFQUNoQyxpQkFBb0MsRUFDcEMsZ0JBQTRCLEVBQzVCLGVBQWdDLEVBQ2hDLEdBQUcsR0FBRyxpQkFBaUIsQ0FBQyw4QkFBOEIsQ0FBQzs7UUFYekQsbUNBQWE7UUFDYiwrQ0FBa0M7UUFDbEMsK0NBQWtDO1FBQ2xDLGlEQUFzQztRQUN0QyxnREFBOEI7UUFTNUIsdUJBQUEsSUFBSSxnQ0FBb0IsZUFBZSxNQUFBLENBQUM7UUFDeEMsdUJBQUEsSUFBSSxnQ0FBb0IsZUFBZSxNQUFBLENBQUM7UUFDeEMsdUJBQUEsSUFBSSxrQ0FBc0IsaUJBQWlCLE1BQUEsQ0FB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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/sequencer-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": "./dest/index.js",
|
|
6
6
|
"typedocOptions": {
|
|
@@ -21,18 +21,18 @@
|
|
|
21
21
|
"test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@aztec/circuit-types": "0.
|
|
25
|
-
"@aztec/circuits.js": "0.
|
|
26
|
-
"@aztec/ethereum": "0.
|
|
27
|
-
"@aztec/foundation": "0.
|
|
28
|
-
"@aztec/l1-artifacts": "0.
|
|
29
|
-
"@aztec/merkle-tree": "0.
|
|
30
|
-
"@aztec/noir-protocol-circuits-types": "0.
|
|
31
|
-
"@aztec/p2p": "0.
|
|
32
|
-
"@aztec/protocol-contracts": "0.
|
|
33
|
-
"@aztec/simulator": "0.
|
|
34
|
-
"@aztec/types": "0.
|
|
35
|
-
"@aztec/world-state": "0.
|
|
24
|
+
"@aztec/circuit-types": "0.30.1",
|
|
25
|
+
"@aztec/circuits.js": "0.30.1",
|
|
26
|
+
"@aztec/ethereum": "0.30.1",
|
|
27
|
+
"@aztec/foundation": "0.30.1",
|
|
28
|
+
"@aztec/l1-artifacts": "0.30.1",
|
|
29
|
+
"@aztec/merkle-tree": "0.30.1",
|
|
30
|
+
"@aztec/noir-protocol-circuits-types": "0.30.1",
|
|
31
|
+
"@aztec/p2p": "0.30.1",
|
|
32
|
+
"@aztec/protocol-contracts": "0.30.1",
|
|
33
|
+
"@aztec/simulator": "0.30.1",
|
|
34
|
+
"@aztec/types": "0.30.1",
|
|
35
|
+
"@aztec/world-state": "0.30.1",
|
|
36
36
|
"@noir-lang/acvm_js": "portal:../../noir/packages/acvm_js",
|
|
37
37
|
"@noir-lang/types": "portal:../../noir/packages/types",
|
|
38
38
|
"lodash.chunk": "^4.2.0",
|
package/src/config.ts
CHANGED
|
@@ -45,6 +45,8 @@ export function getConfigEnvVars(): SequencerClientConfig {
|
|
|
45
45
|
REGISTRY_CONTRACT_ADDRESS,
|
|
46
46
|
INBOX_CONTRACT_ADDRESS,
|
|
47
47
|
OUTBOX_CONTRACT_ADDRESS,
|
|
48
|
+
GAS_TOKEN_CONTRACT_ADDRESS,
|
|
49
|
+
GAS_PORTAL_CONTRACT_ADDRESS,
|
|
48
50
|
COINBASE,
|
|
49
51
|
FEE_RECIPIENT,
|
|
50
52
|
ACVM_WORKING_DIRECTORY,
|
|
@@ -63,6 +65,10 @@ export function getConfigEnvVars(): SequencerClientConfig {
|
|
|
63
65
|
registryAddress: REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
64
66
|
inboxAddress: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
65
67
|
outboxAddress: OUTBOX_CONTRACT_ADDRESS ? EthAddress.fromString(OUTBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
68
|
+
gasTokenAddress: GAS_TOKEN_CONTRACT_ADDRESS ? EthAddress.fromString(GAS_TOKEN_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
69
|
+
gasPortalAddress: GAS_PORTAL_CONTRACT_ADDRESS
|
|
70
|
+
? EthAddress.fromString(GAS_PORTAL_CONTRACT_ADDRESS)
|
|
71
|
+
: EthAddress.ZERO,
|
|
66
72
|
};
|
|
67
73
|
|
|
68
74
|
return {
|
|
@@ -12,10 +12,12 @@ import { WorldStateStatus, WorldStateSynchronizer } from '@aztec/world-state';
|
|
|
12
12
|
import { BlockBuilder } from '../block_builder/index.js';
|
|
13
13
|
import { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
|
|
14
14
|
import { L1Publisher } from '../publisher/l1-publisher.js';
|
|
15
|
+
import { WorldStatePublicDB } from '../simulator/public_executor.js';
|
|
15
16
|
import { ceilPowerOfTwo } from '../utils.js';
|
|
16
17
|
import { SequencerConfig } from './config.js';
|
|
17
18
|
import { ProcessedTx } from './processed_tx.js';
|
|
18
19
|
import { PublicProcessorFactory } from './public_processor.js';
|
|
20
|
+
import { TxValidator } from './tx_validator.js';
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Sequencer client
|
|
@@ -47,6 +49,7 @@ export class Sequencer {
|
|
|
47
49
|
private l1ToL2MessageSource: L1ToL2MessageSource,
|
|
48
50
|
private publicProcessorFactory: PublicProcessorFactory,
|
|
49
51
|
config: SequencerConfig = {},
|
|
52
|
+
private gasPortalAddress = EthAddress.ZERO,
|
|
50
53
|
private log = createDebugLogger('aztec:sequencer'),
|
|
51
54
|
) {
|
|
52
55
|
this.updateConfig(config);
|
|
@@ -171,8 +174,20 @@ export class Sequencer {
|
|
|
171
174
|
);
|
|
172
175
|
|
|
173
176
|
// Filter out invalid txs
|
|
177
|
+
const trees = this.worldState.getLatest();
|
|
178
|
+
const txValidator = new TxValidator(
|
|
179
|
+
{
|
|
180
|
+
getNullifierIndex(nullifier: Fr): Promise<bigint | undefined> {
|
|
181
|
+
return trees.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
new WorldStatePublicDB(trees),
|
|
185
|
+
this.gasPortalAddress,
|
|
186
|
+
newGlobalVariables,
|
|
187
|
+
);
|
|
188
|
+
|
|
174
189
|
// TODO: It should be responsibility of the P2P layer to validate txs before passing them on here
|
|
175
|
-
const validTxs = await this.takeValidTxs(pendingTxs,
|
|
190
|
+
const validTxs = await this.takeValidTxs(pendingTxs, txValidator);
|
|
176
191
|
if (validTxs.length < this.minTxsPerBLock) {
|
|
177
192
|
return;
|
|
178
193
|
}
|
|
@@ -193,7 +208,7 @@ export class Sequencer {
|
|
|
193
208
|
// public functions emitting nullifiers would pass earlier check but fail here.
|
|
194
209
|
// Note that we're checking all nullifiers generated in the private execution twice,
|
|
195
210
|
// we could store the ones already checked and skip them here as an optimization.
|
|
196
|
-
const processedValidTxs = await this.takeValidTxs(processedTxs,
|
|
211
|
+
const processedValidTxs = await this.takeValidTxs(processedTxs, txValidator);
|
|
197
212
|
|
|
198
213
|
if (processedValidTxs.length === 0) {
|
|
199
214
|
this.log('No txs processed correctly to build block. Exiting');
|
|
@@ -251,47 +266,14 @@ export class Sequencer {
|
|
|
251
266
|
}
|
|
252
267
|
}
|
|
253
268
|
|
|
254
|
-
protected async takeValidTxs<T extends Tx | ProcessedTx>(txs: T[],
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
// Process txs until we get to maxTxsPerBlock, rejecting double spends in the process
|
|
260
|
-
for (const tx of txs) {
|
|
261
|
-
if (tx.data.constants.txContext.chainId.value !== globalVariables.chainId.value) {
|
|
262
|
-
this.log(
|
|
263
|
-
`Deleting tx for incorrect chain ${tx.data.constants.txContext.chainId.toString()}, tx hash ${Tx.getHash(
|
|
264
|
-
tx,
|
|
265
|
-
)}`,
|
|
266
|
-
);
|
|
267
|
-
txsToDelete.push(tx);
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
if (await this.isTxDoubleSpend(tx)) {
|
|
271
|
-
this.log(`Deleting double spend tx ${Tx.getHash(tx)}`);
|
|
272
|
-
txsToDelete.push(tx);
|
|
273
|
-
continue;
|
|
274
|
-
} else if (this.isTxDoubleSpendSameBlock(tx, thisBlockNullifiers)) {
|
|
275
|
-
// We don't drop these txs from the p2p pool immediately since they become valid
|
|
276
|
-
// again if the current block fails to be published for some reason.
|
|
277
|
-
this.log(`Skipping tx with double-spend for this same block ${Tx.getHash(tx)}`);
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
tx.data.end.newNullifiers.forEach(n => thisBlockNullifiers.add(n.value.toBigInt()));
|
|
282
|
-
tx.data.endNonRevertibleData.newNullifiers.forEach(n => thisBlockNullifiers.add(n.value.toBigInt()));
|
|
283
|
-
validTxs.push(tx);
|
|
284
|
-
if (validTxs.length >= this.maxTxsPerBlock) {
|
|
285
|
-
break;
|
|
286
|
-
}
|
|
269
|
+
protected async takeValidTxs<T extends Tx | ProcessedTx>(txs: T[], validator: TxValidator): Promise<T[]> {
|
|
270
|
+
const [valid, invalid] = await validator.validateTxs(txs);
|
|
271
|
+
if (invalid.length > 0) {
|
|
272
|
+
this.log(`Dropping invalid txs from the p2p pool ${Tx.getHashes(invalid).join(', ')}`);
|
|
273
|
+
await this.p2pClient.deleteTxs(Tx.getHashes(invalid));
|
|
287
274
|
}
|
|
288
275
|
|
|
289
|
-
|
|
290
|
-
if (txsToDelete.length > 0) {
|
|
291
|
-
await this.p2pClient.deleteTxs(Tx.getHashes([...txsToDelete]));
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return validTxs;
|
|
276
|
+
return valid.slice(0, this.maxTxsPerBlock);
|
|
295
277
|
}
|
|
296
278
|
|
|
297
279
|
/**
|
|
@@ -334,56 +316,6 @@ export class Sequencer {
|
|
|
334
316
|
return block;
|
|
335
317
|
}
|
|
336
318
|
|
|
337
|
-
/**
|
|
338
|
-
* Returns true if one of the tx nullifiers exist on the block being built.
|
|
339
|
-
* @param tx - The tx to test.
|
|
340
|
-
* @param thisBlockNullifiers - The nullifiers added so far.
|
|
341
|
-
*/
|
|
342
|
-
protected isTxDoubleSpendSameBlock(tx: Tx | ProcessedTx, thisBlockNullifiers: Set<bigint>): boolean {
|
|
343
|
-
// We only consider non-empty nullifiers
|
|
344
|
-
const newNullifiers = [
|
|
345
|
-
...tx.data.endNonRevertibleData.newNullifiers.filter(n => !n.isEmpty()),
|
|
346
|
-
...tx.data.end.newNullifiers.filter(n => !n.isEmpty()),
|
|
347
|
-
];
|
|
348
|
-
|
|
349
|
-
for (const nullifier of newNullifiers) {
|
|
350
|
-
if (thisBlockNullifiers.has(nullifier.value.toBigInt())) {
|
|
351
|
-
return true;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
return false;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Returns true if one of the transaction nullifiers exist.
|
|
359
|
-
* Nullifiers prevent double spends in a private context.
|
|
360
|
-
* @param tx - The transaction.
|
|
361
|
-
* @returns Whether this is a problematic double spend that the L1 contract would reject.
|
|
362
|
-
*/
|
|
363
|
-
protected async isTxDoubleSpend(tx: Tx | ProcessedTx): Promise<boolean> {
|
|
364
|
-
// We only consider non-empty nullifiers
|
|
365
|
-
const newNullifiers = [
|
|
366
|
-
...tx.data.endNonRevertibleData.newNullifiers.filter(n => !n.isEmpty()),
|
|
367
|
-
...tx.data.end.newNullifiers.filter(n => !n.isEmpty()),
|
|
368
|
-
];
|
|
369
|
-
|
|
370
|
-
// Ditch this tx if it has a repeated nullifiers
|
|
371
|
-
const uniqNullifiers = new Set(newNullifiers.map(n => n.value.toBigInt()));
|
|
372
|
-
if (uniqNullifiers.size !== newNullifiers.length) {
|
|
373
|
-
return true;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
for (const nullifier of newNullifiers) {
|
|
377
|
-
// TODO(AD): this is an exhaustive search currently
|
|
378
|
-
const db = this.worldState.getLatest();
|
|
379
|
-
const indexInDb = await db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
380
|
-
if (indexInDb !== undefined) {
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
319
|
get coinbase(): EthAddress {
|
|
388
320
|
return this._coinbase;
|
|
389
321
|
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { Tx } from '@aztec/circuit-types';
|
|
2
|
+
import { AztecAddress, EthAddress, Fr, GlobalVariables } from '@aztec/circuits.js';
|
|
3
|
+
import { pedersenHash } from '@aztec/foundation/crypto';
|
|
4
|
+
import { Logger, createDebugLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token';
|
|
6
|
+
|
|
7
|
+
import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
|
|
8
|
+
import { ProcessedTx } from './processed_tx.js';
|
|
9
|
+
|
|
10
|
+
/** A source of what nullifiers have been committed to the state trees */
|
|
11
|
+
export interface NullifierSource {
|
|
12
|
+
getNullifierIndex: (nullifier: Fr) => Promise<bigint | undefined>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Provides a view into public contract state */
|
|
16
|
+
export interface PublicStateSource {
|
|
17
|
+
storageRead: (contractAddress: AztecAddress, slot: Fr) => Promise<Fr>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// prefer symbols over booleans so it's clear what the intention is
|
|
21
|
+
// vs returning true/false is tied to the function name
|
|
22
|
+
// eg. isDoubleSpend vs isValidChain assign different meanings to booleans
|
|
23
|
+
const VALID_TX = Symbol('valid_tx');
|
|
24
|
+
const INVALID_TX = Symbol('invalid_tx');
|
|
25
|
+
|
|
26
|
+
type TxValidationStatus = typeof VALID_TX | typeof INVALID_TX;
|
|
27
|
+
|
|
28
|
+
// the storage slot associated with "storage.balances"
|
|
29
|
+
const GAS_TOKEN_BALANCES_SLOT = new Fr(1);
|
|
30
|
+
|
|
31
|
+
export class TxValidator {
|
|
32
|
+
#log: Logger;
|
|
33
|
+
#globalVariables: GlobalVariables;
|
|
34
|
+
#nullifierSource: NullifierSource;
|
|
35
|
+
#publicStateSource: PublicStateSource;
|
|
36
|
+
#gasPortalAddress: EthAddress;
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
nullifierSource: NullifierSource,
|
|
40
|
+
publicStateSource: PublicStateSource,
|
|
41
|
+
gasPortalAddress: EthAddress,
|
|
42
|
+
globalVariables: GlobalVariables,
|
|
43
|
+
log = createDebugLogger('aztec:sequencer:tx_validator'),
|
|
44
|
+
) {
|
|
45
|
+
this.#nullifierSource = nullifierSource;
|
|
46
|
+
this.#globalVariables = globalVariables;
|
|
47
|
+
this.#publicStateSource = publicStateSource;
|
|
48
|
+
this.#gasPortalAddress = gasPortalAddress;
|
|
49
|
+
|
|
50
|
+
this.#log = log;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validates a list of transactions.
|
|
55
|
+
* @param txs - The transactions to validate.
|
|
56
|
+
* @returns A tuple of valid and invalid transactions.
|
|
57
|
+
*/
|
|
58
|
+
public async validateTxs<T extends Tx | ProcessedTx>(txs: T[]): Promise<[validTxs: T[], invalidTxs: T[]]> {
|
|
59
|
+
const validTxs: T[] = [];
|
|
60
|
+
const invalidTxs: T[] = [];
|
|
61
|
+
const thisBlockNullifiers = new Set<bigint>();
|
|
62
|
+
|
|
63
|
+
for (const tx of txs) {
|
|
64
|
+
if (this.#validateMetadata(tx) === INVALID_TX) {
|
|
65
|
+
invalidTxs.push(tx);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if ((await this.#validateNullifiers(tx, thisBlockNullifiers)) === INVALID_TX) {
|
|
70
|
+
invalidTxs.push(tx);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// skip already processed transactions
|
|
75
|
+
if (tx instanceof Tx && (await this.#validateFee(tx)) === INVALID_TX) {
|
|
76
|
+
invalidTxs.push(tx);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
validTxs.push(tx);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return [validTxs, invalidTxs];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* It rejects transactions with the wrong chain id.
|
|
88
|
+
* @param tx - The transaction.
|
|
89
|
+
* @returns Whether the transaction is valid.
|
|
90
|
+
*/
|
|
91
|
+
#validateMetadata(tx: Tx | ProcessedTx): TxValidationStatus {
|
|
92
|
+
if (!tx.data.constants.txContext.chainId.equals(this.#globalVariables.chainId)) {
|
|
93
|
+
this.#log.warn(
|
|
94
|
+
`Rejecting tx ${Tx.getHash(
|
|
95
|
+
tx,
|
|
96
|
+
)} because of incorrect chain ${tx.data.constants.txContext.chainId.toString()} != ${this.#globalVariables.chainId.toString()}`,
|
|
97
|
+
);
|
|
98
|
+
return INVALID_TX;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return VALID_TX;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* It looks for duplicate nullifiers:
|
|
106
|
+
* - in the same transaction
|
|
107
|
+
* - in the same block
|
|
108
|
+
* - in the nullifier tree
|
|
109
|
+
*
|
|
110
|
+
* Nullifiers prevent double spends in a private context.
|
|
111
|
+
*
|
|
112
|
+
* @param tx - The transaction.
|
|
113
|
+
* @returns Whether this is a problematic double spend that the L1 contract would reject.
|
|
114
|
+
*/
|
|
115
|
+
async #validateNullifiers(tx: Tx | ProcessedTx, thisBlockNullifiers: Set<bigint>): Promise<TxValidationStatus> {
|
|
116
|
+
const newNullifiers = [...tx.data.endNonRevertibleData.newNullifiers, ...tx.data.end.newNullifiers]
|
|
117
|
+
.filter(x => !x.isEmpty())
|
|
118
|
+
.map(x => x.value.toBigInt());
|
|
119
|
+
|
|
120
|
+
// Ditch this tx if it has repeated nullifiers
|
|
121
|
+
const uniqueNullifiers = new Set(newNullifiers);
|
|
122
|
+
if (uniqueNullifiers.size !== newNullifiers.length) {
|
|
123
|
+
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for emitting duplicate nullifiers`);
|
|
124
|
+
return INVALID_TX;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (const nullifier of newNullifiers) {
|
|
128
|
+
if (thisBlockNullifiers.has(nullifier)) {
|
|
129
|
+
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for repeating a nullifier in the same block`);
|
|
130
|
+
return INVALID_TX;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
thisBlockNullifiers.add(nullifier);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const nullifierIndexes = await Promise.all(
|
|
137
|
+
newNullifiers.map(n => this.#nullifierSource.getNullifierIndex(new Fr(n))),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const hasDuplicates = nullifierIndexes.some(index => index !== undefined);
|
|
141
|
+
if (hasDuplicates) {
|
|
142
|
+
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for repeating nullifiers present in state trees`);
|
|
143
|
+
return INVALID_TX;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return VALID_TX;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async #validateFee(tx: Tx): Promise<TxValidationStatus> {
|
|
150
|
+
if (!tx.data.needsTeardown) {
|
|
151
|
+
// TODO check if fees are mandatory and reject this tx
|
|
152
|
+
this.#log.debug(`Tx ${Tx.getHash(tx)} doesn't pay for gas`);
|
|
153
|
+
return VALID_TX;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const {
|
|
157
|
+
// TODO what if there's more than one function call?
|
|
158
|
+
// if we're to enshrine that teardown = 1 function call, then we should turn this into a single function call
|
|
159
|
+
[PublicKernelPhase.TEARDOWN]: [teardownFn],
|
|
160
|
+
} = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx.data, tx.enqueuedPublicFunctionCalls);
|
|
161
|
+
|
|
162
|
+
if (!teardownFn) {
|
|
163
|
+
this.#log.warn(
|
|
164
|
+
`Rejecting tx ${Tx.getHash(tx)} because it should pay for gas but has no enqueued teardown function call`,
|
|
165
|
+
);
|
|
166
|
+
return INVALID_TX;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// TODO(#1204) if a generator index is used for the derived storage slot of a map, update it here as well
|
|
170
|
+
const slot = pedersenHash([GAS_TOKEN_BALANCES_SLOT.toBuffer(), teardownFn.callContext.msgSender.toBuffer()]);
|
|
171
|
+
const gasBalance = await this.#publicStateSource.storageRead(
|
|
172
|
+
getCanonicalGasTokenAddress(this.#gasPortalAddress),
|
|
173
|
+
slot,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// TODO(#5004) calculate fee needed based on tx limits and gas prices
|
|
177
|
+
const gasAmountNeeded = new Fr(1);
|
|
178
|
+
if (gasBalance.lt(gasAmountNeeded)) {
|
|
179
|
+
this.#log.warn(
|
|
180
|
+
`Rejecting tx ${Tx.getHash(
|
|
181
|
+
tx,
|
|
182
|
+
)} because it should pay for gas but has insufficient balance ${gasBalance.toShortString()} < ${gasAmountNeeded.toShortString()}`,
|
|
183
|
+
);
|
|
184
|
+
return INVALID_TX;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return VALID_TX;
|
|
188
|
+
}
|
|
189
|
+
}
|