Skip to content

Commit e656aba

Browse files
committed
feat: Fault Proof support (Phase 1 & 2)
Phase 1 - Challenger EOA Monitoring: - Add op-challenger component to OP Stack topology - Implement Challenger EOA balance monitoring - Add auto-refill playbooks for critical balance - Update component dependencies and K8s configs Phase 2 - Dispute Game & Bond Management: - Implement DisputeGameMonitor for on-chain game tracking - Implement BondManager for automatic bond claims - Add playbooks: deadline alerts, unclaimed bonds, proof timeouts - Add dispute game metrics and monitoring New Playbooks: - challenger-balance-low (Phase 1) - challenger-balance-critical with auto-refill (Phase 1) - op-challenger-failure detection (Phase 1) - dispute-game-deadline-near (Phase 2) - unclaimed-bond-alert with auto-claim (Phase 2) - proof-generation-timeout (Phase 2) Configuration: - Add FAULT_PROOF_ENABLED flag - Add CHALLENGER_EOA_ADDRESS / CHALLENGER_PRIVATE_KEY - Add DISPUTE_GAME_FACTORY_ADDRESS - Add bond and deadline threshold configs AI Prompts: - Update RCA system prompt with op-challenger component - Add Fault Proof failure patterns Note: Phase 2 contracts require DisputeGameFactory ABI for full on-chain integration (marked as TODO).
1 parent 99ed228 commit e656aba

File tree

7 files changed

+624
-5
lines changed

7 files changed

+624
-5
lines changed

.env.local.sample

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ AWS_CLUSTER_NAME=my-cluster-name
4949
# 1. Manual EOA addresses (if you know the addresses)
5050
# BATCHER_EOA_ADDRESS=0x... # Batcher EOA address to monitor
5151
# PROPOSER_EOA_ADDRESS=0x... # Proposer EOA address to monitor
52+
# CHALLENGER_EOA_ADDRESS=0x... # Challenger EOA address (Fault Proof only)
5253
#
5354
# 2. Private key derivation (derive EOA from private key, no L1 RPC required)
5455
# BATCHER_PRIVATE_KEY=0x... # Batcher private key → derive EOA address
5556
# PROPOSER_PRIVATE_KEY=0x... # Proposer private key → derive EOA address
57+
# CHALLENGER_PRIVATE_KEY=0x... # Challenger private key (Fault Proof only)
5658
#
5759
# Auto-refill Configuration (requires treasury wallet):
5860
# TREASURY_PRIVATE_KEY=0x... # Treasury wallet private key for auto-refill (omit for monitor-only)
@@ -115,6 +117,26 @@ AWS_CLUSTER_NAME=my-cluster-name
115117
# LLM_TEST_PARALLELISM_DEFAULT=5 # Default concurrent requests
116118
# LLM_TEST_OUTPUT_DIR=src/lib/__tests__/llm-stress-test/output # Result output directory
117119

120+
# === Fault Proof (Optional - Phase 1 & 2) ===
121+
# Enable Fault Proof monitoring for OP Stack deployments with dispute game system.
122+
# Requires op-challenger component to be deployed.
123+
#
124+
# Phase 1: Challenger EOA monitoring + auto-refill
125+
# FAULT_PROOF_ENABLED=true # Enable Fault Proof features
126+
# CHALLENGER_EOA_ADDRESS=0x... # Challenger EOA to monitor (see EOA section above)
127+
# CHALLENGER_PRIVATE_KEY=0x... # For bond claims + balance derivation
128+
#
129+
# Phase 2: Dispute Game monitoring + Bond management
130+
# DISPUTE_GAME_FACTORY_ADDRESS=0x... # L1 DisputeGameFactory contract address
131+
# GAME_DEADLINE_ALERT_HOURS=24 # Alert when game deadline < N hours (default: 24)
132+
# AUTO_BOND_CLAIM=true # Auto-claim bonds from won games (default: false)
133+
#
134+
# Bond thresholds (Challenger-specific):
135+
# CHALLENGER_BOND_MIN_ETH=0.8 # Minimum total balance for bond participation (10 games × 0.08)
136+
# CHALLENGER_BOND_REFILL_ETH=1.0 # Auto-refill amount when balance critical
137+
# CHALLENGER_BALANCE_WARNING_ETH=0.5 # Warning threshold
138+
# CHALLENGER_BALANCE_CRITICAL_ETH=0.1 # Critical threshold (triggers auto-refill)
139+
118140
# === Display (Optional) ===
119141
# NEXT_PUBLIC_NETWORK_NAME=Thanos Sepolia # Network name shown in dashboard header
120142

