@aztec/sequencer-client 0.76.4-devnet-test-rc3 → 0.77.0-testnet-ignition.17
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/index.js +0 -1
- package/dest/client/sequencer-client.d.ts +12 -9
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +55 -60
- package/dest/config.d.ts +2 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +41 -46
- package/dest/global_variable_builder/global_builder.d.ts +5 -2
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +45 -31
- package/dest/global_variable_builder/index.js +0 -1
- package/dest/index.js +0 -1
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +33 -48
- package/dest/publisher/index.js +0 -1
- package/dest/publisher/sequencer-publisher-metrics.d.ts +6 -5
- package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-metrics.js +46 -28
- package/dest/publisher/sequencer-publisher.d.ts +11 -23
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +191 -238
- package/dest/sequencer/allowed.d.ts +1 -1
- package/dest/sequencer/allowed.d.ts.map +1 -1
- package/dest/sequencer/allowed.js +6 -13
- package/dest/sequencer/config.d.ts +1 -1
- package/dest/sequencer/config.d.ts.map +1 -1
- package/dest/sequencer/config.js +1 -2
- package/dest/sequencer/index.js +0 -1
- package/dest/sequencer/metrics.js +26 -18
- package/dest/sequencer/sequencer.d.ts +19 -15
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +589 -625
- package/dest/sequencer/timetable.d.ts +1 -1
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +33 -19
- package/dest/sequencer/utils.d.ts +2 -1
- package/dest/sequencer/utils.d.ts.map +1 -1
- package/dest/sequencer/utils.js +22 -32
- package/dest/slasher/factory.d.ts +5 -5
- package/dest/slasher/factory.d.ts.map +1 -1
- package/dest/slasher/factory.js +5 -4
- package/dest/slasher/index.js +0 -1
- package/dest/slasher/slasher_client.d.ts +4 -4
- package/dest/slasher/slasher_client.d.ts.map +1 -1
- package/dest/slasher/slasher_client.js +110 -113
- package/dest/test/index.d.ts +3 -3
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +4 -1
- package/dest/tx_validator/archive_cache.d.ts +3 -3
- package/dest/tx_validator/archive_cache.d.ts.map +1 -1
- package/dest/tx_validator/archive_cache.js +8 -8
- package/dest/tx_validator/gas_validator.d.ts +5 -3
- package/dest/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/tx_validator/gas_validator.js +70 -70
- package/dest/tx_validator/nullifier_cache.d.ts +2 -2
- package/dest/tx_validator/nullifier_cache.d.ts.map +1 -1
- package/dest/tx_validator/nullifier_cache.js +9 -9
- package/dest/tx_validator/phases_validator.d.ts +3 -2
- package/dest/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/tx_validator/phases_validator.js +28 -20
- package/dest/tx_validator/test_utils.d.ts +4 -2
- package/dest/tx_validator/test_utils.d.ts.map +1 -1
- package/dest/tx_validator/test_utils.js +2 -3
- package/dest/tx_validator/tx_validator_factory.d.ts +7 -5
- package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
- package/dest/tx_validator/tx_validator_factory.js +14 -13
- package/package.json +26 -27
- package/src/client/sequencer-client.ts +17 -14
- package/src/config.ts +6 -14
- package/src/global_variable_builder/global_builder.ts +18 -19
- package/src/publisher/config.ts +9 -17
- package/src/publisher/sequencer-publisher-metrics.ts +22 -9
- package/src/publisher/sequencer-publisher.ts +16 -101
- package/src/sequencer/allowed.ts +4 -4
- package/src/sequencer/config.ts +1 -1
- package/src/sequencer/sequencer.ts +39 -113
- package/src/sequencer/timetable.ts +1 -1
- package/src/sequencer/utils.ts +2 -1
- package/src/slasher/factory.ts +5 -5
- package/src/slasher/slasher_client.ts +16 -21
- package/src/test/index.ts +3 -3
- package/src/tx_validator/archive_cache.ts +4 -3
- package/src/tx_validator/gas_validator.ts +22 -31
- package/src/tx_validator/nullifier_cache.ts +3 -2
- package/src/tx_validator/phases_validator.ts +7 -7
- package/src/tx_validator/test_utils.ts +5 -3
- package/src/tx_validator/tx_validator_factory.ts +23 -17
|
@@ -1,47 +1,47 @@
|
|
|
1
|
+
import type { L2Block } from '@aztec/aztec.js';
|
|
2
|
+
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
3
|
+
import { omit } from '@aztec/foundation/collection';
|
|
4
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
|
+
import type { Signature } from '@aztec/foundation/eth-signature';
|
|
6
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
7
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
8
|
+
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
9
|
+
import { type DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
|
|
10
|
+
import type { P2P } from '@aztec/p2p';
|
|
11
|
+
import type { BlockBuilderFactory } from '@aztec/prover-client/block-builder';
|
|
12
|
+
import type { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
13
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
14
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
15
|
+
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
16
|
+
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
17
|
+
import { Gas } from '@aztec/stdlib/gas';
|
|
1
18
|
import {
|
|
2
|
-
type
|
|
3
|
-
type L1RollupConstants,
|
|
4
|
-
type L1ToL2MessageSource,
|
|
5
|
-
type L2Block,
|
|
6
|
-
type L2BlockSource,
|
|
19
|
+
type AllowedElement,
|
|
7
20
|
SequencerConfigSchema,
|
|
8
|
-
Tx,
|
|
9
|
-
type TxHash,
|
|
10
21
|
type WorldStateSynchronizer,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import {
|
|
22
|
+
type WorldStateSynchronizerStatus,
|
|
23
|
+
} from '@aztec/stdlib/interfaces/server';
|
|
24
|
+
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
25
|
+
import { pickFromSchema } from '@aztec/stdlib/schemas';
|
|
26
|
+
import type { L2BlockBuiltStats } from '@aztec/stdlib/stats';
|
|
27
|
+
import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
|
|
14
28
|
import {
|
|
15
|
-
AppendOnlyTreeSnapshot,
|
|
16
29
|
BlockHeader,
|
|
17
30
|
ContentCommitment,
|
|
18
|
-
type ContractDataSource,
|
|
19
|
-
GENESIS_ARCHIVE_ROOT,
|
|
20
|
-
Gas,
|
|
21
31
|
type GlobalVariables,
|
|
22
|
-
INITIAL_L2_BLOCK_NUM,
|
|
23
32
|
StateReference,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
28
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
29
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
30
|
-
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
31
|
-
import { pickFromSchema } from '@aztec/foundation/schemas';
|
|
32
|
-
import { type DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
|
|
33
|
-
import { type P2P } from '@aztec/p2p';
|
|
34
|
-
import { type BlockBuilderFactory } from '@aztec/prover-client/block-builder';
|
|
35
|
-
import { type PublicProcessorFactory } from '@aztec/simulator/server';
|
|
33
|
+
Tx,
|
|
34
|
+
type TxHash,
|
|
35
|
+
} from '@aztec/stdlib/tx';
|
|
36
36
|
import { Attributes, type TelemetryClient, type Tracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
37
|
-
import {
|
|
37
|
+
import type { ValidatorClient } from '@aztec/validator-client';
|
|
38
38
|
|
|
39
|
-
import {
|
|
39
|
+
import type { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
|
|
40
40
|
import { type SequencerPublisher, VoteType } from '../publisher/sequencer-publisher.js';
|
|
41
|
-
import {
|
|
41
|
+
import type { SlasherClient } from '../slasher/slasher_client.js';
|
|
42
42
|
import { createValidatorsForBlockBuilding } from '../tx_validator/tx_validator_factory.js';
|
|
43
43
|
import { getDefaultAllowedSetupFunctions } from './allowed.js';
|
|
44
|
-
import {
|
|
44
|
+
import type { SequencerConfig } from './config.js';
|
|
45
45
|
import { SequencerMetrics } from './metrics.js';
|
|
46
46
|
import { SequencerTimetable, SequencerTooSlowError } from './timetable.js';
|
|
47
47
|
import { SequencerState, orderAttestations } from './utils.js';
|
|
@@ -272,9 +272,6 @@ export class Sequencer {
|
|
|
272
272
|
VoteType.SLASHING,
|
|
273
273
|
);
|
|
274
274
|
|
|
275
|
-
// Start collecting proof quotes for the previous epoch if needed in the background
|
|
276
|
-
const createProofQuotePromise = this.createProofClaimForPreviousEpoch(slot);
|
|
277
|
-
|
|
278
275
|
this.setState(SequencerState.INITIALIZING_PROPOSAL, slot);
|
|
279
276
|
this.log.verbose(`Preparing proposal for block ${newBlockNumber} at slot ${slot}`, {
|
|
280
277
|
chainTipArchive,
|
|
@@ -315,11 +312,6 @@ export class Sequencer {
|
|
|
315
312
|
await enqueueSlashingVotePromise.catch(err => {
|
|
316
313
|
this.log.error(`Error enqueuing slashing vote`, err, { blockNumber: newBlockNumber, slot });
|
|
317
314
|
});
|
|
318
|
-
await createProofQuotePromise
|
|
319
|
-
.then(quote => (quote ? this.publisher.enqueueClaimEpochProofRight(quote) : undefined))
|
|
320
|
-
.catch(err => {
|
|
321
|
-
this.log.error(`Error creating proof quote`, err, { blockNumber: newBlockNumber, slot });
|
|
322
|
-
});
|
|
323
315
|
|
|
324
316
|
await this.publisher.sendRequests();
|
|
325
317
|
|
|
@@ -460,7 +452,6 @@ export class Sequencer {
|
|
|
460
452
|
publicProcessorFork,
|
|
461
453
|
this.contractDataSource,
|
|
462
454
|
newGlobalVariables,
|
|
463
|
-
!!this.config.enforceFees,
|
|
464
455
|
this.allowedInSetup,
|
|
465
456
|
);
|
|
466
457
|
|
|
@@ -658,54 +649,6 @@ export class Sequencer {
|
|
|
658
649
|
return orderAttestations(attestations, committee);
|
|
659
650
|
}
|
|
660
651
|
|
|
661
|
-
protected async createProofClaimForPreviousEpoch(slotNumber: bigint): Promise<EpochProofQuote | undefined> {
|
|
662
|
-
try {
|
|
663
|
-
// Find out which epoch we are currently in
|
|
664
|
-
const epochToProve = await this.publisher.getClaimableEpoch();
|
|
665
|
-
|
|
666
|
-
if (epochToProve === undefined) {
|
|
667
|
-
this.log.trace(`No epoch to claim at slot ${slotNumber}`);
|
|
668
|
-
return undefined;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
// Get quotes for the epoch to be proven
|
|
672
|
-
this.log.debug(`Collecting proof quotes for epoch ${epochToProve}`);
|
|
673
|
-
const p2pQuotes = await this.p2pClient
|
|
674
|
-
.getEpochProofQuotes(epochToProve)
|
|
675
|
-
.then(quotes =>
|
|
676
|
-
quotes
|
|
677
|
-
.filter(x => x.payload.validUntilSlot >= slotNumber)
|
|
678
|
-
.filter(x => x.payload.epochToProve === epochToProve),
|
|
679
|
-
);
|
|
680
|
-
this.log.verbose(`Retrieved ${p2pQuotes.length} quotes for slot ${slotNumber} epoch ${epochToProve}`, {
|
|
681
|
-
epochToProve,
|
|
682
|
-
slotNumber,
|
|
683
|
-
quotes: p2pQuotes.map(q => q.payload),
|
|
684
|
-
});
|
|
685
|
-
if (!p2pQuotes.length) {
|
|
686
|
-
return undefined;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// ensure these quotes are still valid for the slot and have the contract validate them
|
|
690
|
-
const validQuotes = await this.publisher.filterValidQuotes(p2pQuotes);
|
|
691
|
-
|
|
692
|
-
if (!validQuotes.length) {
|
|
693
|
-
this.log.warn(`Failed to find any valid proof quotes`);
|
|
694
|
-
return undefined;
|
|
695
|
-
}
|
|
696
|
-
// pick the quote with the lowest fee
|
|
697
|
-
const sortedQuotes = validQuotes.sort(
|
|
698
|
-
(a: EpochProofQuote, b: EpochProofQuote) => a.payload.basisPointFee - b.payload.basisPointFee,
|
|
699
|
-
);
|
|
700
|
-
const quote = sortedQuotes[0];
|
|
701
|
-
this.log.info(`Selected proof quote for proof claim`, { quote: quote.toInspect() });
|
|
702
|
-
return quote;
|
|
703
|
-
} catch (err) {
|
|
704
|
-
this.log.error(`Failed to create proof claim for previous epoch`, err, { slotNumber });
|
|
705
|
-
return undefined;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
652
|
/**
|
|
710
653
|
* Publishes the L2Block to the rollup contract.
|
|
711
654
|
* @param block - The L2Block to be published.
|
|
@@ -734,29 +677,6 @@ export class Sequencer {
|
|
|
734
677
|
}
|
|
735
678
|
}
|
|
736
679
|
|
|
737
|
-
@trackSpan(
|
|
738
|
-
'Sequencer.claimEpochProofRightIfAvailable',
|
|
739
|
-
slotNumber => ({ [Attributes.SLOT_NUMBER]: Number(slotNumber) }),
|
|
740
|
-
epoch => ({ [Attributes.EPOCH_NUMBER]: Number(epoch) }),
|
|
741
|
-
)
|
|
742
|
-
/** Collects an epoch proof quote if there is an epoch to prove, and submits it to the L1 contract. */
|
|
743
|
-
protected async claimEpochProofRightIfAvailable(slotNumber: bigint) {
|
|
744
|
-
const proofQuote = await this.createProofClaimForPreviousEpoch(slotNumber);
|
|
745
|
-
if (proofQuote === undefined) {
|
|
746
|
-
return;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
const epoch = proofQuote.payload.epochToProve;
|
|
750
|
-
const ctx = { slotNumber, epoch, quote: proofQuote.toInspect() };
|
|
751
|
-
this.log.verbose(`Claiming proof right for epoch ${epoch}`, ctx);
|
|
752
|
-
const enqueued = this.publisher.enqueueClaimEpochProofRight(proofQuote);
|
|
753
|
-
if (!enqueued) {
|
|
754
|
-
throw new Error(`Failed to enqueue claim of proof right for epoch ${epoch}`);
|
|
755
|
-
}
|
|
756
|
-
this.log.info(`Enqueued claim of proof right for epoch ${epoch}`, ctx);
|
|
757
|
-
return epoch;
|
|
758
|
-
}
|
|
759
|
-
|
|
760
680
|
/**
|
|
761
681
|
* Returns whether all dependencies have caught up.
|
|
762
682
|
* We don't check against the previous block submitted since it may have been reorg'd out.
|
|
@@ -764,7 +684,12 @@ export class Sequencer {
|
|
|
764
684
|
*/
|
|
765
685
|
protected async getChainTip(): Promise<{ blockNumber: number; archive: Fr } | undefined> {
|
|
766
686
|
const syncedBlocks = await Promise.all([
|
|
767
|
-
this.worldState.status().then((s: WorldStateSynchronizerStatus) =>
|
|
687
|
+
this.worldState.status().then((s: WorldStateSynchronizerStatus) => {
|
|
688
|
+
return {
|
|
689
|
+
number: s.syncSummary.latestBlockNumber,
|
|
690
|
+
hash: s.syncSummary.latestBlockHash,
|
|
691
|
+
};
|
|
692
|
+
}),
|
|
768
693
|
this.l2BlockSource.getL2Tips().then(t => t.latest),
|
|
769
694
|
this.p2pClient.getStatus().then(p2p => p2p.syncedToL2Block),
|
|
770
695
|
this.l1ToL2MessageSource.getBlockNumber(),
|
|
@@ -806,7 +731,8 @@ export class Sequencer {
|
|
|
806
731
|
|
|
807
732
|
return { blockNumber: block.number, archive: block.archive.root };
|
|
808
733
|
} else {
|
|
809
|
-
|
|
734
|
+
const archive = new Fr((await this.worldState.getCommitted().getTreeInfo(MerkleTreeId.ARCHIVE)).root);
|
|
735
|
+
return { blockNumber: INITIAL_L2_BLOCK_NUM - 1, archive };
|
|
810
736
|
}
|
|
811
737
|
}
|
|
812
738
|
|
package/src/sequencer/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
2
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
3
|
+
import type { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
3
4
|
|
|
4
5
|
export enum SequencerState {
|
|
5
6
|
/**
|
package/src/slasher/factory.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { type L1ContractsConfig, type L1ReaderConfig } from '@aztec/ethereum';
|
|
1
|
+
import type { L1ContractsConfig, L1ReaderConfig } from '@aztec/ethereum';
|
|
3
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
4
|
+
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
6
5
|
import { createStore } from '@aztec/kv-store/lmdb-v2';
|
|
6
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
7
7
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
8
8
|
|
|
9
9
|
import { SlasherClient } from './slasher_client.js';
|
|
10
|
-
import {
|
|
10
|
+
import type { SlasherConfig } from './slasher_client.js';
|
|
11
11
|
|
|
12
12
|
export const createSlasherClient = async (
|
|
13
13
|
_config: SlasherConfig & DataStoreConfig & L1ContractsConfig & L1ReaderConfig,
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
2
|
+
import {
|
|
3
|
+
type L1ContractsConfig,
|
|
4
|
+
type L1ReaderConfig,
|
|
5
|
+
type ViemPublicClient,
|
|
6
|
+
createEthereumChain,
|
|
7
|
+
} from '@aztec/ethereum';
|
|
8
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
9
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
10
|
+
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncSingleton } from '@aztec/kv-store';
|
|
11
|
+
import { SlashFactoryAbi } from '@aztec/l1-artifacts';
|
|
1
12
|
import {
|
|
2
13
|
type L2Block,
|
|
3
14
|
type L2BlockId,
|
|
@@ -5,25 +16,10 @@ import {
|
|
|
5
16
|
L2BlockStream,
|
|
6
17
|
type L2BlockStreamEvent,
|
|
7
18
|
type L2Tips,
|
|
8
|
-
} from '@aztec/
|
|
9
|
-
import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants';
|
|
10
|
-
import { type L1ContractsConfig, type L1ReaderConfig, createEthereumChain } from '@aztec/ethereum';
|
|
11
|
-
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
12
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
13
|
-
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncSingleton } from '@aztec/kv-store';
|
|
14
|
-
import { SlashFactoryAbi } from '@aztec/l1-artifacts';
|
|
19
|
+
} from '@aztec/stdlib/block';
|
|
15
20
|
import { type TelemetryClient, WithTracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
16
21
|
|
|
17
|
-
import {
|
|
18
|
-
type Chain,
|
|
19
|
-
type GetContractReturnType,
|
|
20
|
-
type HttpTransport,
|
|
21
|
-
type PublicClient,
|
|
22
|
-
createPublicClient,
|
|
23
|
-
getAddress,
|
|
24
|
-
getContract,
|
|
25
|
-
http,
|
|
26
|
-
} from 'viem';
|
|
22
|
+
import { type GetContractReturnType, createPublicClient, fallback, getAddress, getContract, http } from 'viem';
|
|
27
23
|
|
|
28
24
|
/**
|
|
29
25
|
* Enum defining the possible states of the Slasher client.
|
|
@@ -100,8 +96,7 @@ export class SlasherClient extends WithTracer {
|
|
|
100
96
|
|
|
101
97
|
private slashEvents: SlashEvent[] = [];
|
|
102
98
|
|
|
103
|
-
protected slashFactoryContract?: GetContractReturnType<typeof SlashFactoryAbi,
|
|
104
|
-
undefined;
|
|
99
|
+
protected slashFactoryContract?: GetContractReturnType<typeof SlashFactoryAbi, ViemPublicClient> = undefined;
|
|
105
100
|
|
|
106
101
|
// The amount to slash for a prune.
|
|
107
102
|
// Note that we set it to 0, such that no actual slashing will happen, but the event will be fired,
|
|
@@ -127,10 +122,10 @@ export class SlasherClient extends WithTracer {
|
|
|
127
122
|
this.synchedProvenBlockNumber = store.openSingleton('slasher_last_proven_l2_block');
|
|
128
123
|
|
|
129
124
|
if (config.l1Contracts.slashFactoryAddress && config.l1Contracts.slashFactoryAddress !== EthAddress.ZERO) {
|
|
130
|
-
const chain = createEthereumChain(config.
|
|
125
|
+
const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
|
|
131
126
|
const publicClient = createPublicClient({
|
|
132
127
|
chain: chain.chainInfo,
|
|
133
|
-
transport:
|
|
128
|
+
transport: fallback(chain.rpcUrls.map(url => http(url))),
|
|
134
129
|
pollingInterval: config.viemPollingIntervalMS,
|
|
135
130
|
});
|
|
136
131
|
|
package/src/test/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
2
2
|
|
|
3
3
|
import { SequencerClient } from '../client/sequencer-client.js';
|
|
4
|
-
import {
|
|
4
|
+
import type { SequencerPublisher } from '../publisher/sequencer-publisher.js';
|
|
5
5
|
import { Sequencer } from '../sequencer/sequencer.js';
|
|
6
|
-
import {
|
|
6
|
+
import type { SequencerTimetable } from '../sequencer/timetable.js';
|
|
7
7
|
|
|
8
8
|
class TestSequencer_ extends Sequencer {
|
|
9
9
|
public override publicProcessorFactory!: PublicProcessorFactory;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import type { ArchiveSource } from '@aztec/p2p';
|
|
3
|
+
import type { MerkleTreeReadOperations } from '@aztec/stdlib/interfaces/server';
|
|
4
|
+
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Implements an archive source by checking a DB and an in-memory collection.
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type AztecAddress, Fr, FunctionSelector, type GasFees } from '@aztec/circuits.js';
|
|
3
|
-
import { U128 } from '@aztec/foundation/abi';
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
4
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
5
|
-
import { computeFeePayerBalanceStorageSlot
|
|
3
|
+
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
4
|
+
import { getExecutionRequestsByPhase } from '@aztec/simulator/server';
|
|
5
|
+
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
6
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
7
|
+
import type { GasFees } from '@aztec/stdlib/gas';
|
|
8
|
+
import { type Tx, TxExecutionPhase, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
6
9
|
|
|
7
10
|
/** Provides a view into public contract state */
|
|
8
11
|
export interface PublicStateSource {
|
|
@@ -13,23 +16,16 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
13
16
|
#log = createLogger('sequencer:tx_validator:tx_gas');
|
|
14
17
|
#publicDataSource: PublicStateSource;
|
|
15
18
|
#feeJuiceAddress: AztecAddress;
|
|
16
|
-
#enforceFees: boolean;
|
|
17
19
|
#gasFees: GasFees;
|
|
18
20
|
|
|
19
|
-
constructor(
|
|
20
|
-
publicDataSource: PublicStateSource,
|
|
21
|
-
feeJuiceAddress: AztecAddress,
|
|
22
|
-
enforceFees: boolean,
|
|
23
|
-
gasFees: GasFees,
|
|
24
|
-
) {
|
|
21
|
+
constructor(publicDataSource: PublicStateSource, feeJuiceAddress: AztecAddress, gasFees: GasFees) {
|
|
25
22
|
this.#publicDataSource = publicDataSource;
|
|
26
23
|
this.#feeJuiceAddress = feeJuiceAddress;
|
|
27
|
-
this.#enforceFees = enforceFees;
|
|
28
24
|
this.#gasFees = gasFees;
|
|
29
25
|
}
|
|
30
26
|
|
|
31
|
-
validateTx(tx: Tx): Promise<TxValidationResult> {
|
|
32
|
-
if (this.#shouldSkip(tx)) {
|
|
27
|
+
async validateTx(tx: Tx): Promise<TxValidationResult> {
|
|
28
|
+
if (await this.#shouldSkip(tx)) {
|
|
33
29
|
return Promise.resolve({ result: 'skipped', reason: ['Insufficient fee per gas'] });
|
|
34
30
|
}
|
|
35
31
|
return this.#validateTxFee(tx);
|
|
@@ -37,11 +33,11 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
37
33
|
|
|
38
34
|
/**
|
|
39
35
|
* Check whether the tx's max fees are valid for the current block, and skip if not.
|
|
40
|
-
* We skip instead of invalidating since the tx may become
|
|
36
|
+
* We skip instead of invalidating since the tx may become eligible later.
|
|
41
37
|
* Note that circuits check max fees even if fee payer is unset, so we
|
|
42
38
|
* keep this validation even if the tx does not pay fees.
|
|
43
39
|
*/
|
|
44
|
-
#shouldSkip(tx: Tx): boolean {
|
|
40
|
+
async #shouldSkip(tx: Tx): Promise<boolean> {
|
|
45
41
|
const gasSettings = tx.data.constants.txContext.gasSettings;
|
|
46
42
|
|
|
47
43
|
// Skip the tx if its max fees are not enough for the current block's gas fees.
|
|
@@ -51,22 +47,16 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
51
47
|
maxFeesPerGas.feePerL2Gas.lt(this.#gasFees.feePerL2Gas);
|
|
52
48
|
|
|
53
49
|
if (notEnoughMaxFees) {
|
|
54
|
-
this.#log.warn(`Skipping transaction ${tx.getTxHash()} due to insufficient fee per gas
|
|
50
|
+
this.#log.warn(`Skipping transaction ${await tx.getTxHash()} due to insufficient fee per gas`, {
|
|
51
|
+
txMaxFeesPerGas: maxFeesPerGas.toInspect(),
|
|
52
|
+
currentGasFees: this.#gasFees.toInspect(),
|
|
53
|
+
});
|
|
55
54
|
}
|
|
56
55
|
return notEnoughMaxFees;
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
async #validateTxFee(tx: Tx): Promise<TxValidationResult> {
|
|
60
59
|
const feePayer = tx.data.feePayer;
|
|
61
|
-
// TODO(@spalladino) Eventually remove the is_zero condition as we should always charge fees to every tx
|
|
62
|
-
if (feePayer.isZero()) {
|
|
63
|
-
if (this.#enforceFees) {
|
|
64
|
-
this.#log.warn(`Rejecting transaction ${tx.getTxHash()} due to missing fee payer`);
|
|
65
|
-
return { result: 'invalid', reason: ['Missing fee payer'] };
|
|
66
|
-
} else {
|
|
67
|
-
return { result: 'valid' };
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
60
|
|
|
71
61
|
// Compute the maximum fee that this tx may pay, based on its gasLimits and maxFeePerGas
|
|
72
62
|
const feeLimit = tx.data.constants.txContext.gasSettings.getFeeLimit();
|
|
@@ -80,7 +70,7 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
80
70
|
// If there is a claim in this tx that increases the fee payer balance in Fee Juice, add it to balance
|
|
81
71
|
const setupFns = getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP);
|
|
82
72
|
const increasePublicBalanceSelector = await FunctionSelector.fromSignature(
|
|
83
|
-
'_increase_public_balance((Field),
|
|
73
|
+
'_increase_public_balance((Field),u128)',
|
|
84
74
|
);
|
|
85
75
|
const claimFunctionCall = setupFns.find(
|
|
86
76
|
fn =>
|
|
@@ -93,10 +83,11 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
93
83
|
!fn.callContext.isStaticCall,
|
|
94
84
|
);
|
|
95
85
|
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
86
|
+
// The claim amount is at index 2 in the args array because:
|
|
87
|
+
// - Index 0: Target function selector (due to dispatch routing)
|
|
88
|
+
// - Index 1: Amount recipient
|
|
89
|
+
// - Index 2: Amount being claimed
|
|
90
|
+
const balance = claimFunctionCall ? initialBalance.add(claimFunctionCall.args[2]) : initialBalance;
|
|
100
91
|
if (balance.lt(feeLimit)) {
|
|
101
92
|
this.#log.warn(`Rejecting transaction due to not enough fee payer balance`, {
|
|
102
93
|
feePayer,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { NullifierSource } from '@aztec/p2p';
|
|
2
|
+
import type { MerkleTreeReadOperations } from '@aztec/stdlib/interfaces/server';
|
|
3
|
+
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Implements a nullifier source by checking a DB and an in-memory collection.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import { ContractsDataSourcePublicDB, getExecutionRequestsByPhase } from '@aztec/simulator/server';
|
|
3
|
+
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
4
|
+
import type { AllowedElement } from '@aztec/stdlib/interfaces/server';
|
|
1
5
|
import {
|
|
2
|
-
type AllowedElement,
|
|
3
6
|
type PublicExecutionRequest,
|
|
4
7
|
Tx,
|
|
5
8
|
TxExecutionPhase,
|
|
6
9
|
type TxValidationResult,
|
|
7
10
|
type TxValidator,
|
|
8
|
-
} from '@aztec/
|
|
9
|
-
import { type ContractDataSource } from '@aztec/circuits.js';
|
|
10
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
11
|
-
import { ContractsDataSourcePublicDB, getExecutionRequestsByPhase } from '@aztec/simulator/server';
|
|
11
|
+
} from '@aztec/stdlib/tx';
|
|
12
12
|
|
|
13
13
|
export class PhasesTxValidator implements TxValidator<Tx> {
|
|
14
14
|
#log = createLogger('sequencer:tx_validator:tx_phases');
|
|
@@ -78,14 +78,14 @@ export class PhasesTxValidator implements TxValidator<Tx> {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
if ('classId' in entry && !('selector' in entry)) {
|
|
81
|
-
if (contractClass.
|
|
81
|
+
if (contractClass.currentContractClassId.equals(entry.classId)) {
|
|
82
82
|
return true;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
if ('classId' in entry && 'selector' in entry) {
|
|
87
87
|
if (
|
|
88
|
-
contractClass.
|
|
88
|
+
contractClass.currentContractClassId.equals(entry.classId) &&
|
|
89
89
|
(entry.selector === undefined || entry.selector.equals(functionSelector))
|
|
90
90
|
) {
|
|
91
91
|
return true;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
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 { computeVarArgsHash } from '@aztec/stdlib/hash';
|
|
5
|
+
import type { Tx } from '@aztec/stdlib/tx';
|
|
4
6
|
|
|
5
7
|
export function patchNonRevertibleFn(
|
|
6
8
|
tx: Tx,
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AllowedElement,
|
|
3
|
-
type ClientProtocolCircuitVerifier,
|
|
4
|
-
type MerkleTreeReadOperations,
|
|
5
|
-
type ProcessedTx,
|
|
6
|
-
type Tx,
|
|
7
|
-
type TxValidator,
|
|
8
|
-
} from '@aztec/circuit-types';
|
|
9
|
-
import { type AztecAddress, type ContractDataSource, Fr, type GasFees, type GlobalVariables } from '@aztec/circuits.js';
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
10
2
|
import {
|
|
11
3
|
AggregateTxValidator,
|
|
12
4
|
BlockHeaderTxValidator,
|
|
@@ -17,6 +9,15 @@ import {
|
|
|
17
9
|
} from '@aztec/p2p';
|
|
18
10
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
19
11
|
import { readPublicState } from '@aztec/simulator/server';
|
|
12
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
13
|
+
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
14
|
+
import type { GasFees } from '@aztec/stdlib/gas';
|
|
15
|
+
import type {
|
|
16
|
+
AllowedElement,
|
|
17
|
+
ClientProtocolCircuitVerifier,
|
|
18
|
+
MerkleTreeReadOperations,
|
|
19
|
+
} from '@aztec/stdlib/interfaces/server';
|
|
20
|
+
import { GlobalVariables, type ProcessedTx, type Tx, type TxValidator } from '@aztec/stdlib/tx';
|
|
20
21
|
|
|
21
22
|
import { ArchiveCache } from './archive_cache.js';
|
|
22
23
|
import { GasTxValidator, type PublicStateSource } from './gas_validator.js';
|
|
@@ -27,24 +28,32 @@ export function createValidatorForAcceptingTxs(
|
|
|
27
28
|
db: MerkleTreeReadOperations,
|
|
28
29
|
contractDataSource: ContractDataSource,
|
|
29
30
|
verifier: ClientProtocolCircuitVerifier | undefined,
|
|
30
|
-
|
|
31
|
+
{
|
|
32
|
+
blockNumber,
|
|
33
|
+
l1ChainId,
|
|
34
|
+
setupAllowList,
|
|
35
|
+
gasFees,
|
|
36
|
+
skipFeeEnforcement,
|
|
37
|
+
}: {
|
|
31
38
|
blockNumber: number;
|
|
32
39
|
l1ChainId: number;
|
|
33
|
-
enforceFees: boolean;
|
|
34
40
|
setupAllowList: AllowedElement[];
|
|
35
41
|
gasFees: GasFees;
|
|
42
|
+
skipFeeEnforcement?: boolean;
|
|
36
43
|
},
|
|
37
44
|
): TxValidator<Tx> {
|
|
38
|
-
const { blockNumber, l1ChainId, enforceFees, setupAllowList, gasFees } = data;
|
|
39
45
|
const validators: TxValidator<Tx>[] = [
|
|
40
46
|
new DataTxValidator(),
|
|
41
47
|
new MetadataTxValidator(new Fr(l1ChainId), new Fr(blockNumber)),
|
|
42
48
|
new DoubleSpendTxValidator(new NullifierCache(db)),
|
|
43
49
|
new PhasesTxValidator(contractDataSource, setupAllowList),
|
|
44
|
-
new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, enforceFees, gasFees),
|
|
45
50
|
new BlockHeaderTxValidator(new ArchiveCache(db)),
|
|
46
51
|
];
|
|
47
52
|
|
|
53
|
+
if (!skipFeeEnforcement) {
|
|
54
|
+
validators.push(new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, gasFees));
|
|
55
|
+
}
|
|
56
|
+
|
|
48
57
|
if (verifier) {
|
|
49
58
|
validators.push(new TxProofValidator(verifier));
|
|
50
59
|
}
|
|
@@ -56,7 +65,6 @@ export function createValidatorsForBlockBuilding(
|
|
|
56
65
|
db: MerkleTreeReadOperations,
|
|
57
66
|
contractDataSource: ContractDataSource,
|
|
58
67
|
globalVariables: GlobalVariables,
|
|
59
|
-
enforceFees: boolean,
|
|
60
68
|
setupAllowList: AllowedElement[],
|
|
61
69
|
): {
|
|
62
70
|
preprocessValidator: TxValidator<Tx>;
|
|
@@ -73,7 +81,6 @@ export function createValidatorsForBlockBuilding(
|
|
|
73
81
|
archiveCache,
|
|
74
82
|
publicStateSource,
|
|
75
83
|
contractDataSource,
|
|
76
|
-
enforceFees,
|
|
77
84
|
globalVariables,
|
|
78
85
|
setupAllowList,
|
|
79
86
|
),
|
|
@@ -95,7 +102,6 @@ function preprocessValidator(
|
|
|
95
102
|
archiveCache: ArchiveCache,
|
|
96
103
|
publicStateSource: PublicStateSource,
|
|
97
104
|
contractDataSource: ContractDataSource,
|
|
98
|
-
enforceFees: boolean,
|
|
99
105
|
globalVariables: GlobalVariables,
|
|
100
106
|
setupAllowList: AllowedElement[],
|
|
101
107
|
): TxValidator<Tx> {
|
|
@@ -104,7 +110,7 @@ function preprocessValidator(
|
|
|
104
110
|
new MetadataTxValidator(globalVariables.chainId, globalVariables.blockNumber),
|
|
105
111
|
new DoubleSpendTxValidator(nullifierCache),
|
|
106
112
|
new PhasesTxValidator(contractDataSource, setupAllowList),
|
|
107
|
-
new GasTxValidator(publicStateSource, ProtocolContractAddress.FeeJuice,
|
|
113
|
+
new GasTxValidator(publicStateSource, ProtocolContractAddress.FeeJuice, globalVariables.gasFees),
|
|
108
114
|
new BlockHeaderTxValidator(archiveCache),
|
|
109
115
|
);
|
|
110
116
|
}
|