@aztec/slasher 0.0.1-commit.6230efd → 0.0.1-commit.6a729f7
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 +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +16 -16
- package/dest/empire_slasher_client.d.ts +1 -1
- package/dest/empire_slasher_client.d.ts.map +1 -1
- package/dest/empire_slasher_client.js +0 -8
- package/dest/factory/create_facade.js +1 -1
- package/dest/generated/slasher-defaults.d.ts +19 -0
- package/dest/generated/slasher-defaults.d.ts.map +1 -0
- package/dest/generated/slasher-defaults.js +19 -0
- package/dest/slash_offenses_collector.d.ts +1 -1
- package/dest/slash_offenses_collector.d.ts.map +1 -1
- package/dest/slash_offenses_collector.js +5 -1
- package/dest/stores/offenses_store.d.ts +1 -1
- package/dest/stores/offenses_store.d.ts.map +1 -1
- package/dest/stores/offenses_store.js +4 -2
- package/dest/stores/payloads_store.d.ts +1 -1
- package/dest/stores/payloads_store.d.ts.map +1 -1
- package/dest/stores/payloads_store.js +6 -3
- package/dest/tally_slasher_client.d.ts +1 -1
- package/dest/tally_slasher_client.d.ts.map +1 -1
- package/dest/tally_slasher_client.js +10 -5
- package/dest/watchers/attestations_block_watcher.d.ts +7 -6
- package/dest/watchers/attestations_block_watcher.d.ts.map +1 -1
- package/dest/watchers/attestations_block_watcher.js +40 -34
- package/dest/watchers/epoch_prune_watcher.d.ts +7 -6
- package/dest/watchers/epoch_prune_watcher.d.ts.map +1 -1
- package/dest/watchers/epoch_prune_watcher.js +31 -10
- package/package.json +14 -12
- package/src/config.ts +17 -16
- package/src/empire_slasher_client.ts +0 -8
- package/src/factory/create_facade.ts +1 -1
- package/src/generated/slasher-defaults.ts +21 -0
- package/src/slash_offenses_collector.ts +5 -1
- package/src/stores/offenses_store.ts +4 -2
- package/src/stores/payloads_store.ts +7 -4
- package/src/tally_slasher_client.ts +10 -5
- package/src/watchers/attestations_block_watcher.ts +57 -44
- package/src/watchers/epoch_prune_watcher.ts +42 -15
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
2
2
|
import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { merge, pick } from '@aztec/foundation/collection';
|
|
4
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
5
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
5
6
|
import {
|
|
6
7
|
EthAddress,
|
|
7
8
|
L2Block,
|
|
8
|
-
type L2BlockPruneEvent,
|
|
9
9
|
type L2BlockSourceEventEmitter,
|
|
10
10
|
L2BlockSourceEvents,
|
|
11
|
+
type L2PruneUnprovenEvent,
|
|
11
12
|
} from '@aztec/stdlib/block';
|
|
12
13
|
import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
13
14
|
import type {
|
|
14
|
-
|
|
15
|
+
ICheckpointsBuilder,
|
|
15
16
|
ITxProvider,
|
|
16
17
|
MerkleTreeWriteOperations,
|
|
17
18
|
SlasherConfig,
|
|
18
19
|
} from '@aztec/stdlib/interfaces/server';
|
|
19
|
-
import type
|
|
20
|
+
import { type L1ToL2MessageSource, computeCheckpointOutHash } from '@aztec/stdlib/messaging';
|
|
20
21
|
import { OffenseType, getOffenseTypeName } from '@aztec/stdlib/slashing';
|
|
22
|
+
import type { CheckpointGlobalVariables } from '@aztec/stdlib/tx';
|
|
21
23
|
import {
|
|
22
24
|
ReExFailedTxsError,
|
|
23
25
|
ReExStateMismatchError,
|
|
@@ -52,7 +54,7 @@ export class EpochPruneWatcher extends (EventEmitter as new () => WatcherEmitter
|
|
|
52
54
|
private l1ToL2MessageSource: L1ToL2MessageSource,
|
|
53
55
|
private epochCache: EpochCache,
|
|
54
56
|
private txProvider: Pick<ITxProvider, 'getAvailableTxs'>,
|
|
55
|
-
private
|
|
57
|
+
private checkpointsBuilder: ICheckpointsBuilder,
|
|
56
58
|
penalties: EpochPruneWatcherPenalties,
|
|
57
59
|
) {
|
|
58
60
|
super();
|
|
@@ -63,12 +65,12 @@ export class EpochPruneWatcher extends (EventEmitter as new () => WatcherEmitter
|
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
public start() {
|
|
66
|
-
this.l2BlockSource.on(L2BlockSourceEvents.
|
|
68
|
+
this.l2BlockSource.events.on(L2BlockSourceEvents.L2PruneUnproven, this.boundHandlePruneL2Blocks);
|
|
67
69
|
return Promise.resolve();
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
public stop() {
|
|
71
|
-
this.l2BlockSource.removeListener(L2BlockSourceEvents.
|
|
73
|
+
this.l2BlockSource.events.removeListener(L2BlockSourceEvents.L2PruneUnproven, this.boundHandlePruneL2Blocks);
|
|
72
74
|
return Promise.resolve();
|
|
73
75
|
}
|
|
74
76
|
|
|
@@ -77,7 +79,7 @@ export class EpochPruneWatcher extends (EventEmitter as new () => WatcherEmitter
|
|
|
77
79
|
this.log.verbose('EpochPruneWatcher config updated', this.penalties);
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
private handlePruneL2Blocks(event:
|
|
82
|
+
private handlePruneL2Blocks(event: L2PruneUnprovenEvent): void {
|
|
81
83
|
const { blocks, epochNumber } = event;
|
|
82
84
|
void this.processPruneL2Blocks(blocks, epochNumber).catch(err =>
|
|
83
85
|
this.log.error('Error processing pruned L2 blocks', err, { epochNumber }),
|
|
@@ -98,7 +100,7 @@ export class EpochPruneWatcher extends (EventEmitter as new () => WatcherEmitter
|
|
|
98
100
|
private async processPruneL2Blocks(blocks: L2Block[], epochNumber: EpochNumber): Promise<void> {
|
|
99
101
|
try {
|
|
100
102
|
const l1Constants = this.epochCache.getL1Constants();
|
|
101
|
-
const epochBlocks = blocks.filter(b => getEpochAtSlot(b.
|
|
103
|
+
const epochBlocks = blocks.filter(b => getEpochAtSlot(b.header.getSlot(), l1Constants) === epochNumber);
|
|
102
104
|
this.log.info(
|
|
103
105
|
`Detected chain prune. Validating epoch ${epochNumber} with blocks ${epochBlocks[0]?.number} to ${epochBlocks[epochBlocks.length - 1]?.number}.`,
|
|
104
106
|
{ blocks: epochBlocks.map(b => b.toBlockInfo()) },
|
|
@@ -123,17 +125,27 @@ export class EpochPruneWatcher extends (EventEmitter as new () => WatcherEmitter
|
|
|
123
125
|
if (blocks.length === 0) {
|
|
124
126
|
return;
|
|
125
127
|
}
|
|
126
|
-
|
|
128
|
+
|
|
129
|
+
let previousCheckpointOutHashes: Fr[] = [];
|
|
130
|
+
const fork = await this.checkpointsBuilder.getFork(BlockNumber(blocks[0].header.globalVariables.blockNumber - 1));
|
|
127
131
|
try {
|
|
128
132
|
for (const block of blocks) {
|
|
129
|
-
await this.validateBlock(block, fork);
|
|
133
|
+
await this.validateBlock(block, previousCheckpointOutHashes, fork);
|
|
134
|
+
|
|
135
|
+
// TODO(mbps): This assumes one block per checkpoint, which is only true for now.
|
|
136
|
+
const checkpointOutHash = computeCheckpointOutHash([block.body.txEffects.map(tx => tx.l2ToL1Msgs)]);
|
|
137
|
+
previousCheckpointOutHashes = [...previousCheckpointOutHashes, checkpointOutHash];
|
|
130
138
|
}
|
|
131
139
|
} finally {
|
|
132
140
|
await fork.close();
|
|
133
141
|
}
|
|
134
142
|
}
|
|
135
143
|
|
|
136
|
-
public async validateBlock(
|
|
144
|
+
public async validateBlock(
|
|
145
|
+
blockFromL1: L2Block,
|
|
146
|
+
previousCheckpointOutHashes: Fr[],
|
|
147
|
+
fork: MerkleTreeWriteOperations,
|
|
148
|
+
): Promise<void> {
|
|
137
149
|
this.log.debug(`Validating pruned block ${blockFromL1.header.globalVariables.blockNumber}`);
|
|
138
150
|
const txHashes = blockFromL1.body.txEffects.map(txEffect => txEffect.txHash);
|
|
139
151
|
// We load txs from the mempool directly, since the TxCollector running in the background has already been
|
|
@@ -147,13 +159,28 @@ export class EpochPruneWatcher extends (EventEmitter as new () => WatcherEmitter
|
|
|
147
159
|
|
|
148
160
|
const checkpointNumber = CheckpointNumber.fromBlockNumber(blockFromL1.number);
|
|
149
161
|
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(checkpointNumber);
|
|
150
|
-
const
|
|
151
|
-
|
|
162
|
+
const gv = blockFromL1.header.globalVariables;
|
|
163
|
+
const constants: CheckpointGlobalVariables = {
|
|
164
|
+
chainId: gv.chainId,
|
|
165
|
+
version: gv.version,
|
|
166
|
+
slotNumber: gv.slotNumber,
|
|
167
|
+
coinbase: gv.coinbase,
|
|
168
|
+
feeRecipient: gv.feeRecipient,
|
|
169
|
+
gasFees: gv.gasFees,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Use checkpoint builder to validate the block
|
|
173
|
+
const checkpointBuilder = await this.checkpointsBuilder.startCheckpoint(
|
|
174
|
+
checkpointNumber,
|
|
175
|
+
constants,
|
|
152
176
|
l1ToL2Messages,
|
|
153
|
-
|
|
154
|
-
{},
|
|
177
|
+
previousCheckpointOutHashes,
|
|
155
178
|
fork,
|
|
179
|
+
this.log.getBindings(),
|
|
156
180
|
);
|
|
181
|
+
|
|
182
|
+
const { block, failedTxs, numTxs } = await checkpointBuilder.buildBlock(txs, gv.blockNumber, gv.timestamp, {});
|
|
183
|
+
|
|
157
184
|
if (numTxs !== txs.length) {
|
|
158
185
|
// This should be detected by state mismatch, but this makes it easier to debug.
|
|
159
186
|
throw new ValidatorError(`Built block with ${numTxs} txs, expected ${txs.length}`);
|