src/chains/thanos/components.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
// Component Names
1414
// ============================================================
1515

16-
export const OP_COMPONENTS = ['op-geth', 'op-node', 'op-batcher', 'op-proposer'] as const;
16+
export const OP_COMPONENTS = ['op-geth', 'op-node', 'op-batcher', 'op-proposer', 'op-challenger'] as const;
1717
export type OptimismComponent = (typeof OP_COMPONENTS)[number];
1818

1919
export const META_COMPONENTS = ['l1', 'system'] as const;
@@ -29,7 +29,7 @@ export const DEPENDENCY_GRAPH: Record<string, ComponentDependency> = {
2929
},
3030
'op-node': {
3131
dependsOn: ['l1'],
32-
feeds: ['op-geth', 'op-batcher', 'op-proposer'],
32+
feeds: ['op-geth', 'op-batcher', 'op-proposer', 'op-challenger'],
3333
},
3434
'op-batcher': {
3535
dependsOn: ['op-node', 'l1'],
@@ -39,13 +39,17 @@ export const DEPENDENCY_GRAPH: Record<string, ComponentDependency> = {
3939
dependsOn: ['op-node', 'l1'],
4040
feeds: [],
4141
},
42+
'op-challenger': {
43+
dependsOn: ['op-node', 'l1'],
44+
feeds: [],
45+
},
4246
'l1': {
4347
dependsOn: [],
44-
feeds: ['op-node', 'op-batcher', 'op-proposer'],
48+
feeds: ['op-node', 'op-batcher', 'op-proposer', 'op-challenger'],
4549
},
4650
'system': {
4751
dependsOn: [],
48-
feeds: ['op-geth', 'op-node', 'op-batcher', 'op-proposer'],
52+
feeds: ['op-geth', 'op-node', 'op-batcher', 'op-proposer', 'op-challenger'],
4953
},
5054
};
5155

@@ -62,6 +66,8 @@ export const COMPONENT_ALIASES: Record<string, string> = {
6266
'batcher': 'op-batcher',
6367
'op-proposer': 'op-proposer',
6468
'proposer': 'op-proposer',
69+
'op-challenger': 'op-challenger',
70+
'challenger': 'op-challenger',
6571
'l1': 'l1',
6672
'system': 'system',
6773
};
@@ -98,6 +104,13 @@ export const K8S_COMPONENTS: K8sComponentConfig[] = [
98104
l1RpcEnvVar: 'OP_PROPOSER_L1_ETH_RPC',
99105
isPrimaryExecution: false,
100106
},
107+
{
108+
component: 'op-challenger',
109+
labelSuffix: 'challenger',
110+
statefulSetSuffix: 'op-challenger',
111+
l1RpcEnvVar: 'OP_CHALLENGER_L1_ETH_RPC',
112+
isPrimaryExecution: false,
113+
},
101114
];
102115

103116
// ============================================================
@@ -115,7 +128,12 @@ export const EOA_CONFIGS: EOAConfig[] = [
115128
addressEnvVar: 'PROPOSER_EOA_ADDRESS',
116129
displayName: 'Proposer',
117130
},
131+
{
132+
role: 'challenger',
133+
addressEnvVar: 'CHALLENGER_EOA_ADDRESS',
134+
displayName: 'Challenger',
135+
},
118136
];
119137

120138
/** Balance metrics for anomaly detection */
121-
export const BALANCE_METRICS = ['batcherBalance', 'proposerBalance'];
139+
export const BALANCE_METRICS = ['batcherBalance', 'proposerBalance', 'challengerBalance'];

