@aztec/slasher 0.87.2-nightly.20250524
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/README.md +5 -0
- package/dest/config.d.ts +40 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +76 -0
- package/dest/epoch_prune_watcher.d.ts +23 -0
- package/dest/epoch_prune_watcher.d.ts.map +1 -0
- package/dest/epoch_prune_watcher.js +77 -0
- package/dest/index.d.ts +4 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +3 -0
- package/dest/slasher_client.d.ts +141 -0
- package/dest/slasher_client.d.ts.map +1 -0
- package/dest/slasher_client.js +309 -0
- package/package.json +83 -0
- package/src/config.ts +118 -0
- package/src/epoch_prune_watcher.ts +94 -0
- package/src/index.ts +3 -0
- package/src/slasher_client.ts +380 -0
package/README.md
ADDED
package/dest/config.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ConfigMappingsType } from '@aztec/foundation/config';
|
|
2
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
4
|
+
export declare enum Offence {
|
|
5
|
+
UNKNOWN = 0,
|
|
6
|
+
EPOCH_PRUNE = 1,
|
|
7
|
+
INACTIVITY = 2
|
|
8
|
+
}
|
|
9
|
+
export declare const OffenceToBigInt: Record<Offence, bigint>;
|
|
10
|
+
export declare function bigIntToOffence(offense: bigint): Offence;
|
|
11
|
+
export declare const WANT_TO_SLASH_EVENT: "wantToSlash";
|
|
12
|
+
export interface WantToSlashArgs {
|
|
13
|
+
validators: `0x${string}`[] | readonly `0x${string}`[];
|
|
14
|
+
amounts: bigint[];
|
|
15
|
+
offenses: Offence[];
|
|
16
|
+
}
|
|
17
|
+
export interface WatcherEventMap {
|
|
18
|
+
[WANT_TO_SLASH_EVENT]: (args: WantToSlashArgs) => void;
|
|
19
|
+
}
|
|
20
|
+
export type WatcherEmitter = TypedEventEmitter<WatcherEventMap>;
|
|
21
|
+
export type CheckSlashFn = (validator: `0x${string}`, amount: bigint, offense: Offence) => Promise<boolean>;
|
|
22
|
+
export type Watcher = WatcherEmitter & {
|
|
23
|
+
shouldSlash: CheckSlashFn;
|
|
24
|
+
start?: () => Promise<void>;
|
|
25
|
+
stop?: () => Promise<void>;
|
|
26
|
+
};
|
|
27
|
+
export interface SlasherConfig {
|
|
28
|
+
slashOverridePayload?: EthAddress;
|
|
29
|
+
slashPayloadTtlSeconds: number;
|
|
30
|
+
slashPruneCreate: boolean;
|
|
31
|
+
slashPrunePenalty: bigint;
|
|
32
|
+
slashPruneSignal: boolean;
|
|
33
|
+
slashInactivityCreateTargetPercentage: number;
|
|
34
|
+
slashInactivityCreatePenalty: bigint;
|
|
35
|
+
slashInactivitySignalTargetPercentage: number;
|
|
36
|
+
slashProposerRoundPollingIntervalSeconds: number;
|
|
37
|
+
}
|
|
38
|
+
export declare const DefaultSlasherConfig: SlasherConfig;
|
|
39
|
+
export declare const slasherConfigMappings: ConfigMappingsType<SlasherConfig>;
|
|
40
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,oBAAY,OAAO;IACjB,OAAO,IAAI;IACX,WAAW,IAAI;IACf,UAAU,IAAI;CACf;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAInD,CAAC;AAEF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAWxD;AAED,eAAO,MAAM,mBAAmB,EAAG,aAAsB,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,KAAK,MAAM,EAAE,EAAE,GAAG,SAAS,KAAK,MAAM,EAAE,EAAE,CAAC;IACvD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAGD,MAAM,WAAW,eAAe;IAC9B,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAEhE,MAAM,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,KAAK,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE5G,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG;IACrC,WAAW,EAAE,YAAY,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,aAAa;IAE5B,oBAAoB,CAAC,EAAE,UAAU,CAAC;IAClC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qCAAqC,EAAE,MAAM,CAAC;IAC9C,4BAA4B,EAAE,MAAM,CAAC;IACrC,qCAAqC,EAAE,MAAM,CAAC;IAC9C,wCAAwC,EAAE,MAAM,CAAC;CAElD;AAED,eAAO,MAAM,oBAAoB,EAAE,aAUlC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,kBAAkB,CAAC,aAAa,CAsCnE,CAAC"}
|
package/dest/config.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { bigintConfigHelper, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
|
|
2
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
export var Offence = /*#__PURE__*/ function(Offence) {
|
|
4
|
+
Offence[Offence["UNKNOWN"] = 0] = "UNKNOWN";
|
|
5
|
+
Offence[Offence["EPOCH_PRUNE"] = 1] = "EPOCH_PRUNE";
|
|
6
|
+
Offence[Offence["INACTIVITY"] = 2] = "INACTIVITY";
|
|
7
|
+
return Offence;
|
|
8
|
+
}({});
|
|
9
|
+
export const OffenceToBigInt = {
|
|
10
|
+
[0]: 0n,
|
|
11
|
+
[1]: 1n,
|
|
12
|
+
[2]: 2n
|
|
13
|
+
};
|
|
14
|
+
export function bigIntToOffence(offense) {
|
|
15
|
+
switch(offense){
|
|
16
|
+
case 0n:
|
|
17
|
+
return 0;
|
|
18
|
+
case 1n:
|
|
19
|
+
return 1;
|
|
20
|
+
case 2n:
|
|
21
|
+
return 2;
|
|
22
|
+
default:
|
|
23
|
+
throw new Error(`Unknown offence: ${offense}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export const WANT_TO_SLASH_EVENT = 'wantToSlash';
|
|
27
|
+
export const DefaultSlasherConfig = {
|
|
28
|
+
slashInactivityCreatePenalty: 1n,
|
|
29
|
+
slashInactivityCreateTargetPercentage: 0.9,
|
|
30
|
+
slashInactivitySignalTargetPercentage: 0.6,
|
|
31
|
+
slashPayloadTtlSeconds: 60 * 60 * 24,
|
|
32
|
+
slashPruneCreate: false,
|
|
33
|
+
slashPrunePenalty: 1n,
|
|
34
|
+
slashPruneSignal: true,
|
|
35
|
+
slashOverridePayload: undefined,
|
|
36
|
+
slashProposerRoundPollingIntervalSeconds: 12
|
|
37
|
+
};
|
|
38
|
+
export const slasherConfigMappings = {
|
|
39
|
+
slashOverridePayload: {
|
|
40
|
+
description: 'An Ethereum address for a slash payload to vote for unconditionally.',
|
|
41
|
+
parseEnv: (val)=>val ? EthAddress.fromString(val) : undefined,
|
|
42
|
+
defaultValue: DefaultSlasherConfig.slashOverridePayload
|
|
43
|
+
},
|
|
44
|
+
slashPayloadTtlSeconds: {
|
|
45
|
+
description: 'Time-to-live for slash payloads in seconds.',
|
|
46
|
+
...numberConfigHelper(DefaultSlasherConfig.slashPayloadTtlSeconds)
|
|
47
|
+
},
|
|
48
|
+
slashPruneCreate: {
|
|
49
|
+
description: 'Enable creation of slash payloads for pruned epochs.',
|
|
50
|
+
...booleanConfigHelper(DefaultSlasherConfig.slashPruneCreate)
|
|
51
|
+
},
|
|
52
|
+
slashPrunePenalty: {
|
|
53
|
+
description: 'Penalty amount for slashing validators of a pruned epoch.',
|
|
54
|
+
...bigintConfigHelper(DefaultSlasherConfig.slashPrunePenalty)
|
|
55
|
+
},
|
|
56
|
+
slashPruneSignal: {
|
|
57
|
+
description: 'Enable voting for slash payloads for pruned epochs.',
|
|
58
|
+
...booleanConfigHelper(DefaultSlasherConfig.slashPruneSignal)
|
|
59
|
+
},
|
|
60
|
+
slashInactivityCreateTargetPercentage: {
|
|
61
|
+
description: 'Missed attestation percentage to trigger creation of inactivity slash payload (0-100).',
|
|
62
|
+
...numberConfigHelper(DefaultSlasherConfig.slashInactivityCreateTargetPercentage)
|
|
63
|
+
},
|
|
64
|
+
slashInactivityCreatePenalty: {
|
|
65
|
+
description: 'Penalty amount for slashing an inactive validator.',
|
|
66
|
+
...bigintConfigHelper(DefaultSlasherConfig.slashInactivityCreatePenalty)
|
|
67
|
+
},
|
|
68
|
+
slashInactivitySignalTargetPercentage: {
|
|
69
|
+
description: 'Missed attestation percentage to trigger voting for an inactivity slash payload (0-100).',
|
|
70
|
+
...numberConfigHelper(DefaultSlasherConfig.slashInactivitySignalTargetPercentage)
|
|
71
|
+
},
|
|
72
|
+
slashProposerRoundPollingIntervalSeconds: {
|
|
73
|
+
description: 'Polling interval for slashing proposer round in seconds.',
|
|
74
|
+
...numberConfigHelper(DefaultSlasherConfig.slashProposerRoundPollingIntervalSeconds)
|
|
75
|
+
}
|
|
76
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EpochCache } from '@aztec/epoch-cache';
|
|
2
|
+
import { type L2BlockSourceEventEmitter } from '@aztec/stdlib/block';
|
|
3
|
+
import { Offence, type Watcher, type WatcherEmitter } from './config.js';
|
|
4
|
+
declare const EpochPruneWatcher_base: new () => WatcherEmitter;
|
|
5
|
+
export declare class EpochPruneWatcher extends EpochPruneWatcher_base implements Watcher {
|
|
6
|
+
private l2BlockSource;
|
|
7
|
+
private epochCache;
|
|
8
|
+
private penalty;
|
|
9
|
+
private log;
|
|
10
|
+
private prunedEpochs;
|
|
11
|
+
private maxPrunedEpochs;
|
|
12
|
+
constructor(l2BlockSource: L2BlockSourceEventEmitter, epochCache: EpochCache, penalty: bigint);
|
|
13
|
+
start(): Promise<void>;
|
|
14
|
+
stop(): Promise<void>;
|
|
15
|
+
private handlePruneL2Blocks;
|
|
16
|
+
private addToPrunedEpochs;
|
|
17
|
+
private getValidatorsForEpoch;
|
|
18
|
+
private validatorsToSlashingArgs;
|
|
19
|
+
private wantToSlashForEpoch;
|
|
20
|
+
shouldSlash(validator: `0x${string}`, amount: bigint, _offense: Offence): Promise<boolean>;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=epoch_prune_watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"epoch_prune_watcher.d.ts","sourceRoot":"","sources":["../src/epoch_prune_watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAA2B,KAAK,yBAAyB,EAAuB,MAAM,qBAAqB,CAAC;AAKnH,OAAO,EAAE,OAAO,EAA6C,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;sCAE5D,UAAU,cAAc;AAAhF,qBAAa,iBAAkB,SAAQ,sBAA2C,YAAW,OAAO;IAShG,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,OAAO;IAVjB,OAAO,CAAC,GAAG,CAA+C;IAG1D,OAAO,CAAC,YAAY,CAA2C;IAE/D,OAAO,CAAC,eAAe,CAAO;gBAGpB,aAAa,EAAE,yBAAyB,EACxC,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,MAAM;IAMlB,KAAK;IAKL,IAAI;IASX,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,CAAC,iBAAiB;YAOX,qBAAqB;IAKnC,OAAO,CAAC,wBAAwB;IAUhC,OAAO,CAAC,mBAAmB;IAIpB,WAAW,CAAC,SAAS,EAAE,KAAK,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CASlG"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import { L2BlockSourceEvents } from '@aztec/stdlib/block';
|
|
3
|
+
import EventEmitter from 'node:events';
|
|
4
|
+
import { Offence, WANT_TO_SLASH_EVENT } from './config.js';
|
|
5
|
+
export class EpochPruneWatcher extends EventEmitter {
|
|
6
|
+
l2BlockSource;
|
|
7
|
+
epochCache;
|
|
8
|
+
penalty;
|
|
9
|
+
log;
|
|
10
|
+
// Keep track of pruned epochs we've seen to their committee
|
|
11
|
+
prunedEpochs;
|
|
12
|
+
// Only keep track of the last N pruned epochs
|
|
13
|
+
maxPrunedEpochs;
|
|
14
|
+
constructor(l2BlockSource, epochCache, penalty){
|
|
15
|
+
super(), this.l2BlockSource = l2BlockSource, this.epochCache = epochCache, this.penalty = penalty, this.log = createLogger('epoch-prune-watcher'), this.prunedEpochs = new Map(), this.maxPrunedEpochs = 100;
|
|
16
|
+
this.log.info('EpochPruneWatcher initialized');
|
|
17
|
+
}
|
|
18
|
+
start() {
|
|
19
|
+
this.l2BlockSource.on(L2BlockSourceEvents.L2PruneDetected, this.handlePruneL2Blocks.bind(this));
|
|
20
|
+
return Promise.resolve();
|
|
21
|
+
}
|
|
22
|
+
stop() {
|
|
23
|
+
this.l2BlockSource.removeListener(L2BlockSourceEvents.L2PruneDetected, this.handlePruneL2Blocks.bind(this));
|
|
24
|
+
return Promise.resolve();
|
|
25
|
+
}
|
|
26
|
+
// TODO(#14407), TODO(#14408)
|
|
27
|
+
// We should only be slashing due to prune if:
|
|
28
|
+
// - the data was not available (#14407)
|
|
29
|
+
// - OR the data was available and the epoch could have been proven (#14408)
|
|
30
|
+
handlePruneL2Blocks(event) {
|
|
31
|
+
const { epochNumber } = event;
|
|
32
|
+
this.log.info(`Detected chain prune. Attempting to create slash for epoch ${epochNumber}`, event);
|
|
33
|
+
this.getValidatorsForEpoch(epochNumber).then((validators)=>{
|
|
34
|
+
const args = this.validatorsToSlashingArgs(validators);
|
|
35
|
+
if (args) {
|
|
36
|
+
this.addToPrunedEpochs(epochNumber, validators);
|
|
37
|
+
this.emit(WANT_TO_SLASH_EVENT, args);
|
|
38
|
+
}
|
|
39
|
+
}).catch((error)=>{
|
|
40
|
+
this.log.error('Error getting validators for epoch', error);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
addToPrunedEpochs(epochNumber, validators) {
|
|
44
|
+
this.prunedEpochs.set(epochNumber, validators);
|
|
45
|
+
if (this.prunedEpochs.size > this.maxPrunedEpochs) {
|
|
46
|
+
this.prunedEpochs.delete(this.prunedEpochs.keys().next().value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async getValidatorsForEpoch(epochNumber) {
|
|
50
|
+
const { committee } = await this.epochCache.getCommitteeForEpoch(epochNumber);
|
|
51
|
+
return committee.map((v)=>v.toString());
|
|
52
|
+
}
|
|
53
|
+
validatorsToSlashingArgs(validators) {
|
|
54
|
+
if (validators.length === 0) {
|
|
55
|
+
this.log.debug('No validators found for epoch, skipping slash creation.');
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
const amounts = Array(validators.length).fill(this.penalty);
|
|
59
|
+
const offenses = Array(validators.length).fill(Offence.EPOCH_PRUNE);
|
|
60
|
+
return {
|
|
61
|
+
validators,
|
|
62
|
+
amounts,
|
|
63
|
+
offenses
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
wantToSlashForEpoch(validator, amount, epochNumber) {
|
|
67
|
+
return this.prunedEpochs.get(epochNumber)?.includes(validator) ?? false;
|
|
68
|
+
}
|
|
69
|
+
shouldSlash(validator, amount, _offense) {
|
|
70
|
+
for (const epoch of this.prunedEpochs.keys()){
|
|
71
|
+
if (this.wantToSlashForEpoch(validator, amount, epoch)) {
|
|
72
|
+
return Promise.resolve(true);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return Promise.resolve(false);
|
|
76
|
+
}
|
|
77
|
+
}
|
package/dest/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC"}
|
package/dest/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { type ExtendedViemWalletClient, type L1ReaderConfig, L1TxUtils, SlashingProposerContract } from '@aztec/ethereum';
|
|
2
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import type { DateProvider } from '@aztec/foundation/timer';
|
|
4
|
+
import { SlashFactoryAbi } from '@aztec/l1-artifacts';
|
|
5
|
+
import { type GetContractReturnType } from 'viem';
|
|
6
|
+
import { Offence, type SlasherConfig, type Watcher } from './config.js';
|
|
7
|
+
type MonitoredSlashPayload = {
|
|
8
|
+
payloadAddress: EthAddress;
|
|
9
|
+
validators: readonly EthAddress[];
|
|
10
|
+
amounts: readonly bigint[];
|
|
11
|
+
offenses: readonly Offence[];
|
|
12
|
+
observedAtSeconds: number;
|
|
13
|
+
totalAmount: bigint;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A Spartiate slasher client implementation
|
|
17
|
+
*
|
|
18
|
+
* Spartiates: a full citizen of the ancient polis of Sparta, member of an elite warrior class.
|
|
19
|
+
*
|
|
20
|
+
* How it works:
|
|
21
|
+
*
|
|
22
|
+
* The constructor accepts instances of Watcher classes that correspond to specific offences. These "watchers" do two things:
|
|
23
|
+
* - watch for their offence conditions and emit an event when they are detected
|
|
24
|
+
* - confirm/deny whether they agree with a proposed offence
|
|
25
|
+
*
|
|
26
|
+
* The SlasherClient class is responsible for:
|
|
27
|
+
* - listening for events from the watchers and creating a corresponding payload
|
|
28
|
+
* - listening for the payloads from L1 filtering them through the watchers
|
|
29
|
+
* - ordering the payloads and discarding stale payloads
|
|
30
|
+
* - presenting the payload that ought to be currently voted for
|
|
31
|
+
* - detecting when it wants to execute a round
|
|
32
|
+
* - executing a round
|
|
33
|
+
* - listening for the round to be executed
|
|
34
|
+
* - removing the executed round from the list of monitored payloads
|
|
35
|
+
*
|
|
36
|
+
* A few improvements:
|
|
37
|
+
* - TODO(#14421): Only vote on the proposal if it is possible to reach quorum, e.g., if 6 votes are needed and only 4 slots are left don't vote.
|
|
38
|
+
*/
|
|
39
|
+
export declare class SlasherClient {
|
|
40
|
+
config: SlasherConfig;
|
|
41
|
+
protected slashFactoryContract: GetContractReturnType<typeof SlashFactoryAbi, ExtendedViemWalletClient>;
|
|
42
|
+
private slashingProposer;
|
|
43
|
+
private l1TxUtils;
|
|
44
|
+
private watchers;
|
|
45
|
+
private dateProvider;
|
|
46
|
+
private log;
|
|
47
|
+
private monitoredPayloads;
|
|
48
|
+
private unwatchCallbacks;
|
|
49
|
+
static new(config: SlasherConfig, l1Contracts: Pick<L1ReaderConfig['l1Contracts'], 'rollupAddress' | 'slashFactoryAddress'>, l1TxUtils: L1TxUtils, watchers: Watcher[], dateProvider: DateProvider): Promise<SlasherClient>;
|
|
50
|
+
constructor(config: SlasherConfig, slashFactoryContract: GetContractReturnType<typeof SlashFactoryAbi, ExtendedViemWalletClient>, slashingProposer: SlashingProposerContract, l1TxUtils: L1TxUtils, watchers: Watcher[], dateProvider: DateProvider, log?: import("@aztec/foundation/log").Logger);
|
|
51
|
+
start(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Allows consumers to stop the instance of the slasher client.
|
|
54
|
+
* 'ready' will now return 'false' and the running promise that keeps the client synced is interrupted.
|
|
55
|
+
*/
|
|
56
|
+
stop(): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Get the payload to slash
|
|
59
|
+
*
|
|
60
|
+
* @param _slotNumber the current slot number (unused)
|
|
61
|
+
* @returns the payload to slash or undefined if there is no payload to slash
|
|
62
|
+
*/
|
|
63
|
+
getSlashPayload(_slotNumber: bigint): Promise<EthAddress | undefined>;
|
|
64
|
+
/**
|
|
65
|
+
* Get the list of monitored payloads
|
|
66
|
+
*
|
|
67
|
+
* Useful for tests.
|
|
68
|
+
*
|
|
69
|
+
* @returns the list of monitored payloads
|
|
70
|
+
*/
|
|
71
|
+
getMonitoredPayloads(): MonitoredSlashPayload[];
|
|
72
|
+
/**
|
|
73
|
+
* This is called when a watcher emits WANT_TO_SLASH_EVENT.
|
|
74
|
+
*
|
|
75
|
+
* @param args - the arguments from the watcher, including the validators, amounts, and offenses
|
|
76
|
+
*/
|
|
77
|
+
private wantToSlash;
|
|
78
|
+
/**
|
|
79
|
+
* Watch for new payloads created by the slash factory
|
|
80
|
+
*
|
|
81
|
+
* Whenever a log has events, we iterate over them and convert them to MonitoredSlashPayloads
|
|
82
|
+
*
|
|
83
|
+
* We then add the payloads to the list of monitored payloads if we agree with them
|
|
84
|
+
*
|
|
85
|
+
* @returns a callback to remove the watcher
|
|
86
|
+
*/
|
|
87
|
+
private watchSlashFactoryEvents;
|
|
88
|
+
/**
|
|
89
|
+
* Convert a list of factory events to an iterable of monitored payloads
|
|
90
|
+
*
|
|
91
|
+
* @param args
|
|
92
|
+
* @returns the list of monitored payloads
|
|
93
|
+
*/
|
|
94
|
+
private factoryEventsToMonitoredPayloads;
|
|
95
|
+
/**
|
|
96
|
+
* Add a payload to the list of monitored payloads if we agree with it
|
|
97
|
+
*
|
|
98
|
+
* @param payload
|
|
99
|
+
*/
|
|
100
|
+
private addMonitoredPayload;
|
|
101
|
+
/**
|
|
102
|
+
* Check if we agree with a payload
|
|
103
|
+
*
|
|
104
|
+
* We check each offense and validator pair against the watchers
|
|
105
|
+
*
|
|
106
|
+
* @param payload
|
|
107
|
+
* @returns true if any watcher agrees with the payload, false otherwise
|
|
108
|
+
*/
|
|
109
|
+
private doIAgreeWithPayload;
|
|
110
|
+
/**
|
|
111
|
+
* Sort the monitored payloads by total amount in descending order
|
|
112
|
+
*/
|
|
113
|
+
private sortMonitoredPayloads;
|
|
114
|
+
/**
|
|
115
|
+
* Filter out payloads that have expired
|
|
116
|
+
*
|
|
117
|
+
* @param currentTimeSeconds
|
|
118
|
+
* @param payloadTtlSeconds
|
|
119
|
+
*/
|
|
120
|
+
private filterExpiredPayloads;
|
|
121
|
+
/**
|
|
122
|
+
* Execute a round if we agree with the proposal.
|
|
123
|
+
*
|
|
124
|
+
* Bound to the slashing proposer contract's listenToExecutableProposals method in the constructor.
|
|
125
|
+
*
|
|
126
|
+
* @param {proposal: `0x${string}`; round: bigint} param0
|
|
127
|
+
*/
|
|
128
|
+
private executeRoundIfAgree;
|
|
129
|
+
/**
|
|
130
|
+
* Handler for when a proposal is executed.
|
|
131
|
+
*
|
|
132
|
+
* Removes the first matching payload from the list of monitored payloads.
|
|
133
|
+
*
|
|
134
|
+
* Bound to the slashing proposer contract's listenToProposalExecuted method in the constructor.
|
|
135
|
+
*
|
|
136
|
+
* @param {round: bigint; proposal: `0x${string}`} param0
|
|
137
|
+
*/
|
|
138
|
+
private proposalExecuted;
|
|
139
|
+
}
|
|
140
|
+
export {};
|
|
141
|
+
//# sourceMappingURL=slasher_client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slasher_client.d.ts","sourceRoot":"","sources":["../src/slasher_client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,SAAS,EAGT,wBAAwB,EACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAEL,KAAK,qBAAqB,EAI3B,MAAM,MAAM,CAAC;AAEd,OAAO,EACL,OAAO,EACP,KAAK,aAAa,EAGlB,KAAK,OAAO,EAEb,MAAM,aAAa,CAAC;AAErB,KAAK,qBAAqB,GAAG;IAC3B,cAAc,EAAE,UAAU,CAAC;IAC3B,UAAU,EAAE,SAAS,UAAU,EAAE,CAAC;IAClC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,aAAa;IA6Bf,MAAM,EAAE,aAAa;IAC5B,SAAS,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,OAAO,eAAe,EAAE,wBAAwB,CAAC;IACvG,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,GAAG;IAlCb,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,gBAAgB,CAAsB;WAEjC,GAAG,CACd,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,EAAE,eAAe,GAAG,qBAAqB,CAAC,EACzF,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,OAAO,EAAE,EACnB,YAAY,EAAE,YAAY;gBAoBnB,MAAM,EAAE,aAAa,EAClB,oBAAoB,EAAE,qBAAqB,CAAC,OAAO,eAAe,EAAE,wBAAwB,CAAC,EAC/F,gBAAgB,EAAE,wBAAwB,EAC1C,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,OAAO,EAAE,EACnB,YAAY,EAAE,YAAY,EAC1B,GAAG,yCAA0B;IAK1B,KAAK;IAuBlB;;;OAGG;IACU,IAAI;IAajB;;;;;OAKG;IACI,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAoB5E;;;;;;OAMG;IACI,oBAAoB,IAAI,qBAAqB,EAAE;IAMtD;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAmBnB;;;;;;;;OAQG;IACH,OAAO,CAAC,uBAAuB;IAc/B;;;;;OAKG;IACH,OAAO,CAAE,gCAAgC;IAuBzC;;;;OAIG;YACW,mBAAmB;IASjC;;;;;;;OAOG;YACW,mBAAmB;IA2BjC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;;;;;OAMG;YACW,mBAAmB;IA0BjC;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;CAQzB"}
|