@aztec/ethereum 0.0.1-commit.8c0b8ff → 0.0.1-commit.8cb2d04d8
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/config.d.ts +6 -6
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +6 -10
- package/dest/contracts/chain_state_override.d.ts +38 -0
- package/dest/contracts/chain_state_override.d.ts.map +1 -0
- package/dest/contracts/chain_state_override.js +100 -0
- package/dest/contracts/inbox.d.ts +3 -3
- package/dest/contracts/inbox.d.ts.map +1 -1
- package/dest/contracts/inbox.js +5 -6
- package/dest/contracts/index.d.ts +3 -3
- package/dest/contracts/index.d.ts.map +1 -1
- package/dest/contracts/index.js +2 -2
- package/dest/contracts/multicall.d.ts +51 -2
- package/dest/contracts/multicall.d.ts.map +1 -1
- package/dest/contracts/multicall.js +85 -0
- package/dest/contracts/rollup.d.ts +68 -18
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +240 -50
- package/dest/contracts/{tally_slashing_proposer.d.ts → slashing_proposer.d.ts} +3 -4
- package/dest/contracts/slashing_proposer.d.ts.map +1 -0
- package/dest/contracts/{tally_slashing_proposer.js → slashing_proposer.js} +13 -15
- package/dest/deploy_aztec_l1_contracts.d.ts +3 -6
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_aztec_l1_contracts.js +2 -4
- package/dest/generated/l1-contracts-defaults.d.ts +2 -2
- package/dest/generated/l1-contracts-defaults.js +2 -2
- package/dest/l1_artifacts.d.ts +8644 -15983
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_artifacts.js +9 -24
- package/dest/l1_contract_addresses.d.ts +1 -5
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +0 -6
- package/dest/l1_tx_utils/l1_tx_utils.d.ts +3 -1
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_tx_utils.js +34 -26
- package/dest/publisher_manager.d.ts +21 -7
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +81 -7
- package/dest/queries.js +3 -3
- package/dest/utils.d.ts +1 -1
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +16 -12
- package/package.json +5 -7
- package/src/config.ts +10 -14
- package/src/contracts/chain_state_override.ts +147 -0
- package/src/contracts/inbox.ts +4 -4
- package/src/contracts/index.ts +2 -2
- package/src/contracts/multicall.ts +65 -1
- package/src/contracts/rollup.ts +256 -43
- package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +14 -16
- package/src/deploy_aztec_l1_contracts.ts +1 -5
- package/src/generated/l1-contracts-defaults.ts +2 -2
- package/src/l1_artifacts.ts +12 -35
- package/src/l1_contract_addresses.ts +0 -7
- package/src/l1_tx_utils/l1_tx_utils.ts +24 -14
- package/src/publisher_manager.ts +105 -10
- package/src/queries.ts +3 -3
- package/src/utils.ts +17 -14
- package/dest/contracts/empire_slashing_proposer.d.ts +0 -69
- package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
- package/dest/contracts/empire_slashing_proposer.js +0 -216
- package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
- package/src/contracts/empire_slashing_proposer.ts +0 -265
|
@@ -2,6 +2,7 @@ import { maxBigint } from '@aztec/foundation/bigint';
|
|
|
2
2
|
import { merge, pick } from '@aztec/foundation/collection';
|
|
3
3
|
import { InterruptError, TimeoutError } from '@aztec/foundation/error';
|
|
4
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { Semaphore } from '@aztec/foundation/queue';
|
|
5
6
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
6
7
|
import { sleep } from '@aztec/foundation/sleep';
|
|
7
8
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
@@ -23,10 +24,11 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
23
24
|
metrics;
|
|
24
25
|
txs;
|
|
25
26
|
/** Last nonce successfully sent to the chain. Used as a lower bound when a fallback RPC node returns a stale count. */ lastSentNonce;
|
|
27
|
+
/** Mutex to prevent concurrent sendTransaction calls from racing on the same nonce. */ sendMutex;
|
|
26
28
|
/** Tx delayer for testing. Only set when enableDelayer config is true. */ delayer;
|
|
27
29
|
/** KZG instance for blob operations. */ kzg;
|
|
28
30
|
constructor(client, address, signer, logger = createLogger('ethereum:publisher'), dateProvider = new DateProvider(), config, debugMaxGasLimit = false, store, metrics, kzg, delayer){
|
|
29
|
-
super(client, logger, dateProvider, config, debugMaxGasLimit), this.client = client, this.address = address, this.signer = signer, this.store = store, this.metrics = metrics, this.txs = [];
|
|
31
|
+
super(client, logger, dateProvider, config, debugMaxGasLimit), this.client = client, this.address = address, this.signer = signer, this.store = store, this.metrics = metrics, this.txs = [], this.sendMutex = new Semaphore(1);
|
|
30
32
|
this.kzg = kzg;
|
|
31
33
|
// Set up delayer: use provided one or create new
|
|
32
34
|
if (config?.enableDelayer && config?.ethereumSlotDuration) {
|
|
@@ -171,34 +173,40 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
171
173
|
if (gasConfig.txTimeoutAt && now > gasConfig.txTimeoutAt) {
|
|
172
174
|
throw new TimeoutError(`Transaction timed out before sending (now ${now.toISOString()} > timeoutAt ${gasConfig.txTimeoutAt.toISOString()})`);
|
|
173
175
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
176
|
+
let txHash;
|
|
177
|
+
let nonce;
|
|
178
|
+
let baseState;
|
|
179
|
+
await this.sendMutex.acquire();
|
|
180
|
+
try {
|
|
181
|
+
const chainNonce = await this.client.getTransactionCount({
|
|
182
|
+
address: account,
|
|
183
|
+
blockTag: 'pending'
|
|
184
|
+
});
|
|
185
|
+
// If a fallback RPC node returns a stale count (lower than what we last sent), use our
|
|
186
|
+
// local lower bound to avoid sending a duplicate of an already-pending transaction.
|
|
187
|
+
nonce = this.lastSentNonce !== undefined && chainNonce <= this.lastSentNonce ? this.lastSentNonce + 1 : chainNonce;
|
|
188
|
+
baseState = {
|
|
189
|
+
request,
|
|
190
|
+
gasLimit,
|
|
191
|
+
blobInputs,
|
|
192
|
+
gasPrice,
|
|
193
|
+
nonce
|
|
194
|
+
};
|
|
195
|
+
const txData = this.makeTxData(baseState, {
|
|
196
|
+
isCancelTx: false
|
|
197
|
+
});
|
|
198
|
+
const signedRequest = await this.prepareSignedTransaction(txData);
|
|
199
|
+
txHash = await this.client.sendRawTransaction({
|
|
200
|
+
serializedTransaction: signedRequest
|
|
201
|
+
});
|
|
202
|
+
this.lastSentNonce = nonce;
|
|
203
|
+
} finally{
|
|
204
|
+
this.sendMutex.release();
|
|
205
|
+
}
|
|
198
206
|
// Create the new state for monitoring
|
|
199
207
|
const l1TxState = {
|
|
200
208
|
...baseState,
|
|
201
|
-
id: await this.store?.consumeNextStateId(account) ?? Math.max(...this.txs.map((tx)=>tx.id),
|
|
209
|
+
id: await this.store?.consumeNextStateId(account) ?? Math.max(...this.txs.map((tx)=>tx.id), -1) + 1,
|
|
202
210
|
txHashes: [
|
|
203
211
|
txHash
|
|
204
212
|
],
|
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import { type LoggerBindings } from '@aztec/foundation/log';
|
|
2
2
|
import { L1TxUtils } from './l1_tx_utils/index.js';
|
|
3
3
|
export type PublisherFilter<UtilsType extends L1TxUtils> = (utils: UtilsType) => boolean;
|
|
4
|
+
/** Config accepted by PublisherManager. */
|
|
5
|
+
type PublisherManagerConfig = {
|
|
6
|
+
publisherAllowInvalidStates?: boolean;
|
|
7
|
+
publisherFundingThreshold?: bigint;
|
|
8
|
+
publisherFundingAmount?: bigint;
|
|
9
|
+
};
|
|
4
10
|
export declare class PublisherManager<UtilsType extends L1TxUtils = L1TxUtils> {
|
|
5
11
|
private publishers;
|
|
6
12
|
private log;
|
|
7
13
|
private config;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
private static readonly FUNDING_CHECK_INTERVAL_MS;
|
|
15
|
+
private funder?;
|
|
16
|
+
private fundingPromise?;
|
|
17
|
+
constructor(publishers: UtilsType[], config: PublisherManagerConfig, opts?: {
|
|
18
|
+
bindings?: LoggerBindings;
|
|
19
|
+
funder?: UtilsType;
|
|
20
|
+
});
|
|
21
|
+
/** Loads the state of all publishers and the funder, and starts periodic funding checks. */
|
|
22
|
+
start(): Promise<void>;
|
|
23
|
+
/** Stops the funding loop and interrupts all publishers. */
|
|
24
|
+
stop(): Promise<void>;
|
|
13
25
|
getAvailablePublisher(filter?: PublisherFilter<UtilsType>): Promise<UtilsType>;
|
|
14
|
-
|
|
26
|
+
private triggerFundingIfNeeded;
|
|
27
|
+
private fundPublishers;
|
|
15
28
|
}
|
|
16
|
-
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaGVyX21hbmFnZXIuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wdWJsaXNoZXJfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQWUsS0FBSyxjQUFjLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFJdkYsT0FBTyxFQUFFLFNBQVMsRUFBZ0IsTUFBTSx3QkFBd0IsQ0FBQztBQXdCakUsTUFBTSxNQUFNLGVBQWUsQ0FBQyxTQUFTLFNBQVMsU0FBUyxJQUFJLENBQUMsS0FBSyxFQUFFLFNBQVMsS0FBSyxPQUFPLENBQUM7QUFFekYsMkNBQTJDO0FBQzNDLEtBQUssc0JBQXNCLEdBQUc7SUFDNUIsMkJBQTJCLENBQUMsRUFBRSxPQUFPLENBQUM7SUFDdEMseUJBQXlCLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDbkMsc0JBQXNCLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDakMsQ0FBQztBQUVGLHFCQUFhLGdCQUFnQixDQUFDLFNBQVMsU0FBUyxTQUFTLEdBQUcsU0FBUztJQVFqRSxPQUFPLENBQUMsVUFBVTtJQVBwQixPQUFPLENBQUMsR0FBRyxDQUFTO0lBQ3BCLE9BQU8sQ0FBQyxNQUFNLENBQXlCO0lBQ3ZDLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLHlCQUF5QixDQUFpQjtJQUNsRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQVk7SUFDM0IsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFpQjtJQUV4QyxZQUNVLFVBQVUsRUFBRSxTQUFTLEVBQUUsRUFDL0IsTUFBTSxFQUFFLHNCQUFzQixFQUM5QixJQUFJLENBQUMsRUFBRTtRQUFFLFFBQVEsQ0FBQyxFQUFFLGNBQWMsQ0FBQztRQUFDLE1BQU0sQ0FBQyxFQUFFLFNBQVMsQ0FBQTtLQUFFLEVBcUJ6RDtJQUVELDRGQUE0RjtJQUMvRSxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQWtCbEM7SUFFRCw0REFBNEQ7SUFDL0MsSUFBSSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FJakM7SUFRWSxxQkFBcUIsQ0FBQyxNQUFNLEdBQUUsZUFBZSxDQUFDLFNBQVMsQ0FBYyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0ErQ3RHO1lBR2Esc0JBQXNCO1lBcUN0QixjQUFjO0NBVTdCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publisher_manager.d.ts","sourceRoot":"","sources":["../src/publisher_manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"publisher_manager.d.ts","sourceRoot":"","sources":["../src/publisher_manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAIvF,OAAO,EAAE,SAAS,EAAgB,MAAM,wBAAwB,CAAC;AAwBjE,MAAM,MAAM,eAAe,CAAC,SAAS,SAAS,SAAS,IAAI,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;AAEzF,2CAA2C;AAC3C,KAAK,sBAAsB,GAAG;IAC5B,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAEF,qBAAa,gBAAgB,CAAC,SAAS,SAAS,SAAS,GAAG,SAAS;IAQjE,OAAO,CAAC,UAAU;IAPpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAiB;IAClE,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,cAAc,CAAC,CAAiB;IAExC,YACU,UAAU,EAAE,SAAS,EAAE,EAC/B,MAAM,EAAE,sBAAsB,EAC9B,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAA;KAAE,EAqBzD;IAED,4FAA4F;IAC/E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAkBlC;IAED,4DAA4D;IAC/C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAIjC;IAQY,qBAAqB,CAAC,MAAM,GAAE,eAAe,CAAC,SAAS,CAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CA+CtG;YAGa,sBAAsB;YAqCtB,cAAc;CAU7B"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { pick } from '@aztec/foundation/collection';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
4
|
+
import { Multicall3 } from './contracts/multicall.js';
|
|
3
5
|
import { TxUtilsState } from './l1_tx_utils/index.js';
|
|
4
6
|
// Defines the order in which we prioritise publishers based on their state (first is better)
|
|
5
7
|
const sortOrder = [
|
|
@@ -25,15 +27,43 @@ export class PublisherManager {
|
|
|
25
27
|
publishers;
|
|
26
28
|
log;
|
|
27
29
|
config;
|
|
28
|
-
|
|
30
|
+
static FUNDING_CHECK_INTERVAL_MS = 2 * 60 * 1000;
|
|
31
|
+
funder;
|
|
32
|
+
fundingPromise;
|
|
33
|
+
constructor(publishers, config, opts){
|
|
29
34
|
this.publishers = publishers;
|
|
30
|
-
this.
|
|
35
|
+
this.funder = opts?.funder;
|
|
36
|
+
this.log = createLogger('publisher:manager', opts?.bindings);
|
|
31
37
|
this.log.info(`PublisherManager initialized with ${publishers.length} publishers.`);
|
|
32
38
|
this.publishers = publishers;
|
|
33
|
-
this.config = pick(config, 'publisherAllowInvalidStates');
|
|
39
|
+
this.config = pick(config, 'publisherAllowInvalidStates', 'publisherFundingThreshold', 'publisherFundingAmount');
|
|
40
|
+
const hasThreshold = this.config.publisherFundingThreshold !== undefined;
|
|
41
|
+
const hasAmount = this.config.publisherFundingAmount !== undefined;
|
|
42
|
+
if (hasThreshold !== hasAmount) {
|
|
43
|
+
this.log.warn(`Incomplete funding config: both publisherFundingThreshold and publisherFundingAmount must be set`);
|
|
44
|
+
}
|
|
45
|
+
if (this.funder) {
|
|
46
|
+
const funderAddress = this.funder.getSenderAddress();
|
|
47
|
+
if (publishers.some((p)=>p.getSenderAddress().equals(funderAddress))) {
|
|
48
|
+
this.log.error(`Funding account ${funderAddress} is also a publisher, disabling funding to avoid self-funding`);
|
|
49
|
+
this.funder = undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Loads the state of all publishers and the funder, and starts periodic funding checks. */ async start() {
|
|
54
|
+
await Promise.all([
|
|
55
|
+
...this.publishers.map((pub)=>pub.loadStateAndResumeMonitoring()),
|
|
56
|
+
this.funder?.loadStateAndResumeMonitoring()
|
|
57
|
+
]);
|
|
58
|
+
if (this.funder && this.config.publisherFundingThreshold !== undefined && this.config.publisherFundingAmount !== undefined) {
|
|
59
|
+
this.fundingPromise = new RunningPromise(()=>this.triggerFundingIfNeeded(), this.log, PublisherManager.FUNDING_CHECK_INTERVAL_MS);
|
|
60
|
+
this.fundingPromise.start();
|
|
61
|
+
}
|
|
34
62
|
}
|
|
35
|
-
/**
|
|
36
|
-
await
|
|
63
|
+
/** Stops the funding loop and interrupts all publishers. */ async stop() {
|
|
64
|
+
await this.fundingPromise?.stop();
|
|
65
|
+
this.publishers.forEach((pub)=>pub.interrupt());
|
|
66
|
+
this.funder?.interrupt();
|
|
37
67
|
}
|
|
38
68
|
// Finds and prioritises available publishers based on
|
|
39
69
|
// 1. Validity as per the provided filter function
|
|
@@ -82,7 +112,51 @@ export class PublisherManager {
|
|
|
82
112
|
});
|
|
83
113
|
return sortedPublishers[0].publisher;
|
|
84
114
|
}
|
|
85
|
-
|
|
86
|
-
this
|
|
115
|
+
/** Check all publisher balances and fund those below threshold. */ async triggerFundingIfNeeded() {
|
|
116
|
+
const { funder, config } = this;
|
|
117
|
+
if (!funder || config.publisherFundingThreshold === undefined || config.publisherFundingAmount === undefined) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const allBalances = await Promise.all(this.publishers.map(async (pub)=>({
|
|
121
|
+
balance: await pub.getSenderBalance(),
|
|
122
|
+
publisher: pub
|
|
123
|
+
})));
|
|
124
|
+
const lowBalance = allBalances.filter((p)=>p.balance < config.publisherFundingThreshold);
|
|
125
|
+
if (lowBalance.length === 0) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const fundingAmount = config.publisherFundingAmount;
|
|
129
|
+
const funderBalance = await funder.getSenderBalance();
|
|
130
|
+
if (funderBalance < 10n * fundingAmount) {
|
|
131
|
+
this.log.warn(`Funding account balance is low`, {
|
|
132
|
+
funderBalance,
|
|
133
|
+
threshold: 10n * fundingAmount
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const affordableCount = Number(funderBalance / fundingAmount);
|
|
137
|
+
if (affordableCount === 0) {
|
|
138
|
+
this.log.error(`Funding account balance too low to fund any publisher`, {
|
|
139
|
+
funderBalance,
|
|
140
|
+
fundingAmount
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (affordableCount < lowBalance.length) {
|
|
145
|
+
this.log.warn(`Funder can only afford ${affordableCount}/${lowBalance.length} publishers`, {
|
|
146
|
+
funderBalance,
|
|
147
|
+
fundingAmount
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const toFund = lowBalance.slice(0, affordableCount).map((p)=>p.publisher);
|
|
151
|
+
await this.fundPublishers(toFund);
|
|
152
|
+
}
|
|
153
|
+
/** Fund publishers via a single Multicall3 aggregate3Value transaction. */ async fundPublishers(publishers) {
|
|
154
|
+
const fundingAmount = this.config.publisherFundingAmount;
|
|
155
|
+
const calls = publishers.map((pub)=>({
|
|
156
|
+
to: pub.getSenderAddress().toString(),
|
|
157
|
+
value: fundingAmount
|
|
158
|
+
}));
|
|
159
|
+
await Multicall3.forwardValue(calls, this.funder, this.log);
|
|
160
|
+
this.log.info(`Funded ${publishers.length} publishers`);
|
|
87
161
|
}
|
|
88
162
|
}
|
package/dest/queries.js
CHANGED
|
@@ -33,8 +33,8 @@ import { RollupContract } from './contracts/rollup.js';
|
|
|
33
33
|
slasherProposer?.getRoundSize() ?? 0n,
|
|
34
34
|
slasherProposer?.getLifetimeInRounds() ?? 0n,
|
|
35
35
|
slasherProposer?.getExecutionDelayInRounds() ?? 0n,
|
|
36
|
-
slasherProposer?.
|
|
37
|
-
slasherProposer?.
|
|
36
|
+
slasherProposer?.getSlashOffsetInRounds() ?? 0n,
|
|
37
|
+
slasherProposer?.getSlashingAmounts() ?? [
|
|
38
38
|
0n,
|
|
39
39
|
0n,
|
|
40
40
|
0n
|
|
@@ -74,7 +74,7 @@ import { RollupContract } from './contracts/rollup.js';
|
|
|
74
74
|
rollupVersion: Number(rollupVersion),
|
|
75
75
|
genesisArchiveTreeRoot: genesisArchiveTreeRoot.toString(),
|
|
76
76
|
exitDelaySeconds: Number(exitDelay),
|
|
77
|
-
|
|
77
|
+
slasherEnabled: !!slasherProposer,
|
|
78
78
|
slashingOffsetInRounds: Number(slashingOffsetInRounds),
|
|
79
79
|
slashAmountSmall: slashingAmounts[0],
|
|
80
80
|
slashAmountMedium: slashingAmounts[1],
|
package/dest/utils.d.ts
CHANGED
|
@@ -35,4 +35,4 @@ export declare function isBlobTransaction(tx: FormattedTransaction): tx is Forma
|
|
|
35
35
|
* Calculates a percentile from an array of bigints
|
|
36
36
|
*/
|
|
37
37
|
export declare function calculatePercentile(values: bigint[], percentile: number): bigint;
|
|
38
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
38
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUdwRCxPQUFPLEVBQ0wsS0FBSyxHQUFHLEVBR1IsS0FBSyxpQkFBaUIsRUFFdEIsS0FBSyx3QkFBd0IsRUFDN0IsS0FBSyxvQkFBb0IsRUFDekIsS0FBSyxHQUFHLEVBQ1IsS0FBSyxHQUFHLEVBR1QsTUFBTSxNQUFNLENBQUM7QUFHZCxNQUFNLFdBQVcsT0FBTztJQUN0QixXQUFXLEVBQUUsRUFBRSxDQUFDO0lBQ2hCLFdBQVcsRUFBRSxFQUFFLENBQUM7SUFDaEIsV0FBVyxFQUFFLEdBQUcsQ0FBQztJQUNqQixnQkFBZ0IsRUFBRSxNQUFNLENBQUM7Q0FDMUI7QUFFRCxxQkFBYSxrQkFBbUIsU0FBUSxLQUFLO0lBQzNDLFlBQVksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBRXJCLFlBQVksT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFJaEQ7Q0FDRjtBQUVELHdCQUFnQixZQUFZLENBQzFCLEtBQUssQ0FBQyxJQUFJLFNBQVMsR0FBRyxHQUFHLFNBQVMsT0FBTyxFQUFFLEVBQzNDLFVBQVUsU0FBUyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFDMUMsVUFBVSxHQUFHLHdCQUF3QixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUUvRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEVBQ1gsT0FBTyxFQUFFLEdBQUcsRUFDWixHQUFHLEVBQUUsSUFBSSxFQUNULFNBQVMsRUFBRSxVQUFVLEVBQ3JCLE1BQU0sQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLFVBQVUsS0FBSyxPQUFPLEVBQ3JDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sR0FDZCxVQUFVLENBTVo7QUFFRCx3QkFBZ0IsZUFBZSxDQUM3QixLQUFLLENBQUMsSUFBSSxTQUFTLEdBQUcsR0FBRyxTQUFTLE9BQU8sRUFBRSxFQUMzQyxVQUFVLFNBQVMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEVBQzFDLFVBQVUsR0FBRyx3QkFBd0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsRUFFL0UsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUNYLE9BQU8sRUFBRSxHQUFHLEVBQ1osR0FBRyxFQUFFLElBQUksRUFDVCxTQUFTLEVBQUUsVUFBVSxFQUNyQixNQUFNLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxVQUFVLEtBQUssT0FBTyxFQUNyQyxNQUFNLENBQUMsRUFBRSxNQUFNLEdBQ2QsVUFBVSxHQUFHLFNBQVMsQ0FnQnhCO0FBRUQsd0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLE9BVzdDO0FBRUQsd0JBQWdCLFNBQVMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsR0FBRyxDQWUxQztBQTJFRDs7Ozs7R0FLRztBQUNILHdCQUFnQixlQUFlLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUUsR0FBZSxHQUFHLGtCQUFrQixDQTREcEY7QUF5QkQsd0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLHNCQWE3QztBQUVEOzs7R0FHRztBQUNILHdCQUFnQixpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsb0JBQW9CLEdBQUcsRUFBRSxJQUFJLG9CQUFvQixHQUFHO0lBQ3hGLGdCQUFnQixFQUFFLE1BQU0sQ0FBQztJQUN6QixtQkFBbUIsRUFBRSxTQUFTLEdBQUcsRUFBRSxDQUFDO0NBQ3JDLENBT0E7QUFFRDs7R0FFRztBQUNILHdCQUFnQixtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsVUFBVSxFQUFFLE1BQU0sR0FBRyxNQUFNLENBT2hGIn0=
|
package/dest/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EACL,KAAK,GAAG,EAGR,KAAK,iBAAiB,EAEtB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,GAAG,EACR,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAGd,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,GAAG,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;IAErB,YAAY,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE,EAIhD;CACF;AAED,wBAAgB,YAAY,CAC1B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAMZ;AAED,wBAAgB,eAAe,CAC7B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,GAAG,SAAS,CAgBxB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,OAW7C;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAe1C;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EACL,KAAK,GAAG,EAGR,KAAK,iBAAiB,EAEtB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,GAAG,EACR,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAGd,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,GAAG,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;IAErB,YAAY,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE,EAIhD;CACF;AAED,wBAAgB,YAAY,CAC1B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAMZ;AAED,wBAAgB,eAAe,CAC7B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,GAAG,SAAS,CAgBxB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,OAW7C;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAe1C;AA2ED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAE,GAAe,GAAG,kBAAkB,CA4DpF;AAyBD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,sBAa7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,oBAAoB,GAAG,EAAE,IAAI,oBAAoB,GAAG;IACxF,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,SAAS,GAAG,EAAE,CAAC;CACrC,CAOA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAOhF"}
|
package/dest/utils.js
CHANGED
|
@@ -112,6 +112,19 @@ function getNestedErrorData(error) {
|
|
|
112
112
|
// Not found
|
|
113
113
|
return undefined;
|
|
114
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Truncates an error message to a safe length for log renderers.
|
|
117
|
+
* LogExplorer can only render up to 2500 characters in its summary view.
|
|
118
|
+
* We cap at 2000 to leave room for decorating context added by callers.
|
|
119
|
+
*/ function truncateErrorMessage(message) {
|
|
120
|
+
const MAX = 2000;
|
|
121
|
+
const CHUNK = 950;
|
|
122
|
+
if (message.length <= MAX) {
|
|
123
|
+
return message;
|
|
124
|
+
}
|
|
125
|
+
const truncated = message.length - 2 * CHUNK;
|
|
126
|
+
return message.slice(0, CHUNK) + `...${truncated} characters truncated...` + message.slice(-CHUNK);
|
|
127
|
+
}
|
|
115
128
|
/**
|
|
116
129
|
* Formats a Viem error into a FormattedViemError instance.
|
|
117
130
|
* @param error - The error to format.
|
|
@@ -162,18 +175,9 @@ function getNestedErrorData(error) {
|
|
|
162
175
|
}
|
|
163
176
|
// If it's a regular Error instance, return it with its message
|
|
164
177
|
if (error instanceof Error) {
|
|
165
|
-
return new FormattedViemError(error.message, error?.metaMessages);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const length = body.length;
|
|
169
|
-
// LogExplorer can only render up to 2500 characters in it's summary view. Try to keep the whole message below this number
|
|
170
|
-
// Limit the error to 2000 chacaters in order to allow code higher up to decorate this error with extra details (up to 500 characters)
|
|
171
|
-
if (length > 2000) {
|
|
172
|
-
const chunk = 950;
|
|
173
|
-
const truncated = length - 2 * chunk;
|
|
174
|
-
return new FormattedViemError(body.slice(0, chunk) + `...${truncated} characters truncated...` + body.slice(-1 * chunk));
|
|
175
|
-
}
|
|
176
|
-
return new FormattedViemError(body);
|
|
178
|
+
return new FormattedViemError(truncateErrorMessage(error.message), error?.metaMessages);
|
|
179
|
+
}
|
|
180
|
+
return new FormattedViemError(truncateErrorMessage(String(error)));
|
|
177
181
|
}
|
|
178
182
|
function stripAbis(obj) {
|
|
179
183
|
if (!obj || typeof obj !== 'object') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/ethereum",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.8cb2d04d8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./account": "./dest/account.js",
|
|
@@ -50,11 +50,10 @@
|
|
|
50
50
|
"../package.common.json"
|
|
51
51
|
],
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
54
|
-
"@aztec/constants": "0.0.1-commit.
|
|
55
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
56
|
-
"@aztec/l1-artifacts": "0.0.1-commit.
|
|
57
|
-
"@viem/anvil": "^0.0.10",
|
|
53
|
+
"@aztec/blob-lib": "0.0.1-commit.8cb2d04d8",
|
|
54
|
+
"@aztec/constants": "0.0.1-commit.8cb2d04d8",
|
|
55
|
+
"@aztec/foundation": "0.0.1-commit.8cb2d04d8",
|
|
56
|
+
"@aztec/l1-artifacts": "0.0.1-commit.8cb2d04d8",
|
|
58
57
|
"dotenv": "^16.0.3",
|
|
59
58
|
"lodash.chunk": "^4.2.0",
|
|
60
59
|
"lodash.pickby": "^4.5.0",
|
|
@@ -69,7 +68,6 @@
|
|
|
69
68
|
"@types/lodash.pickby": "^4",
|
|
70
69
|
"@types/node": "^22.15.17",
|
|
71
70
|
"@typescript/native-preview": "7.0.0-dev.20260113.1",
|
|
72
|
-
"@viem/anvil": "^0.0.10",
|
|
73
71
|
"get-port": "^7.1.0",
|
|
74
72
|
"jest": "^30.0.0",
|
|
75
73
|
"jest-mock-extended": "^4.0.0",
|
package/src/config.ts
CHANGED
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
type ConfigMappingsType,
|
|
3
3
|
bigintConfigHelper,
|
|
4
4
|
booleanConfigHelper,
|
|
5
|
-
enumConfigHelper,
|
|
6
5
|
getConfigFromMappings,
|
|
7
6
|
getDefaultConfig,
|
|
8
7
|
numberConfigHelper,
|
|
@@ -60,13 +59,13 @@ export type L1ContractsConfig = {
|
|
|
60
59
|
slashingOffsetInRounds: number;
|
|
61
60
|
/** How long slashing can be disabled for in seconds when vetoer disables it */
|
|
62
61
|
slashingDisableDuration: number;
|
|
63
|
-
/**
|
|
64
|
-
|
|
65
|
-
/** Minimum amount that can be slashed
|
|
62
|
+
/** Whether to deploy a slasher proposer */
|
|
63
|
+
slasherEnabled: boolean;
|
|
64
|
+
/** Minimum amount that can be slashed */
|
|
66
65
|
slashAmountSmall: bigint;
|
|
67
|
-
/** Medium amount to slash
|
|
66
|
+
/** Medium amount to slash */
|
|
68
67
|
slashAmountMedium: bigint;
|
|
69
|
-
/** Largest amount that can be slashed per round
|
|
68
|
+
/** Largest amount that can be slashed per round */
|
|
70
69
|
slashAmountLarge: bigint;
|
|
71
70
|
/** Governance proposing quorum (defaults to roundSize/2 + 1) */
|
|
72
71
|
governanceProposerQuorum?: number;
|
|
@@ -152,13 +151,10 @@ export const l1ContractsConfigMappings: ConfigMappingsType<L1ContractsConfig> =
|
|
|
152
151
|
'How many slashing rounds back we slash (ie when slashing in round N, we slash for offenses committed during epochs of round N-offset)',
|
|
153
152
|
...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_SLASHING_OFFSET_IN_ROUNDS),
|
|
154
153
|
},
|
|
155
|
-
|
|
156
|
-
env: '
|
|
157
|
-
description: '
|
|
158
|
-
...
|
|
159
|
-
['empire', 'tally', 'none'] as const,
|
|
160
|
-
l1ContractsDefaultEnv.AZTEC_SLASHER_FLAVOR as 'empire' | 'tally' | 'none',
|
|
161
|
-
),
|
|
154
|
+
slasherEnabled: {
|
|
155
|
+
env: 'AZTEC_SLASHER_ENABLED',
|
|
156
|
+
description: 'Whether to deploy a slasher proposer',
|
|
157
|
+
...booleanConfigHelper(true),
|
|
162
158
|
},
|
|
163
159
|
slashAmountSmall: {
|
|
164
160
|
env: 'AZTEC_SLASH_AMOUNT_SMALL',
|
|
@@ -263,7 +259,7 @@ export const genesisStateConfigMappings: ConfigMappingsType<GenesisStateConfig>
|
|
|
263
259
|
},
|
|
264
260
|
prefundAddresses: {
|
|
265
261
|
env: 'PREFUND_ADDRESSES',
|
|
266
|
-
description: 'Comma-separated list of Aztec addresses to prefund with fee juice at genesis.',
|
|
262
|
+
description: 'Comma-separated list of Aztec addresses to prefund with fee juice at genesis (local network only).',
|
|
267
263
|
parseEnv: (val: string) =>
|
|
268
264
|
val
|
|
269
265
|
.split(',')
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
|
|
2
|
+
import type { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
|
+
|
|
5
|
+
import type { StateOverride } from 'viem';
|
|
6
|
+
|
|
7
|
+
import { type FeeHeader, RollupContract } from './rollup.js';
|
|
8
|
+
|
|
9
|
+
export type PendingCheckpointOverrideState = {
|
|
10
|
+
archive?: Fr;
|
|
11
|
+
feeHeader?: FeeHeader;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** Describes the simulated L1 rollup state that downstream calls should observe. */
|
|
15
|
+
export type SimulationOverridesPlan = {
|
|
16
|
+
pendingCheckpointNumber?: CheckpointNumber;
|
|
17
|
+
pendingCheckpointState?: PendingCheckpointOverrideState;
|
|
18
|
+
disableBlobCheck?: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** Builds a single-checkpoint simulation plan before it is translated into a viem state override. */
|
|
22
|
+
export class SimulationOverridesBuilder {
|
|
23
|
+
private pendingCheckpointNumber?: CheckpointNumber;
|
|
24
|
+
private pendingCheckpointState?: PendingCheckpointOverrideState;
|
|
25
|
+
private disableBlobCheck = false;
|
|
26
|
+
|
|
27
|
+
/** Starts from an existing plan so callers can extend or specialize it. */
|
|
28
|
+
public static from(plan: SimulationOverridesPlan | undefined): SimulationOverridesBuilder {
|
|
29
|
+
return new SimulationOverridesBuilder().merge(plan);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Merges another plan into this builder. Later values win. */
|
|
33
|
+
public merge(plan: SimulationOverridesPlan | undefined): this {
|
|
34
|
+
if (!plan) {
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this.pendingCheckpointNumber = plan.pendingCheckpointNumber;
|
|
39
|
+
this.pendingCheckpointState = plan.pendingCheckpointState
|
|
40
|
+
? { ...(this.pendingCheckpointState ?? {}), ...plan.pendingCheckpointState }
|
|
41
|
+
: this.pendingCheckpointState;
|
|
42
|
+
this.disableBlobCheck = this.disableBlobCheck || (plan.disableBlobCheck ?? false);
|
|
43
|
+
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Sets the checkpoint number that archive and fee header overrides should attach to. */
|
|
48
|
+
public forPendingCheckpoint(pendingCheckpointNumber: CheckpointNumber | undefined): this {
|
|
49
|
+
this.pendingCheckpointNumber = pendingCheckpointNumber;
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Overrides the archive root for the configured pending checkpoint. */
|
|
54
|
+
public withPendingArchive(archive: Fr): this {
|
|
55
|
+
this.assertPendingCheckpointNumber();
|
|
56
|
+
this.pendingCheckpointState = { ...(this.pendingCheckpointState ?? {}), archive };
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Overrides the fee header for the configured pending checkpoint. */
|
|
61
|
+
public withPendingFeeHeader(feeHeader: FeeHeader): this {
|
|
62
|
+
this.assertPendingCheckpointNumber();
|
|
63
|
+
this.pendingCheckpointState = { ...(this.pendingCheckpointState ?? {}), feeHeader };
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Disables blob checking for simulations that cannot provide DA inputs. */
|
|
68
|
+
public withoutBlobCheck(): this {
|
|
69
|
+
this.disableBlobCheck = true;
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Builds the final plan, or `undefined` when no overrides were configured. */
|
|
74
|
+
public build(): SimulationOverridesPlan | undefined {
|
|
75
|
+
if (!this.pendingCheckpointState && this.pendingCheckpointNumber === undefined && !this.disableBlobCheck) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
pendingCheckpointNumber: this.pendingCheckpointNumber,
|
|
81
|
+
pendingCheckpointState: this.pendingCheckpointState,
|
|
82
|
+
disableBlobCheck: this.disableBlobCheck || undefined,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private assertPendingCheckpointNumber(): void {
|
|
87
|
+
if (this.pendingCheckpointNumber === undefined) {
|
|
88
|
+
throw new Error('pendingCheckpointNumber must be set before attaching archive or fee header overrides');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Translates a simulation plan into the viem state override shape expected by rollup calls. */
|
|
94
|
+
export async function buildSimulationOverridesStateOverride(
|
|
95
|
+
rollup: RollupContract,
|
|
96
|
+
plan: SimulationOverridesPlan | undefined,
|
|
97
|
+
): Promise<StateOverride> {
|
|
98
|
+
if (!plan) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const rollupStateDiff: NonNullable<StateOverride[number]['stateDiff']> = [];
|
|
103
|
+
|
|
104
|
+
if (plan.pendingCheckpointNumber !== undefined) {
|
|
105
|
+
rollupStateDiff.push(
|
|
106
|
+
...extractRollupStateDiff(await rollup.makePendingCheckpointNumberOverride(plan.pendingCheckpointNumber)),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (plan.pendingCheckpointState && plan.pendingCheckpointNumber === undefined) {
|
|
111
|
+
throw new Error('pendingCheckpointState requires pendingCheckpointNumber to be set');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (plan.pendingCheckpointState?.archive) {
|
|
115
|
+
rollupStateDiff.push(
|
|
116
|
+
...extractRollupStateDiff(
|
|
117
|
+
rollup.makeArchiveOverride(plan.pendingCheckpointNumber!, plan.pendingCheckpointState.archive),
|
|
118
|
+
),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (plan.pendingCheckpointState?.feeHeader) {
|
|
123
|
+
rollupStateDiff.push(
|
|
124
|
+
...extractRollupStateDiff(
|
|
125
|
+
await rollup.makeFeeHeaderOverride(plan.pendingCheckpointNumber!, plan.pendingCheckpointState.feeHeader),
|
|
126
|
+
),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (plan.disableBlobCheck) {
|
|
131
|
+
rollupStateDiff.push({
|
|
132
|
+
slot: toPaddedHex(RollupContract.checkBlobStorageSlot, true),
|
|
133
|
+
value: toPaddedHex(0n, true),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (rollupStateDiff.length === 0) {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return [{ address: rollup.address, stateDiff: rollupStateDiff }];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function extractRollupStateDiff(override: StateOverride | StateOverride[number] | undefined) {
|
|
145
|
+
const entries = Array.isArray(override) ? override : override ? [override] : [];
|
|
146
|
+
return entries.flatMap(entry => entry.stateDiff ?? []);
|
|
147
|
+
}
|
package/src/contracts/inbox.ts
CHANGED
|
@@ -82,10 +82,10 @@ export class InboxContract {
|
|
|
82
82
|
.map(log => this.mapMessageSentLog(log));
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
/** Fetches MessageSent events for a specific message hash
|
|
86
|
-
async getMessageSentEventByHash(
|
|
87
|
-
const
|
|
88
|
-
return
|
|
85
|
+
/** Fetches MessageSent events for a specific message hash at a specific block. */
|
|
86
|
+
async getMessageSentEventByHash(msgHash: Hex, l1BlockHash: Hex): Promise<MessageSentLog> {
|
|
87
|
+
const [log] = await this.inbox.getEvents.MessageSent({ hash: msgHash }, { blockHash: l1BlockHash });
|
|
88
|
+
return log && this.mapMessageSentLog(log);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
private mapMessageSentLog(log: {
|
package/src/contracts/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './chain_state_override.js';
|
|
1
2
|
export * from './empire_base.js';
|
|
2
3
|
export * from './errors.js';
|
|
3
4
|
export * from './fee_asset_handler.js';
|
|
@@ -12,6 +13,5 @@ export * from './multicall.js';
|
|
|
12
13
|
export * from './outbox.js';
|
|
13
14
|
export * from './registry.js';
|
|
14
15
|
export * from './rollup.js';
|
|
15
|
-
export * from './
|
|
16
|
-
export * from './tally_slashing_proposer.js';
|
|
16
|
+
export * from './slashing_proposer.js';
|
|
17
17
|
export * from './slasher_contract.js';
|