src/chains/thanos/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ export class ThanosPlugin implements ChainPlugin {
7777
if (metric.includes('proposer') || metric === 'proposerBalance') {
7878
return 'op-proposer';
7979
}
80+
if (metric.includes('challenger') || metric === 'challengerBalance') {
81+
return 'op-challenger';
82+
}
8083
return 'system';
8184
}
8285

src/chains/thanos/playbooks.ts

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,177 @@ export const THANOS_PLAYBOOKS: Playbook[] = [
222222
],
223223
maxAttempts: 0, // Immediate escalation
224224
},
225+
226+
// Playbook 8: Challenger EOA Balance Low (Phase 1)
227+
{
228+
name: 'challenger-balance-low',
229+
description: 'Challenger EOA balance below warning threshold',
230+
trigger: {
231+
component: 'op-challenger',
232+
indicators: [
233+
{ type: 'metric', condition: 'challengerBalance < warning' },
234+
],
235+
},
236+
actions: [
237+
{
238+
type: 'escalate_operator',
239+
safetyLevel: 'safe',
240+
params: { urgency: 'medium', message: 'Challenger EOA balance low. Refill recommended.' },
241+
},
242+
],
243+
maxAttempts: 0, // Alert only
244+
},
245+
246+
// Playbook 9: Challenger EOA Balance Critical (Phase 1)
247+
{
248+
name: 'challenger-balance-critical',
249+
description: 'Challenger EOA balance critically low — auto-refill for dispute game participation',
250+
trigger: {
251+
component: 'op-challenger',
252+
indicators: [
253+
{ type: 'metric', condition: 'challengerBalance < critical' },
254+
],
255+
},
256+
actions: [
257+
{
258+
type: 'check_treasury_balance',
259+
safetyLevel: 'safe',
260+
},
261+
{
262+
type: 'check_l1_gas_price',
263+
safetyLevel: 'safe',
264+
},
265+
{
266+
type: 'refill_eoa',
267+
safetyLevel: 'guarded',
268+
params: { role: 'challenger', amount: '1.0' },
269+
waitAfterMs: 30000,
270+
},
271+
{
272+
type: 'verify_balance_restored',
273+
safetyLevel: 'safe',
274+
params: { role: 'challenger' },
275+
},
276+
],
277+
fallback: [
278+
{
279+
type: 'escalate_operator',
280+
safetyLevel: 'safe',
281+
params: { urgency: 'critical', message: 'Challenger EOA refill failed. Cannot participate in dispute games — security risk!' },
282+
},
283+
],
284+
maxAttempts: 1,
285+
},
286+
287+
// Playbook 10: op-challenger Component Failure (Phase 1)
288+
{
289+
name: 'op-challenger-failure',
290+
description: 'op-challenger pod crash or proof generation failure',
291+
trigger: {
292+
component: 'op-challenger',
293+
indicators: [
294+
{ type: 'log_pattern', condition: 'proof generation failed|panic|fatal error' },
295+
{ type: 'metric', condition: 'pod restart count > 3' },
296+
],
297+
},
298+
actions: [
299+
{
300+
type: 'collect_logs',
301+
safetyLevel: 'safe',
302+
target: 'op-challenger',
303+
params: { lines: 500 },
304+
},
305+
{
306+
type: 'escalate_operator',
307+
safetyLevel: 'safe',
308+
params: { urgency: 'critical', message: 'op-challenger failure detected. Dispute resolution compromised.' },
309+
},
310+
],
311+
maxAttempts: 0, // Manual intervention required
312+
},
313+
314+
// Playbook 11: Dispute Game Deadline Approaching (Phase 2)
315+
{
316+
name: 'dispute-game-deadline-near',
317+
description: 'Dispute game deadline approaching — requires immediate action',
318+
trigger: {
319+
component: 'op-challenger',
320+
indicators: [
321+
{ type: 'metric', condition: 'gameDeadlineProximity < 1h' },
322+
],
323+
},
324+
actions: [
325+
{
326+
type: 'escalate_operator',
327+
safetyLevel: 'safe',
328+
params: { urgency: 'critical', message: 'Dispute game deadline < 1 hour. Immediate review required.' },
329+
},
330+
{
331+
type: 'collect_logs',
332+
safetyLevel: 'safe',
333+
target: 'op-challenger',
334+
params: { lines: 200 },
335+
},
336+
],
337+
maxAttempts: 0, // Alert only
338+
},
339+
340+
// Playbook 12: Unclaimed Bond Alert (Phase 2)
341+
{
342+
name: 'unclaimed-bond-alert',
343+
description: 'Bond from resolved game not claimed after 24h',
344+
trigger: {
345+
component: 'op-challenger',
346+
indicators: [
347+
{ type: 'metric', condition: 'unclaimedBonds > 0 && unclaimedAge > 24h' },
348+
],
349+
},
350+
actions: [
351+
{
352+
type: 'claim_bond',
353+
safetyLevel: 'guarded',
354+
params: { auto: true },
355+
},
356+
{
357+
type: 'escalate_operator',
358+
safetyLevel: 'safe',
359+
params: { urgency: 'medium', message: 'Auto-claiming unclaimed bonds from resolved games.' },
360+
},
361+
],
362+
fallback: [
363+
{
364+
type: 'escalate_operator',
365+
safetyLevel: 'safe',
366+
params: { urgency: 'high', message: 'Bond claim failed. Manual intervention required.' },
367+
},
368+
],
369+
maxAttempts: 2,
370+
},
371+
372+
// Playbook 13: Proof Generation Timeout (Phase 2)
373+
{
374+
name: 'proof-generation-timeout',
375+
description: 'Fault proof generation taking too long or stalled',
376+
trigger: {
377+
component: 'op-challenger',
378+
indicators: [
379+
{ type: 'metric', condition: 'proofGenerationLatency > 300s' },
380+
{ type: 'log_pattern', condition: 'proof generation timeout|MIPS execution stalled' },
381+
],
382+
},
383+
actions: [
384+
{
385+
type: 'collect_logs',
386+
safetyLevel: 'safe',
387+
target: 'op-challenger',
388+
params: { lines: 500 },
389+
},
390+
{
391+
type: 'escalate_operator',
392+
safetyLevel: 'safe',
393+
params: { urgency: 'high', message: 'Proof generation timeout. Check op-program logs and game deadline.' },
394+
},
395+
],
396+
maxAttempts: 0, // Requires manual investigation
397+
},
225398
];

