@aztec/sequencer-client 0.47.1 → 0.49.2
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/block_builder/index.d.ts +26 -0
- package/dest/block_builder/index.d.ts.map +1 -0
- package/dest/block_builder/index.js +40 -0
- package/dest/client/sequencer-client.d.ts +1 -2
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +5 -4
- package/dest/config.d.ts +6 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +91 -31
- package/dest/global_variable_builder/global_builder.d.ts +14 -8
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +10 -16
- package/dest/global_variable_builder/index.d.ts +2 -3
- package/dest/global_variable_builder/index.d.ts.map +1 -1
- package/dest/global_variable_builder/index.js +1 -1
- package/dest/global_variable_builder/viem-reader.d.ts +5 -4
- package/dest/global_variable_builder/viem-reader.d.ts.map +1 -1
- package/dest/global_variable_builder/viem-reader.js +11 -8
- package/dest/publisher/config.d.ts +7 -15
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +38 -11
- package/dest/publisher/index.d.ts +3 -2
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/index.js +4 -4
- package/dest/publisher/l1-publisher-metrics.d.ts +17 -0
- package/dest/publisher/l1-publisher-metrics.d.ts.map +1 -0
- package/dest/publisher/l1-publisher-metrics.js +75 -0
- package/dest/publisher/l1-publisher.d.ts +33 -5
- package/dest/publisher/l1-publisher.d.ts.map +1 -1
- package/dest/publisher/l1-publisher.js +44 -36
- package/dest/publisher/viem-tx-sender.d.ts +9 -2
- package/dest/publisher/viem-tx-sender.d.ts.map +1 -1
- package/dest/publisher/viem-tx-sender.js +85 -16
- package/dest/receiver.d.ts +2 -8
- package/dest/receiver.d.ts.map +1 -1
- package/dest/sequencer/metrics.d.ts +17 -0
- package/dest/sequencer/metrics.d.ts.map +1 -0
- package/dest/sequencer/metrics.js +56 -0
- package/dest/sequencer/sequencer.d.ts +9 -7
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +66 -37
- package/dest/tx_validator/gas_validator.d.ts +1 -1
- package/dest/tx_validator/gas_validator.js +11 -11
- package/dest/tx_validator/tx_validator_factory.js +2 -2
- package/package.json +17 -15
- package/src/block_builder/index.ts +51 -0
- package/src/client/sequencer-client.ts +3 -4
- package/src/config.ts +106 -54
- package/src/global_variable_builder/global_builder.ts +35 -25
- package/src/global_variable_builder/index.ts +3 -3
- package/src/global_variable_builder/viem-reader.ts +14 -11
- package/src/publisher/config.ts +43 -31
- package/src/publisher/index.ts +5 -3
- package/src/publisher/l1-publisher-metrics.ts +108 -0
- package/src/publisher/l1-publisher.ts +78 -43
- package/src/publisher/viem-tx-sender.ts +89 -14
- package/src/receiver.ts +3 -8
- package/src/sequencer/metrics.ts +86 -0
- package/src/sequencer/sequencer.ts +89 -52
- package/src/tx_validator/gas_validator.ts +9 -9
- package/src/tx_validator/tx_validator_factory.ts +2 -2
- package/dest/global_variable_builder/config.d.ts +0 -19
- package/dest/global_variable_builder/config.d.ts.map +0 -1
- package/dest/global_variable_builder/config.js +0 -2
- package/src/global_variable_builder/config.ts +0 -20
package/src/config.ts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import { type AllowedElement } from '@aztec/circuit-types';
|
|
2
2
|
import { AztecAddress, Fr, FunctionSelector, getContractClassFromArtifact } from '@aztec/circuits.js';
|
|
3
|
-
import {
|
|
3
|
+
import { type L1ReaderConfig, l1ReaderConfigMappings } from '@aztec/ethereum';
|
|
4
|
+
import {
|
|
5
|
+
type ConfigMappingsType,
|
|
6
|
+
booleanConfigHelper,
|
|
7
|
+
getConfigFromMappings,
|
|
8
|
+
numberConfigHelper,
|
|
9
|
+
} from '@aztec/foundation/config';
|
|
4
10
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
11
|
import { FPCContract } from '@aztec/noir-contracts.js/FPC';
|
|
6
12
|
import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
|
|
7
13
|
import { AuthRegistryAddress } from '@aztec/protocol-contracts/auth-registry';
|
|
8
|
-
import {
|
|
14
|
+
import { FeeJuiceAddress } from '@aztec/protocol-contracts/fee-juice';
|
|
9
15
|
|
|
10
|
-
import {
|
|
11
|
-
|
|
16
|
+
import {
|
|
17
|
+
type PublisherConfig,
|
|
18
|
+
type TxSenderConfig,
|
|
19
|
+
getPublisherConfigMappings,
|
|
20
|
+
getTxSenderConfigMappings,
|
|
21
|
+
} from './publisher/config.js';
|
|
12
22
|
import { type SequencerConfig } from './sequencer/config.js';
|
|
13
23
|
|
|
14
24
|
/** Chain configuration. */
|
|
@@ -22,60 +32,102 @@ type ChainConfig = {
|
|
|
22
32
|
/**
|
|
23
33
|
* Configuration settings for the SequencerClient.
|
|
24
34
|
*/
|
|
25
|
-
export type SequencerClientConfig = PublisherConfig &
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
export type SequencerClientConfig = PublisherConfig & TxSenderConfig & SequencerConfig & L1ReaderConfig & ChainConfig;
|
|
36
|
+
|
|
37
|
+
export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
|
|
38
|
+
transactionPollingIntervalMS: {
|
|
39
|
+
env: 'SEQ_TX_POLLING_INTERVAL_MS',
|
|
40
|
+
description: 'The number of ms to wait between polling for pending txs.',
|
|
41
|
+
...numberConfigHelper(1_000),
|
|
42
|
+
},
|
|
43
|
+
maxTxsPerBlock: {
|
|
44
|
+
env: 'SEQ_MAX_TX_PER_BLOCK',
|
|
45
|
+
description: 'The maximum number of txs to include in a block.',
|
|
46
|
+
...numberConfigHelper(32),
|
|
47
|
+
},
|
|
48
|
+
minTxsPerBlock: {
|
|
49
|
+
env: 'SEQ_MIN_TX_PER_BLOCK',
|
|
50
|
+
description: 'The minimum number of txs to include in a block.',
|
|
51
|
+
...numberConfigHelper(1),
|
|
52
|
+
},
|
|
53
|
+
minSecondsBetweenBlocks: {
|
|
54
|
+
env: 'SEQ_MIN_SECONDS_BETWEEN_BLOCKS',
|
|
55
|
+
description: 'The minimum number of seconds in-between consecutive blocks.',
|
|
56
|
+
...numberConfigHelper(0),
|
|
57
|
+
},
|
|
58
|
+
maxSecondsBetweenBlocks: {
|
|
59
|
+
env: 'SEQ_MAX_SECONDS_BETWEEN_BLOCKS',
|
|
60
|
+
description:
|
|
61
|
+
'The maximum number of seconds in-between consecutive blocks. Sequencer will produce a block with less than minTxsPerBlock once this threshold is reached.',
|
|
62
|
+
...numberConfigHelper(0),
|
|
63
|
+
},
|
|
64
|
+
coinbase: {
|
|
65
|
+
env: 'COINBASE',
|
|
66
|
+
parseEnv: (val: string) => EthAddress.fromString(val),
|
|
67
|
+
description: 'Recipient of block reward.',
|
|
68
|
+
},
|
|
69
|
+
feeRecipient: {
|
|
70
|
+
env: 'FEE_RECIPIENT',
|
|
71
|
+
parseEnv: (val: string) => AztecAddress.fromString(val),
|
|
72
|
+
description: 'Address to receive fees.',
|
|
73
|
+
},
|
|
74
|
+
acvmWorkingDirectory: {
|
|
75
|
+
env: 'ACVM_WORKING_DIRECTORY',
|
|
76
|
+
description: 'The working directory to use for simulation/proving',
|
|
77
|
+
},
|
|
78
|
+
acvmBinaryPath: {
|
|
79
|
+
env: 'ACVM_BINARY_PATH',
|
|
80
|
+
description: 'The path to the ACVM binary',
|
|
81
|
+
},
|
|
82
|
+
allowedInSetup: {
|
|
83
|
+
env: 'SEQ_ALLOWED_SETUP_FN',
|
|
84
|
+
parseEnv: (val: string) => parseSequencerAllowList(val),
|
|
85
|
+
defaultValue: getDefaultAllowedSetupFunctions(),
|
|
86
|
+
description: 'The list of functions calls allowed to run in setup',
|
|
87
|
+
printDefault: () =>
|
|
88
|
+
'AuthRegistry, FeeJuice.increase_public_balance, Token.increase_public_balance, FPC.prepare_fee',
|
|
89
|
+
},
|
|
90
|
+
allowedInTeardown: {
|
|
91
|
+
env: 'SEQ_ALLOWED_TEARDOWN_FN',
|
|
92
|
+
parseEnv: (val: string) => parseSequencerAllowList(val),
|
|
93
|
+
defaultValue: getDefaultAllowedTeardownFunctions(),
|
|
94
|
+
description: 'The list of functions calls allowed to run teardown',
|
|
95
|
+
printDefault: () => 'FPC.pay_refund, FPC.pay_refund_with_shielded_rebate',
|
|
96
|
+
},
|
|
97
|
+
maxBlockSizeInBytes: {
|
|
98
|
+
env: 'SEQ_MAX_BLOCK_SIZE_IN_BYTES',
|
|
99
|
+
description: 'Max block size',
|
|
100
|
+
...numberConfigHelper(1024 * 1024),
|
|
101
|
+
},
|
|
102
|
+
enforceFees: {
|
|
103
|
+
env: 'ENFORCE_FEES',
|
|
104
|
+
description: 'Whether to require every tx to have a fee payer',
|
|
105
|
+
...booleanConfigHelper(),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const chainConfigMappings: ConfigMappingsType<ChainConfig> = {
|
|
110
|
+
l1ChainId: l1ReaderConfigMappings.l1ChainId,
|
|
111
|
+
version: {
|
|
112
|
+
env: 'VERSION',
|
|
113
|
+
description: 'The version of the rollup.',
|
|
114
|
+
...numberConfigHelper(1),
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const sequencerClientConfigMappings: ConfigMappingsType<SequencerClientConfig> = {
|
|
119
|
+
...sequencerConfigMappings,
|
|
120
|
+
...getTxSenderConfigMappings('SEQ'),
|
|
121
|
+
...getPublisherConfigMappings('SEQ'),
|
|
122
|
+
...l1ReaderConfigMappings,
|
|
123
|
+
...chainConfigMappings,
|
|
124
|
+
};
|
|
30
125
|
|
|
31
126
|
/**
|
|
32
127
|
* Creates an instance of SequencerClientConfig out of environment variables using sensible defaults for integration testing if not set.
|
|
33
128
|
*/
|
|
34
129
|
export function getConfigEnvVars(): SequencerClientConfig {
|
|
35
|
-
|
|
36
|
-
VERSION,
|
|
37
|
-
SEQ_PUBLISH_RETRY_INTERVAL_MS,
|
|
38
|
-
SEQ_TX_POLLING_INTERVAL_MS,
|
|
39
|
-
SEQ_MAX_TX_PER_BLOCK,
|
|
40
|
-
SEQ_MIN_TX_PER_BLOCK,
|
|
41
|
-
SEQ_MAX_SECONDS_BETWEEN_BLOCKS,
|
|
42
|
-
SEQ_MIN_SECONDS_BETWEEN_BLOCKS,
|
|
43
|
-
SEQ_ALLOWED_SETUP_FN,
|
|
44
|
-
SEQ_ALLOWED_TEARDOWN_FN,
|
|
45
|
-
SEQ_MAX_BLOCK_SIZE_IN_BYTES,
|
|
46
|
-
SEQ_SKIP_SUBMIT_PROOFS,
|
|
47
|
-
COINBASE,
|
|
48
|
-
FEE_RECIPIENT,
|
|
49
|
-
ACVM_WORKING_DIRECTORY,
|
|
50
|
-
ACVM_BINARY_PATH,
|
|
51
|
-
ENFORCE_FEES = '',
|
|
52
|
-
} = process.env;
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
enforceFees: ['1', 'true'].includes(ENFORCE_FEES),
|
|
56
|
-
version: VERSION ? +VERSION : 1, // 1 is our default version
|
|
57
|
-
l1PublishRetryIntervalMS: SEQ_PUBLISH_RETRY_INTERVAL_MS ? +SEQ_PUBLISH_RETRY_INTERVAL_MS : 1_000,
|
|
58
|
-
transactionPollingIntervalMS: SEQ_TX_POLLING_INTERVAL_MS ? +SEQ_TX_POLLING_INTERVAL_MS : 1_000,
|
|
59
|
-
maxBlockSizeInBytes: SEQ_MAX_BLOCK_SIZE_IN_BYTES ? +SEQ_MAX_BLOCK_SIZE_IN_BYTES : undefined,
|
|
60
|
-
l1Contracts: getL1ContractAddressesFromEnv(),
|
|
61
|
-
maxTxsPerBlock: SEQ_MAX_TX_PER_BLOCK ? +SEQ_MAX_TX_PER_BLOCK : 32,
|
|
62
|
-
minTxsPerBlock: SEQ_MIN_TX_PER_BLOCK ? +SEQ_MIN_TX_PER_BLOCK : 1,
|
|
63
|
-
maxSecondsBetweenBlocks: SEQ_MAX_SECONDS_BETWEEN_BLOCKS ? +SEQ_MAX_SECONDS_BETWEEN_BLOCKS : 0,
|
|
64
|
-
minSecondsBetweenBlocks: SEQ_MIN_SECONDS_BETWEEN_BLOCKS ? +SEQ_MIN_SECONDS_BETWEEN_BLOCKS : 0,
|
|
65
|
-
sequencerSkipSubmitProofs: ['1', 'true'].includes(SEQ_SKIP_SUBMIT_PROOFS ?? ''),
|
|
66
|
-
// TODO: undefined should not be allowed for the following 2 values in PROD
|
|
67
|
-
coinbase: COINBASE ? EthAddress.fromString(COINBASE) : undefined,
|
|
68
|
-
feeRecipient: FEE_RECIPIENT ? AztecAddress.fromString(FEE_RECIPIENT) : undefined,
|
|
69
|
-
acvmWorkingDirectory: ACVM_WORKING_DIRECTORY ? ACVM_WORKING_DIRECTORY : undefined,
|
|
70
|
-
acvmBinaryPath: ACVM_BINARY_PATH ? ACVM_BINARY_PATH : undefined,
|
|
71
|
-
allowedInSetup: SEQ_ALLOWED_SETUP_FN
|
|
72
|
-
? parseSequencerAllowList(SEQ_ALLOWED_SETUP_FN)
|
|
73
|
-
: getDefaultAllowedSetupFunctions(),
|
|
74
|
-
allowedInTeardown: SEQ_ALLOWED_TEARDOWN_FN
|
|
75
|
-
? parseSequencerAllowList(SEQ_ALLOWED_TEARDOWN_FN)
|
|
76
|
-
: getDefaultAllowedTeardownFunctions(),
|
|
77
|
-
...getTxSenderConfigFromEnv('SEQ'),
|
|
78
|
-
};
|
|
130
|
+
return getConfigFromMappings<SequencerClientConfig>(sequencerClientConfigMappings);
|
|
79
131
|
}
|
|
80
132
|
|
|
81
133
|
/**
|
|
@@ -136,7 +188,7 @@ function getDefaultAllowedSetupFunctions(): AllowedElement[] {
|
|
|
136
188
|
},
|
|
137
189
|
// needed for claiming on the same tx as a spend
|
|
138
190
|
{
|
|
139
|
-
address:
|
|
191
|
+
address: FeeJuiceAddress,
|
|
140
192
|
selector: FunctionSelector.fromSignature('_increase_public_balance((Field),Field)'),
|
|
141
193
|
},
|
|
142
194
|
// needed for private transfers via FPC
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AztecAddress,
|
|
3
|
+
ETHEREUM_SLOT_DURATION,
|
|
4
|
+
type EthAddress,
|
|
5
|
+
GasFees,
|
|
6
|
+
GlobalVariables,
|
|
7
|
+
} from '@aztec/circuits.js';
|
|
2
8
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
9
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
10
|
|
|
@@ -6,11 +12,6 @@ import { createDebugLogger } from '@aztec/foundation/log';
|
|
|
6
12
|
* Reads values from L1 state that is used for the global values.
|
|
7
13
|
*/
|
|
8
14
|
export interface L1GlobalReader {
|
|
9
|
-
/**
|
|
10
|
-
* Fetches the last timestamp that a block was processed by the contract.
|
|
11
|
-
* @returns The last timestamp that a block was processed by the contract.
|
|
12
|
-
*/
|
|
13
|
-
getLastTimestamp(): Promise<bigint>;
|
|
14
15
|
/**
|
|
15
16
|
* Fetches the version of the rollup contract.
|
|
16
17
|
* @returns The version of the rollup contract.
|
|
@@ -29,10 +30,23 @@ export interface L1GlobalReader {
|
|
|
29
30
|
getL1CurrentTime(): Promise<bigint>;
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
|
-
* Gets the
|
|
33
|
-
* @returns The
|
|
33
|
+
* Gets the current slot.
|
|
34
|
+
* @returns The current slot.
|
|
34
35
|
*/
|
|
35
|
-
|
|
36
|
+
getCurrentSlot(): Promise<bigint>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the slot for a specific timestamp.
|
|
40
|
+
* @param timestamp - The timestamp to get the slot for.
|
|
41
|
+
*/
|
|
42
|
+
getSlotAt(timestamp: readonly [bigint]): Promise<bigint>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gets the timestamp for a slot
|
|
46
|
+
* @param slot - The slot to get the timestamp for.
|
|
47
|
+
* @returns The timestamp for the slot.
|
|
48
|
+
*/
|
|
49
|
+
getTimestampForSlot(slot: readonly [bigint]): Promise<bigint>;
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
/**
|
|
@@ -69,34 +83,30 @@ export class SimpleTestGlobalVariableBuilder implements GlobalVariableBuilder {
|
|
|
69
83
|
coinbase: EthAddress,
|
|
70
84
|
feeRecipient: AztecAddress,
|
|
71
85
|
): Promise<GlobalVariables> {
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
const chainId = new Fr(await this.reader.getChainId());
|
|
86
|
+
// Not just the current slot, the slot of the next block.
|
|
87
|
+
const ts = (await this.reader.getL1CurrentTime()) + BigInt(ETHEREUM_SLOT_DURATION);
|
|
75
88
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// So, for now you check if L2 time was warped and if so, serve warpedTime + 1 to txs in the new rollup.
|
|
79
|
-
// Check if L2 time was warped in the last rollup by checking if current L1 time is same as the warpedTime (stored on the rollup contract).
|
|
80
|
-
// more details at https://github.com/AztecProtocol/aztec-packages/issues/1614
|
|
89
|
+
const slot = await this.reader.getSlotAt([ts]);
|
|
90
|
+
const timestamp = await this.reader.getTimestampForSlot([slot]);
|
|
81
91
|
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
92
|
+
const slotFr = new Fr(slot);
|
|
93
|
+
const timestampFr = new Fr(timestamp);
|
|
94
|
+
|
|
95
|
+
const version = new Fr(await this.reader.getVersion());
|
|
96
|
+
const chainId = new Fr(await this.reader.getChainId());
|
|
88
97
|
|
|
89
98
|
const gasFees = GasFees.default();
|
|
90
99
|
const globalVariables = new GlobalVariables(
|
|
91
100
|
chainId,
|
|
92
101
|
version,
|
|
93
102
|
blockNumber,
|
|
94
|
-
|
|
103
|
+
slotFr,
|
|
104
|
+
timestampFr,
|
|
95
105
|
coinbase,
|
|
96
106
|
feeRecipient,
|
|
97
107
|
gasFees,
|
|
98
108
|
);
|
|
99
109
|
this.log.debug(`Built global variables for block ${blockNumber}`, globalVariables.toJSON());
|
|
100
|
-
return
|
|
110
|
+
return globalVariables;
|
|
101
111
|
}
|
|
102
112
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type L1ReaderConfig } from '@aztec/ethereum';
|
|
2
|
+
|
|
2
3
|
import { type GlobalVariableBuilder, SimpleTestGlobalVariableBuilder } from './global_builder.js';
|
|
3
4
|
import { ViemReader } from './viem-reader.js';
|
|
4
5
|
|
|
5
6
|
export { SimpleTestGlobalVariableBuilder as SimpleGlobalVariableBuilder } from './global_builder.js';
|
|
6
|
-
export { GlobalReaderConfig } from './config.js';
|
|
7
7
|
export { GlobalVariableBuilder } from './global_builder.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -11,6 +11,6 @@ export { GlobalVariableBuilder } from './global_builder.js';
|
|
|
11
11
|
* @param config - Configuration to initialize the builder.
|
|
12
12
|
* @returns A new instance of the global variable builder.
|
|
13
13
|
*/
|
|
14
|
-
export function getGlobalVariableBuilder(config:
|
|
14
|
+
export function getGlobalVariableBuilder(config: L1ReaderConfig): GlobalVariableBuilder {
|
|
15
15
|
return new SimpleTestGlobalVariableBuilder(new ViemReader(config));
|
|
16
16
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createEthereumChain } from '@aztec/ethereum';
|
|
1
|
+
import { type L1ReaderConfig, createEthereumChain } from '@aztec/ethereum';
|
|
2
2
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
} from 'viem';
|
|
13
13
|
import type * as chains from 'viem/chains';
|
|
14
14
|
|
|
15
|
-
import { type GlobalReaderConfig } from './config.js';
|
|
16
15
|
import { type L1GlobalReader } from './global_builder.js';
|
|
17
16
|
|
|
18
17
|
/**
|
|
@@ -22,10 +21,10 @@ export class ViemReader implements L1GlobalReader {
|
|
|
22
21
|
private rollupContract: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, chains.Chain>>;
|
|
23
22
|
private publicClient: PublicClient<HttpTransport, chains.Chain>;
|
|
24
23
|
|
|
25
|
-
constructor(config:
|
|
26
|
-
const {
|
|
24
|
+
constructor(config: L1ReaderConfig) {
|
|
25
|
+
const { l1RpcUrl, l1ChainId: chainId, l1Contracts } = config;
|
|
27
26
|
|
|
28
|
-
const chain = createEthereumChain(
|
|
27
|
+
const chain = createEthereumChain(l1RpcUrl, chainId);
|
|
29
28
|
|
|
30
29
|
this.publicClient = createPublicClient({
|
|
31
30
|
chain: chain.chainInfo,
|
|
@@ -39,10 +38,6 @@ export class ViemReader implements L1GlobalReader {
|
|
|
39
38
|
});
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
public async getLastTimestamp(): Promise<bigint> {
|
|
43
|
-
return BigInt(await this.rollupContract.read.lastBlockTs());
|
|
44
|
-
}
|
|
45
|
-
|
|
46
41
|
public async getVersion(): Promise<bigint> {
|
|
47
42
|
return BigInt(await this.rollupContract.read.VERSION());
|
|
48
43
|
}
|
|
@@ -55,7 +50,15 @@ export class ViemReader implements L1GlobalReader {
|
|
|
55
50
|
return await Promise.resolve((await this.publicClient.getBlock()).timestamp);
|
|
56
51
|
}
|
|
57
52
|
|
|
58
|
-
public async
|
|
59
|
-
return BigInt(await this.rollupContract.read.
|
|
53
|
+
public async getCurrentSlot(): Promise<bigint> {
|
|
54
|
+
return BigInt(await this.rollupContract.read.getCurrentSlot());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public async getSlotAt(timestamp: readonly [bigint]): Promise<bigint> {
|
|
58
|
+
return BigInt(await this.rollupContract.read.getSlotAt(timestamp));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async getTimestampForSlot(slot: readonly [bigint]): Promise<bigint> {
|
|
62
|
+
return BigInt(await this.rollupContract.read.getTimestampForSlot(slot));
|
|
60
63
|
}
|
|
61
64
|
}
|
package/src/publisher/config.ts
CHANGED
|
@@ -1,36 +1,20 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
|
|
3
|
-
import { type Hex } from 'viem';
|
|
1
|
+
import { type L1ReaderConfig, NULL_KEY } from '@aztec/ethereum';
|
|
2
|
+
import { type ConfigMappingsType, getConfigFromMappings } from '@aztec/foundation/config';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* The configuration of the rollup transaction publisher.
|
|
7
6
|
*/
|
|
8
|
-
export
|
|
7
|
+
export type TxSenderConfig = L1ReaderConfig & {
|
|
9
8
|
/**
|
|
10
9
|
* The private key to be used by the publisher.
|
|
11
10
|
*/
|
|
12
11
|
publisherPrivateKey: `0x${string}`;
|
|
13
12
|
|
|
14
|
-
/**
|
|
15
|
-
* The RPC Url of the ethereum host.
|
|
16
|
-
*/
|
|
17
|
-
rpcUrl: string;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* The chain ID of the ethereum host.
|
|
21
|
-
*/
|
|
22
|
-
l1ChainId: number;
|
|
23
|
-
|
|
24
13
|
/**
|
|
25
14
|
* The number of confirmations required.
|
|
26
15
|
*/
|
|
27
16
|
requiredConfirmations: number;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* The deployed l1 contract addresses
|
|
31
|
-
*/
|
|
32
|
-
l1Contracts: L1ContractAddresses;
|
|
33
|
-
}
|
|
17
|
+
};
|
|
34
18
|
|
|
35
19
|
/**
|
|
36
20
|
* Configuration of the L1Publisher.
|
|
@@ -42,18 +26,46 @@ export interface PublisherConfig {
|
|
|
42
26
|
l1PublishRetryIntervalMS: number;
|
|
43
27
|
}
|
|
44
28
|
|
|
45
|
-
export
|
|
46
|
-
|
|
29
|
+
export const getTxSenderConfigMappings: (
|
|
30
|
+
scope: 'PROVER' | 'SEQ',
|
|
31
|
+
) => ConfigMappingsType<Omit<TxSenderConfig, 'l1Contracts'>> = (scope: 'PROVER' | 'SEQ') => ({
|
|
32
|
+
l1RpcUrl: {
|
|
33
|
+
env: 'ETHEREUM_HOST',
|
|
34
|
+
description: 'The RPC Url of the ethereum host.',
|
|
35
|
+
},
|
|
36
|
+
l1ChainId: {
|
|
37
|
+
env: 'L1_CHAIN_ID',
|
|
38
|
+
parseEnv: (val: string) => +val,
|
|
39
|
+
defaultValue: 31337,
|
|
40
|
+
description: 'The chain ID of the ethereum host.',
|
|
41
|
+
},
|
|
42
|
+
publisherPrivateKey: {
|
|
43
|
+
env: `${scope}_PUBLISHER_PRIVATE_KEY`,
|
|
44
|
+
description: 'The private key to be used by the publisher.',
|
|
45
|
+
parseEnv: (val: string) => (val ? `0x${val.replace('0x', '')}` : NULL_KEY),
|
|
46
|
+
defaultValue: NULL_KEY,
|
|
47
|
+
},
|
|
48
|
+
requiredConfirmations: {
|
|
49
|
+
env: `${scope}_REQUIRED_CONFIRMATIONS`,
|
|
50
|
+
parseEnv: (val: string) => +val,
|
|
51
|
+
defaultValue: 1,
|
|
52
|
+
description: 'The number of confirmations required.',
|
|
53
|
+
},
|
|
54
|
+
});
|
|
47
55
|
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
export function getTxSenderConfigFromEnv(scope: 'PROVER' | 'SEQ'): Omit<TxSenderConfig, 'l1Contracts'> {
|
|
57
|
+
return getConfigFromMappings(getTxSenderConfigMappings(scope));
|
|
58
|
+
}
|
|
50
59
|
|
|
51
|
-
|
|
60
|
+
export const getPublisherConfigMappings: (scope: 'PROVER' | 'SEQ') => ConfigMappingsType<PublisherConfig> = scope => ({
|
|
61
|
+
l1PublishRetryIntervalMS: {
|
|
62
|
+
env: `${scope}_PUBLISH_RETRY_INTERVAL_MS`,
|
|
63
|
+
parseEnv: (val: string) => +val,
|
|
64
|
+
defaultValue: 1000,
|
|
65
|
+
description: 'The interval to wait between publish retries.',
|
|
66
|
+
},
|
|
67
|
+
});
|
|
52
68
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
requiredConfirmations: REQUIRED_CONFIRMATIONS ? +REQUIRED_CONFIRMATIONS : 1,
|
|
56
|
-
publisherPrivateKey,
|
|
57
|
-
l1ChainId: L1_CHAIN_ID ? +L1_CHAIN_ID : 31337,
|
|
58
|
-
};
|
|
69
|
+
export function getPublisherConfigFromEnv(scope: 'PROVER' | 'SEQ'): PublisherConfig {
|
|
70
|
+
return getConfigFromMappings(getPublisherConfigMappings(scope));
|
|
59
71
|
}
|
package/src/publisher/index.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
2
|
+
|
|
1
3
|
import { type PublisherConfig, type TxSenderConfig } from './config.js';
|
|
2
4
|
import { L1Publisher } from './l1-publisher.js';
|
|
3
5
|
import { ViemTxSender } from './viem-tx-sender.js';
|
|
4
6
|
|
|
5
7
|
export { L1Publisher } from './l1-publisher.js';
|
|
6
|
-
export
|
|
8
|
+
export * from './config.js';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Returns a new instance of the L1Publisher.
|
|
10
12
|
* @param config - Configuration to initialize the new instance.
|
|
11
13
|
*/
|
|
12
|
-
export function getL1Publisher(config: PublisherConfig & TxSenderConfig): L1Publisher {
|
|
13
|
-
return new L1Publisher(new ViemTxSender(config), config);
|
|
14
|
+
export function getL1Publisher(config: PublisherConfig & TxSenderConfig, client: TelemetryClient): L1Publisher {
|
|
15
|
+
return new L1Publisher(new ViemTxSender(config), client, config);
|
|
14
16
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { L1PublishBlockStats, L1PublishProofStats } from '@aztec/circuit-types/stats';
|
|
2
|
+
import {
|
|
3
|
+
Attributes,
|
|
4
|
+
type Histogram,
|
|
5
|
+
Metrics,
|
|
6
|
+
type TelemetryClient,
|
|
7
|
+
type UpDownCounter,
|
|
8
|
+
ValueType,
|
|
9
|
+
} from '@aztec/telemetry-client';
|
|
10
|
+
|
|
11
|
+
import { formatEther } from 'viem/utils';
|
|
12
|
+
|
|
13
|
+
export type L1TxType = 'submitProof' | 'process';
|
|
14
|
+
|
|
15
|
+
export class L1PublisherMetrics {
|
|
16
|
+
private gasPrice: Histogram;
|
|
17
|
+
|
|
18
|
+
private txCount: UpDownCounter;
|
|
19
|
+
private txDuration: Histogram;
|
|
20
|
+
private txGas: Histogram;
|
|
21
|
+
private txCalldataSize: Histogram;
|
|
22
|
+
private txCalldataGas: Histogram;
|
|
23
|
+
|
|
24
|
+
constructor(client: TelemetryClient, name = 'L1Publisher') {
|
|
25
|
+
const meter = client.getMeter(name);
|
|
26
|
+
|
|
27
|
+
this.gasPrice = meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE, {
|
|
28
|
+
description: 'The gas price used for transactions',
|
|
29
|
+
unit: 'gwei',
|
|
30
|
+
valueType: ValueType.DOUBLE,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
this.txCount = meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
|
|
34
|
+
description: 'The number of transactions processed',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
this.txDuration = meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
|
|
38
|
+
description: 'The duration of transaction processing',
|
|
39
|
+
unit: 'ms',
|
|
40
|
+
valueType: ValueType.INT,
|
|
41
|
+
advice: {
|
|
42
|
+
explicitBucketBoundaries: [10, 50, 100, 200, 500, 1000, 2000, 5000, 10000],
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.txGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
|
|
47
|
+
description: 'The gas consumed by transactions',
|
|
48
|
+
unit: 'gas',
|
|
49
|
+
valueType: ValueType.INT,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
this.txCalldataSize = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
|
|
53
|
+
description: 'The size of the calldata in transactions',
|
|
54
|
+
unit: 'bytes',
|
|
55
|
+
valueType: ValueType.INT,
|
|
56
|
+
advice: {
|
|
57
|
+
explicitBucketBoundaries: [0, 100, 200, 500, 1000, 2000, 5000, 10000],
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
this.txCalldataGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
|
|
62
|
+
description: 'The gas consumed by the calldata in transactions',
|
|
63
|
+
unit: 'gas',
|
|
64
|
+
valueType: ValueType.INT,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
recordFailedTx(txType: L1TxType) {
|
|
69
|
+
this.txCount.add(1, {
|
|
70
|
+
[Attributes.L1_TX_TYPE]: txType,
|
|
71
|
+
[Attributes.OK]: false,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
recordSubmitProof(durationMs: number, stats: L1PublishProofStats) {
|
|
76
|
+
this.recordTx('submitProof', durationMs, stats);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
recordProcessBlockTx(durationMs: number, stats: L1PublishBlockStats) {
|
|
80
|
+
this.recordTx('process', durationMs, stats);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private recordTx(txType: L1TxType, durationMs: number, stats: Omit<L1PublishProofStats, 'eventName'>) {
|
|
84
|
+
const attributes = {
|
|
85
|
+
[Attributes.L1_TX_TYPE]: txType,
|
|
86
|
+
} as const;
|
|
87
|
+
|
|
88
|
+
this.txCount.add(1, {
|
|
89
|
+
...attributes,
|
|
90
|
+
[Attributes.OK]: true,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
this.txDuration.record(Math.ceil(durationMs), attributes);
|
|
94
|
+
this.txGas.record(
|
|
95
|
+
// safe to downcast - total block limit is 30M gas which fits in a JS number
|
|
96
|
+
Number(stats.gasUsed),
|
|
97
|
+
attributes,
|
|
98
|
+
);
|
|
99
|
+
this.txCalldataGas.record(stats.calldataGas, attributes);
|
|
100
|
+
this.txCalldataSize.record(stats.calldataSize, attributes);
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
this.gasPrice.record(parseInt(formatEther(stats.gasPrice, 'gwei'), 10));
|
|
104
|
+
} catch (e) {
|
|
105
|
+
// ignore
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|