Skip to content

Commit e8bbd86

Browse files
committed
feat: persist core ChainState and reload WASM on restart
- Persist core ChainState (wasm_challenge_configs, routes) to storage - Load persisted core state on startup instead of starting fresh - Reload WASM modules from distributed storage on restart - Add BOOTSTRAP_END_BLOCK=7612000 for block-based bootstrap period - State saved every 60s alongside P2P state
1 parent 9a808ef commit e8bbd86

File tree

7 files changed

+656
-6
lines changed

7 files changed

+656
-6
lines changed

bins/platform-sudo/src/main.rs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,65 @@ enum Commands {
6262
#[arg(short, long)]
6363
name: String,
6464
},
65+
/// Set challenge weight/emission ratio on a mechanism
66+
SetEmission {
67+
/// Challenge ID (UUID)
68+
#[arg(short = 'c', long)]
69+
challenge_id: String,
70+
/// Mechanism ID (default: 0)
71+
#[arg(short, long, default_value = "0")]
72+
mechanism_id: u8,
73+
/// Weight ratio (0.0 - 1.0)
74+
#[arg(short, long)]
75+
weight: f64,
76+
},
77+
/// Set mechanism burn rate
78+
SetBurnRate {
79+
/// Mechanism ID
80+
#[arg(short, long, default_value = "0")]
81+
mechanism_id: u8,
82+
/// Burn rate (0.0 - 1.0), e.g., 0.1 = 10% to UID 0
83+
#[arg(short, long)]
84+
rate: f64,
85+
},
86+
/// Configure mechanism weight distribution
87+
SetMechanismConfig {
88+
/// Mechanism ID
89+
#[arg(short, long, default_value = "0")]
90+
mechanism_id: u8,
91+
/// Burn rate (0.0 - 1.0)
92+
#[arg(long, default_value = "0.0")]
93+
burn_rate: f64,
94+
/// Equal distribution among challenges
95+
#[arg(long)]
96+
equal_distribution: bool,
97+
/// Minimum weight threshold
98+
#[arg(long, default_value = "0.0001")]
99+
min_weight: f64,
100+
},
101+
/// Emergency pause the network
102+
Pause {
103+
/// Reason for the pause
104+
#[arg(short, long)]
105+
reason: String,
106+
},
107+
/// Resume the network after a pause
108+
Resume,
109+
/// Set required validator version
110+
SetVersion {
111+
/// Minimum required version (e.g., "0.2.0")
112+
#[arg(long)]
113+
min: String,
114+
/// Recommended version
115+
#[arg(long)]
116+
recommended: String,
117+
/// Whether the update is mandatory
118+
#[arg(long)]
119+
mandatory: bool,
120+
/// Deadline block (optional)
121+
#[arg(long)]
122+
deadline: Option<u64>,
123+
},
65124
/// List all challenges
66125
List,
67126
/// Show validator status
@@ -292,6 +351,42 @@ impl SudoCli {
292351
Ok(())
293352
}
294353

354+
async fn send_sudo_action(&self, action: serde_json::Value) -> Result<()> {
355+
let timestamp = chrono::Utc::now().timestamp_millis();
356+
357+
let msg_to_sign = format!("sudo:action:{}:{}", action.to_string(), timestamp);
358+
let signature = self.sign(msg_to_sign.as_bytes())?;
359+
360+
let request = serde_json::json!({
361+
"action": action,
362+
"signature": hex::encode(&signature),
363+
"timestamp": timestamp,
364+
});
365+
366+
let response = self
367+
.client
368+
.post(format!("{}/sudo/action", self.rpc_url))
369+
.json(&request)
370+
.send()
371+
.await
372+
.context("Failed to send sudo action")?;
373+
374+
if response.status().is_success() {
375+
let result: SudoResponse = response.json().await?;
376+
if result.success {
377+
info!("Sudo action applied: {}", result.message);
378+
} else {
379+
warn!("Sudo action failed: {}", result.message);
380+
}
381+
} else {
382+
let status = response.status();
383+
let text = response.text().await.unwrap_or_default();
384+
error!(status = %status, body = %text, "Sudo action request failed");
385+
}
386+
387+
Ok(())
388+
}
389+
295390
async fn list_challenges(&self) -> Result<()> {
296391
let response = self
297392
.client
@@ -443,6 +538,80 @@ async fn main() -> Result<()> {
443538
Some(Commands::Rename { id, name }) => {
444539
sudo_cli.rename_challenge(&id, &name).await?;
445540
}
541+
Some(Commands::SetEmission {
542+
challenge_id,
543+
mechanism_id,
544+
weight,
545+
}) => {
546+
let cid = ChallengeId::from_string(&challenge_id);
547+
let action = serde_json::json!({
548+
"SetChallengeWeight": {
549+
"challenge_id": cid.0.to_string(),
550+
"mechanism_id": mechanism_id,
551+
"weight_ratio": weight
552+
}
553+
});
554+
sudo_cli.send_sudo_action(action).await?;
555+
}
556+
Some(Commands::SetBurnRate { mechanism_id, rate }) => {
557+
let action = serde_json::json!({
558+
"SetMechanismBurnRate": {
559+
"mechanism_id": mechanism_id,
560+
"burn_rate": rate
561+
}
562+
});
563+
sudo_cli.send_sudo_action(action).await?;
564+
}
565+
Some(Commands::SetMechanismConfig {
566+
mechanism_id,
567+
burn_rate,
568+
equal_distribution,
569+
min_weight,
570+
}) => {
571+
let action = serde_json::json!({
572+
"SetMechanismConfig": {
573+
"mechanism_id": mechanism_id,
574+
"config": {
575+
"mechanism_id": mechanism_id,
576+
"base_burn_rate": burn_rate,
577+
"equal_distribution": equal_distribution,
578+
"min_weight_threshold": min_weight,
579+
"max_weight_cap": 1.0,
580+
"active": true
581+
}
582+
}
583+
});
584+
sudo_cli.send_sudo_action(action).await?;
585+
}
586+
Some(Commands::Pause { reason }) => {
587+
let action = serde_json::json!({
588+
"EmergencyPause": {
589+
"reason": reason
590+
}
591+
});
592+
sudo_cli.send_sudo_action(action).await?;
593+
}
594+
Some(Commands::Resume) => {
595+
let action = serde_json::json!("Resume");
596+
sudo_cli.send_sudo_action(action).await?;
597+
}
598+
Some(Commands::SetVersion {
599+
min,
600+
recommended,
601+
mandatory,
602+
deadline,
603+
}) => {
604+
let action = serde_json::json!({
605+
"SetRequiredVersion": {
606+
"min_version": min,
607+
"recommended_version": recommended,
608+
"mandatory": mandatory,
609+
"deadline_block": deadline,
610+
"release_notes": null
611+
}
612+
});
613+
sudo_cli.send_sudo_action(action).await?;
614+
}
446615
Some(Commands::List) => {
447616
sudo_cli.list_challenges().await?;
448617
}

0 commit comments

Comments
 (0)