src/chains/thanos/prompts.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,18 @@ const RCA_SYSTEM_PROMPT = `You are performing Root Cause Analysis (RCA) for a Th
3939
- Depends on op-node for state data and L1 for submission
4040
- If proposer fails: withdrawals delayed, but L2 continues operating
4141
42+
6. **op-challenger (Fault Proof / Dispute Game)**
43+
- Monitors state root proposals on L1
44+
- Participates in dispute games to challenge invalid proposals
45+
- Generates fault proofs via MIPS execution (op-program)
46+
- Depends on op-node for L2 state verification and L1 for game participation
47+
- If challenger fails: SECURITY RISK — invalid proposals may be accepted
48+
4249
== Component Dependency Graph ==
4350
L1 -> op-node -> op-geth
4451
-> op-batcher -> L1
4552
-> op-proposer -> L1
53+
-> op-challenger -> L1
4654
4755
== Common Thanos Failure Patterns ==
4856
@@ -51,6 +59,9 @@ L1 -> op-node -> op-geth
5159
3. **op-geth Crash / OOM**: CPU/Memory anomalies, connection refused errors
5260
4. **Batcher Backlog**: txpool monotonically increasing, no batch submissions
5361
5. **Network Partition / P2P Issues**: Peer disconnections, gossip failures
62+
6. **Challenger EOA Low Balance**: Cannot participate in dispute games, bond deposit fails — SECURITY CRITICAL
63+
7. **Proof Generation Timeout**: op-program MIPS execution stalls, game deadline missed
64+
8. **Dispute Game Deadline Missed**: Invalid proposal accepted, withdrawal security compromised
5465
5566
== Your Task ==
5667

0 commit comments

Comments
 (0)