@aztec-labs/ethereum 6.0.0-rc.3 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/blob_tx.d.ts +24 -0
- package/dest/blob_tx.d.ts.map +1 -0
- package/dest/blob_tx.js +94 -0
- package/dest/bn254/hash_to_point.d.ts +32 -0
- package/dest/bn254/hash_to_point.d.ts.map +1 -0
- package/dest/bn254/hash_to_point.js +80 -0
- package/dest/bn254/index.d.ts +3 -0
- package/dest/bn254/index.d.ts.map +1 -0
- package/dest/bn254/index.js +2 -0
- package/dest/bn254/proof_of_possession_gas.d.ts +29 -0
- package/dest/bn254/proof_of_possession_gas.d.ts.map +1 -0
- package/dest/bn254/proof_of_possession_gas.js +24 -0
- package/dest/client.d.ts +1 -1
- package/dest/client.d.ts.map +1 -1
- package/dest/client.js +5 -3
- package/dest/contracts/errors.d.ts +10 -3
- package/dest/contracts/errors.d.ts.map +1 -1
- package/dest/contracts/errors.js +10 -4
- package/dest/contracts/inbox.d.ts +1 -1
- package/dest/contracts/inbox.d.ts.map +1 -1
- package/dest/contracts/inbox.js +2 -0
- package/dest/contracts/log.d.ts +7 -1
- package/dest/contracts/log.d.ts.map +1 -1
- package/dest/contracts/log.js +6 -0
- package/dest/contracts/rollup.d.ts +32 -4
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +63 -7
- package/dest/deploy_aztec_l1_contracts.d.ts +16 -1
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_aztec_l1_contracts.js +201 -65
- package/dest/foundry_binary.d.ts +1 -1
- package/dest/foundry_binary.d.ts.map +1 -1
- package/dest/foundry_binary.js +2 -1
- package/dest/l1_tx_utils/amsterdam.d.ts +1 -1
- package/dest/l1_tx_utils/amsterdam.d.ts.map +1 -1
- package/dest/l1_tx_utils/amsterdam.js +4 -1
- package/dest/l1_tx_utils/constants.d.ts +2 -1
- package/dest/l1_tx_utils/constants.d.ts.map +1 -1
- package/dest/l1_tx_utils/constants.js +3 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +1 -1
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -1
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +6 -1
- package/dest/l1_tx_utils/index.d.ts +2 -1
- package/dest/l1_tx_utils/index.d.ts.map +1 -1
- package/dest/l1_tx_utils/index.js +1 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts +21 -1
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_tx_utils.js +71 -5
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +8 -1
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +1 -1
- package/dest/l1_tx_utils/send_cost.d.ts +15 -0
- package/dest/l1_tx_utils/send_cost.d.ts.map +1 -0
- package/dest/l1_tx_utils/send_cost.js +10 -0
- package/dest/l1_tx_utils/signer.d.ts +2 -2
- package/dest/l1_tx_utils/signer.d.ts.map +1 -1
- package/dest/l1_tx_utils/signer.js +2 -2
- package/dest/l1_tx_utils/tx_delayer.d.ts +1 -1
- package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -1
- package/dest/l1_tx_utils/tx_delayer.js +8 -26
- package/dest/publisher_manager.d.ts +127 -13
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +320 -79
- package/dest/test/anvil_hardfork.d.ts +42 -0
- package/dest/test/anvil_hardfork.d.ts.map +1 -0
- package/dest/test/anvil_hardfork.js +107 -0
- package/dest/test/eth_cheat_codes.d.ts +30 -5
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +283 -101
- package/dest/test/index.d.ts +3 -1
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +2 -0
- package/dest/test/l1_hardfork.d.ts +43 -0
- package/dest/test/l1_hardfork.d.ts.map +1 -0
- package/dest/test/l1_hardfork.js +51 -0
- package/dest/test/recording_rpc_server.d.ts +1 -1
- package/dest/test/recording_rpc_server.d.ts.map +1 -1
- package/dest/test/recording_rpc_server.js +1 -0
- package/dest/test/rollup_cheat_codes.d.ts +1 -1
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +7 -7
- package/dest/test/start_anvil.d.ts +14 -2
- package/dest/test/start_anvil.d.ts.map +1 -1
- package/dest/test/start_anvil.js +28 -11
- package/package.json +13 -11
- package/src/blob_tx.ts +118 -0
- package/src/bn254/hash_to_point.ts +95 -0
- package/src/bn254/index.ts +2 -0
- package/src/bn254/proof_of_possession_gas.ts +54 -0
- package/src/client.ts +6 -3
- package/src/contracts/errors.ts +12 -4
- package/src/contracts/inbox.ts +4 -0
- package/src/contracts/log.ts +12 -0
- package/src/contracts/rollup.ts +63 -6
- package/src/deploy_aztec_l1_contracts.ts +238 -63
- package/src/foundry_binary.ts +2 -1
- package/src/l1_tx_utils/amsterdam.ts +4 -1
- package/src/l1_tx_utils/constants.ts +4 -0
- package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +11 -1
- package/src/l1_tx_utils/index.ts +1 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +72 -5
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +1 -1
- package/src/l1_tx_utils/send_cost.ts +21 -0
- package/src/l1_tx_utils/signer.ts +3 -2
- package/src/l1_tx_utils/tx_delayer.ts +8 -37
- package/src/publisher_manager.ts +458 -83
- package/src/test/anvil_hardfork.ts +95 -0
- package/src/test/eth_cheat_codes.ts +306 -81
- package/src/test/fixtures/sepolia_blob_tx.json +10 -0
- package/src/test/index.ts +2 -0
- package/src/test/l1_hardfork.ts +71 -0
- package/src/test/recording_rpc_server.ts +1 -0
- package/src/test/rollup_cheat_codes.ts +9 -9
- package/src/test/start_anvil.ts +41 -13
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { computeBn254RegistrationDigestForPrivateKey } from './hash_to_point.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Upper-bound model of the minimum gas stipend `Bn254LibWrapper.proofOfPossession` needs to accept a valid key, as a
|
|
5
|
+
* function of the `hashToPoint` loop work for that key:
|
|
6
|
+
* `fixed + perAttempt * attempts + perSqrtCall * sqrtCalls + ceil(memoryNumerator * attempts^2 / memoryDenominator)`.
|
|
7
|
+
*/
|
|
8
|
+
export type ProofOfPossessionGasModel = {
|
|
9
|
+
/** Work that does not depend on the key: pairing, scalar multiplications, hashing, stipend headroom. */
|
|
10
|
+
fixed: number;
|
|
11
|
+
/** Per loop attempt: keccak, ABI encoding and loop overhead. */
|
|
12
|
+
perAttempt: number;
|
|
13
|
+
/** Per attempt that reaches the modexp square root. */
|
|
14
|
+
perSqrtCall: number;
|
|
15
|
+
/** Memory growth from allocations that every attempt leaves behind, quadratic in the attempts. */
|
|
16
|
+
memoryNumerator: number;
|
|
17
|
+
memoryDenominator: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Conservative min-stipend fit of the BN254 proof-of-possession gas calibration vectors measured under amsterdam
|
|
22
|
+
* pricing, which matches osaka on this path. The vectors are aztec-packages `l1-contracts/test/fixtures/
|
|
23
|
+
* bn254_pop_gas_vectors.json`, copied verbatim to `fixtures/` next to this file.
|
|
24
|
+
*/
|
|
25
|
+
export const AMSTERDAM_PROOF_OF_POSSESSION_GAS_MODEL: ProofOfPossessionGasModel = {
|
|
26
|
+
fixed: 132_694,
|
|
27
|
+
perAttempt: 515,
|
|
28
|
+
perSqrtCall: 4_580,
|
|
29
|
+
memoryNumerator: 95_975,
|
|
30
|
+
memoryDenominator: 1_000_000,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** Estimated minimum stipend for the proof-of-possession check of a key with the given `hashToPoint` work. */
|
|
34
|
+
export function estimateProofOfPossessionGas(model: ProofOfPossessionGasModel, attempts: number, sqrtCalls: number) {
|
|
35
|
+
const memory = BigInt(model.memoryNumerator) * BigInt(attempts) ** 2n;
|
|
36
|
+
const denominator = BigInt(model.memoryDenominator);
|
|
37
|
+
return (
|
|
38
|
+
model.fixed +
|
|
39
|
+
model.perAttempt * attempts +
|
|
40
|
+
model.perSqrtCall * sqrtCalls +
|
|
41
|
+
Number((memory + denominator - 1n) / denominator)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Estimated minimum stipend for the proof-of-possession check of a BN254 BLS private key. */
|
|
46
|
+
export function estimateBlsKeyProofOfPossessionGas(model: ProofOfPossessionGasModel, privateKey: string) {
|
|
47
|
+
const { attempts, sqrtCalls } = computeBn254RegistrationDigestForPrivateKey(privateKey);
|
|
48
|
+
return estimateProofOfPossessionGas(model, attempts, sqrtCalls);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Lowest gas estimate any key can have: one attempt that reaches the square root and succeeds. */
|
|
52
|
+
export function minimumProofOfPossessionGas(model: ProofOfPossessionGasModel) {
|
|
53
|
+
return estimateProofOfPossessionGas(model, 1, 1);
|
|
54
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
|
|
20
20
|
import { foundry } from 'viem/chains';
|
|
21
21
|
|
|
22
|
-
import { createEthereumChain } from './chain.js';
|
|
22
|
+
import { createEthereumChain, isAnvilTestChain } from './chain.js';
|
|
23
23
|
import type { ExtendedViemWalletClient, ViemPublicClient } from './types.js';
|
|
24
24
|
|
|
25
25
|
type Config = {
|
|
@@ -45,7 +45,10 @@ export class L1RpcError extends Error {
|
|
|
45
45
|
|
|
46
46
|
/** Creates a viem fallback HTTP transport for the given L1 RPC URLs. */
|
|
47
47
|
export function makeL1HttpTransport(rpcUrls: string[], opts?: { timeout?: number }) {
|
|
48
|
-
|
|
48
|
+
// viem caps response bodies at 10MB by default, which large getLogs or debug trace responses can exceed.
|
|
49
|
+
return wrapL1RpcTransport(
|
|
50
|
+
fallback(rpcUrls.map(url => http(url, { batch: false, timeout: opts?.timeout, maxResponseBodySize: false }))),
|
|
51
|
+
);
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
/** Returns the HTTP status from an L1 RPC error's cause chain, if one is available. */
|
|
@@ -158,7 +161,7 @@ export function createExtendedL1Client(
|
|
|
158
161
|
account: hdAccount,
|
|
159
162
|
chain,
|
|
160
163
|
transport: makeL1HttpTransport(rpcUrls, { timeout: opts?.httpTimeoutMS }),
|
|
161
|
-
pollingInterval: pollingIntervalMS,
|
|
164
|
+
pollingInterval: pollingIntervalMS ?? (isAnvilTestChain(chain.id) ? 100 : undefined),
|
|
162
165
|
}).extend(publicActions);
|
|
163
166
|
|
|
164
167
|
return extendedClient;
|
package/src/contracts/errors.ts
CHANGED
|
@@ -5,9 +5,17 @@ export class BlockTagTooOldError extends Error {
|
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
/**
|
|
9
|
+
* The committee for an epoch cannot be served yet because its sample seed can still change on L1: the randao it
|
|
10
|
+
* samples has not been checkpointed, and the epoch that would checkpoint it is not over. Thrown by callers that cannot
|
|
11
|
+
* act without the committee and retry later.
|
|
12
|
+
*/
|
|
13
|
+
export class CommitteeNotStableError extends Error {
|
|
14
|
+
constructor(
|
|
15
|
+
public readonly epoch: bigint,
|
|
16
|
+
public readonly l1BlockNumber: bigint,
|
|
17
|
+
) {
|
|
18
|
+
super(`The committee for epoch ${epoch} is not stable yet as of L1 block ${l1BlockNumber}`);
|
|
19
|
+
this.name = 'CommitteeNotStableError';
|
|
12
20
|
}
|
|
13
21
|
}
|
package/src/contracts/inbox.ts
CHANGED
|
@@ -192,6 +192,8 @@ export class InboxContract {
|
|
|
192
192
|
blockNumber: bigint | null;
|
|
193
193
|
blockHash: `0x${string}` | null;
|
|
194
194
|
transactionHash: `0x${string}` | null;
|
|
195
|
+
transactionIndex: number | null;
|
|
196
|
+
logIndex: number | null;
|
|
195
197
|
args: {
|
|
196
198
|
hash?: `0x${string}`;
|
|
197
199
|
inboxRollingHash?: `0x${string}`;
|
|
@@ -210,6 +212,8 @@ export class InboxContract {
|
|
|
210
212
|
l1BlockNumber: log.blockNumber!,
|
|
211
213
|
l1BlockHash: Buffer32.fromString(log.blockHash!),
|
|
212
214
|
l1TransactionHash: log.transactionHash!,
|
|
215
|
+
l1TransactionIndex: log.transactionIndex!,
|
|
216
|
+
l1LogIndex: log.logIndex!,
|
|
213
217
|
args: {
|
|
214
218
|
index: message.index,
|
|
215
219
|
leaf: Fr.fromString(log.args.hash!),
|
package/src/contracts/log.ts
CHANGED
|
@@ -8,10 +8,22 @@ export type L1EventLog<T> = {
|
|
|
8
8
|
l1BlockHash: Buffer32;
|
|
9
9
|
/** L1 transaction hash that emitted the event. */
|
|
10
10
|
l1TransactionHash: `0x${string}`;
|
|
11
|
+
/** Index of the emitting transaction within its L1 block. */
|
|
12
|
+
l1TransactionIndex: number;
|
|
13
|
+
/** Index of the log within its L1 block (not within its transaction), as `eth_getLogs` reports it. */
|
|
14
|
+
l1LogIndex: number;
|
|
11
15
|
/** Event-specific arguments. */
|
|
12
16
|
args: T;
|
|
13
17
|
};
|
|
14
18
|
|
|
19
|
+
/** Orders L1 event logs by their position on L1: block number, then transaction index, then log index. */
|
|
20
|
+
export function compareL1LogPosition(a: L1EventLog<unknown>, b: L1EventLog<unknown>): number {
|
|
21
|
+
if (a.l1BlockNumber !== b.l1BlockNumber) {
|
|
22
|
+
return a.l1BlockNumber < b.l1BlockNumber ? -1 : 1;
|
|
23
|
+
}
|
|
24
|
+
return a.l1TransactionIndex - b.l1TransactionIndex || a.l1LogIndex - b.l1LogIndex;
|
|
25
|
+
}
|
|
26
|
+
|
|
15
27
|
/**
|
|
16
28
|
* Message fragments providers use to refuse a log query for being too wide or returning too much, the failures a
|
|
17
29
|
* narrower range is known to fix. Matched on text because the JSON-RPC boundary leaves no error class or code behind
|
package/src/contracts/rollup.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { Signature, type ViemSignature } from '@aztec-labs/foundation/eth-signat
|
|
|
12
12
|
import { createLogger } from '@aztec-labs/foundation/log';
|
|
13
13
|
import { makeBackoff, retry } from '@aztec-labs/foundation/retry';
|
|
14
14
|
import { getErrorCause } from '@aztec-labs/foundation/types';
|
|
15
|
+
import { Buffer } from 'buffer';
|
|
15
16
|
import chunk from 'lodash.chunk';
|
|
16
17
|
import {
|
|
17
18
|
type AbiParameter,
|
|
@@ -342,6 +343,7 @@ export type CheckpointProposedArgs = {
|
|
|
342
343
|
export type CheckpointProposedLog = L1EventLog<CheckpointProposedArgs>;
|
|
343
344
|
|
|
344
345
|
const INSUFFICIENT_VALIDATOR_SET_SIZE_ERROR = 'ValidatorSelection__InsufficientValidatorSetSize';
|
|
346
|
+
const EPOCH_NOT_STABLE_ERROR = 'ValidatorSelection__EpochNotStable';
|
|
345
347
|
|
|
346
348
|
/** SlasherUpdated events are rare governance operations, so their watcher polls well below the client's interval. */
|
|
347
349
|
const SLASHER_UPDATED_POLLING_INTERVAL_MS = 60_000;
|
|
@@ -354,6 +356,11 @@ function isValidatorSelectionError(err: unknown, errorName: string): boolean {
|
|
|
354
356
|
);
|
|
355
357
|
}
|
|
356
358
|
|
|
359
|
+
/** Whether a rollup read reverted because the requested epoch's committee or seed can still change. */
|
|
360
|
+
export function isEpochNotStableError(err: unknown): boolean {
|
|
361
|
+
return isValidatorSelectionError(err, EPOCH_NOT_STABLE_ERROR);
|
|
362
|
+
}
|
|
363
|
+
|
|
357
364
|
function decodeRpcRequestErrorName(err: unknown): string | undefined {
|
|
358
365
|
const data = getErrorCause(err, RpcRequestError)?.data;
|
|
359
366
|
if (!isHexString(data)) {
|
|
@@ -383,6 +390,7 @@ export class RollupContract {
|
|
|
383
390
|
private readonly logger = createLogger('ethereum:rollup');
|
|
384
391
|
|
|
385
392
|
private static cachedStfStorageSlot: Hex | undefined;
|
|
393
|
+
private static cachedValidatorSelectionStorageSlot: Hex | undefined;
|
|
386
394
|
private cachedEscapeHatch?: {
|
|
387
395
|
address: EthAddress;
|
|
388
396
|
contract: GetContractReturnType<typeof EscapeHatchAbi, ViemClient>;
|
|
@@ -400,6 +408,13 @@ export class RollupContract {
|
|
|
400
408
|
return (RollupContract.cachedStfStorageSlot ??= keccak256(Buffer.from('aztec.stf.storage', 'utf-8')));
|
|
401
409
|
}
|
|
402
410
|
|
|
411
|
+
/** Base slot of the rollup's validator selection storage struct, whose first field maps epochs to committee commitments. */
|
|
412
|
+
static get validatorSelectionStorageSlot(): Hex {
|
|
413
|
+
return (RollupContract.cachedValidatorSelectionStorageSlot ??= keccak256(
|
|
414
|
+
Buffer.from('aztec.validator_selection.storage', 'utf-8'),
|
|
415
|
+
));
|
|
416
|
+
}
|
|
417
|
+
|
|
403
418
|
static getFromL1ContractsValues(deployL1ContractsValues: DeployAztecL1ContractsReturnType) {
|
|
404
419
|
const {
|
|
405
420
|
l1Client,
|
|
@@ -645,15 +660,18 @@ export class RollupContract {
|
|
|
645
660
|
* This function is intentionally defensive: any failure to query the escape hatch
|
|
646
661
|
* (RPC issues, transient errors, etc.) is treated as "closed" to avoid callers
|
|
647
662
|
* needing to sprinkle try/catch everywhere.
|
|
663
|
+
*
|
|
664
|
+
* `options.blockNumber` pins only the hatch's `isHatchOpen` read: the escape hatch address is always resolved at the
|
|
665
|
+
* latest L1 block.
|
|
648
666
|
*/
|
|
649
|
-
async isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean> {
|
|
667
|
+
async isEscapeHatchOpen(epoch: EpochNumber, options?: { blockNumber?: bigint }): Promise<boolean> {
|
|
650
668
|
try {
|
|
651
669
|
const escapeHatch = await this.getEscapeHatchContract();
|
|
652
670
|
if (!escapeHatch) {
|
|
653
671
|
return false;
|
|
654
672
|
}
|
|
655
673
|
|
|
656
|
-
const [isOpen] = await escapeHatch.read.isHatchOpen([BigInt(epoch)]);
|
|
674
|
+
const [isOpen] = await escapeHatch.read.isHatchOpen([BigInt(epoch)], options);
|
|
657
675
|
return isOpen;
|
|
658
676
|
} catch (err) {
|
|
659
677
|
this.logger.warn('isEscapeHatchOpen failed (treating as closed); RPC or contract error may cause liveness risk', {
|
|
@@ -745,13 +763,14 @@ export class RollupContract {
|
|
|
745
763
|
return this.rollup.read.getEthPerFeeAsset();
|
|
746
764
|
}
|
|
747
765
|
|
|
748
|
-
async getCommitteeAt(timestamp: bigint): Promise<EthAddress[] | undefined> {
|
|
766
|
+
async getCommitteeAt(timestamp: bigint, options?: { blockNumber?: bigint }): Promise<EthAddress[] | undefined> {
|
|
749
767
|
const { result } = await this.client
|
|
750
768
|
.simulateContract({
|
|
751
769
|
address: this.address,
|
|
752
770
|
abi: RollupAbi,
|
|
753
771
|
functionName: 'getCommitteeAt',
|
|
754
772
|
args: [timestamp],
|
|
773
|
+
blockNumber: options?.blockNumber,
|
|
755
774
|
})
|
|
756
775
|
.catch(e => {
|
|
757
776
|
if (isValidatorSelectionError(e, INSUFFICIENT_VALIDATOR_SET_SIZE_ERROR)) {
|
|
@@ -763,8 +782,8 @@ export class RollupContract {
|
|
|
763
782
|
return result ? result.map(addr => EthAddress.fromString(addr)) : undefined;
|
|
764
783
|
}
|
|
765
784
|
|
|
766
|
-
async getSampleSeedAt(timestamp: bigint): Promise<Buffer32> {
|
|
767
|
-
return Buffer32.fromBigInt(await this.rollup.read.getSampleSeedAt([timestamp]));
|
|
785
|
+
async getSampleSeedAt(timestamp: bigint, options?: { blockNumber?: bigint }): Promise<Buffer32> {
|
|
786
|
+
return Buffer32.fromBigInt(await this.rollup.read.getSampleSeedAt([timestamp], options));
|
|
768
787
|
}
|
|
769
788
|
|
|
770
789
|
async getCurrentSampleSeed(): Promise<Buffer32> {
|
|
@@ -775,6 +794,26 @@ export class RollupContract {
|
|
|
775
794
|
return EpochNumber.fromBigInt(await this.rollup.read.getCurrentEpoch());
|
|
776
795
|
}
|
|
777
796
|
|
|
797
|
+
/**
|
|
798
|
+
* Whether `setupEpoch` has already run for the epoch, i.e. its committee commitment is stored, as of
|
|
799
|
+
* `options.blockNumber` (the latest L1 block by default).
|
|
800
|
+
* Read straight from storage because `getEpochCommitteeCommitment` computes the commitment when it is not stored.
|
|
801
|
+
*/
|
|
802
|
+
async isEpochSetUp(epoch: EpochNumber, options?: { blockNumber?: bigint }): Promise<boolean> {
|
|
803
|
+
const slot = keccak256(
|
|
804
|
+
encodeAbiParameters(
|
|
805
|
+
[{ type: 'uint256' }, { type: 'uint256' }],
|
|
806
|
+
[BigInt(epoch), BigInt(RollupContract.validatorSelectionStorageSlot)],
|
|
807
|
+
),
|
|
808
|
+
);
|
|
809
|
+
const value = await this.client.getStorageAt(
|
|
810
|
+
options?.blockNumber === undefined
|
|
811
|
+
? { address: this.address, slot, blockTag: 'latest' }
|
|
812
|
+
: { address: this.address, slot, blockNumber: options.blockNumber },
|
|
813
|
+
);
|
|
814
|
+
return value !== undefined && hexToBigInt(value) !== 0n;
|
|
815
|
+
}
|
|
816
|
+
|
|
778
817
|
async getCurrentEpochCommittee(): Promise<EthAddress[] | undefined> {
|
|
779
818
|
const { result } = await this.client
|
|
780
819
|
.simulateContract({
|
|
@@ -1317,6 +1356,21 @@ export class RollupContract {
|
|
|
1317
1356
|
return this.rollup.read.getHasSubmitted([BigInt(epochNumber), BigInt(numberOfCheckpointsInEpoch), prover]);
|
|
1318
1357
|
}
|
|
1319
1358
|
|
|
1359
|
+
/**
|
|
1360
|
+
* Calls getHasSubmittedFullEpoch directly. Returns whether the given prover's proof with the given length for the
|
|
1361
|
+
* given epoch was registered as a full-epoch proof, which is the only kind that raises the prover's activity score.
|
|
1362
|
+
*/
|
|
1363
|
+
public getHasSubmittedFullEpochProof(
|
|
1364
|
+
epochNumber: EpochNumber,
|
|
1365
|
+
numberOfCheckpointsInEpoch: number,
|
|
1366
|
+
prover: Hex | EthAddress,
|
|
1367
|
+
): Promise<boolean> {
|
|
1368
|
+
if (prover instanceof EthAddress) {
|
|
1369
|
+
prover = prover.toString();
|
|
1370
|
+
}
|
|
1371
|
+
return this.rollup.read.getHasSubmittedFullEpoch([BigInt(epochNumber), BigInt(numberOfCheckpointsInEpoch), prover]);
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1320
1374
|
/**
|
|
1321
1375
|
* Returns the minimum mana fee at the given timestamp.
|
|
1322
1376
|
* @param options - Optional state override to simulate against, and optional L1 block number to pin the call
|
|
@@ -1391,7 +1445,8 @@ export class RollupContract {
|
|
|
1391
1445
|
const block = await this.client.getBlock();
|
|
1392
1446
|
const blockNumber = block.number ?? undefined;
|
|
1393
1447
|
const ts = timestamp ?? block.timestamp;
|
|
1394
|
-
|
|
1448
|
+
// Count at ts, matching the addresses below; the current count would truncate a shrunk set.
|
|
1449
|
+
const attesterSize = await this.getAttesterCountAtTime(ts, { blockNumber });
|
|
1395
1450
|
const gse = new GSEContract(this.client, await this.getGSE());
|
|
1396
1451
|
const indices = Array.from({ length: attesterSize }, (_, i) => BigInt(i));
|
|
1397
1452
|
const chunks = chunk(indices, 1000);
|
|
@@ -1822,6 +1877,8 @@ export class RollupContract {
|
|
|
1822
1877
|
l1BlockNumber: log.blockNumber!,
|
|
1823
1878
|
l1BlockHash: Buffer32.fromString(log.blockHash!),
|
|
1824
1879
|
l1TransactionHash: log.transactionHash!,
|
|
1880
|
+
l1TransactionIndex: log.transactionIndex!,
|
|
1881
|
+
l1LogIndex: log.logIndex!,
|
|
1825
1882
|
args: {
|
|
1826
1883
|
checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber!),
|
|
1827
1884
|
archive: Fr.fromString(log.args.archive!),
|