feat: presign for validator account (#6747)

#6746


  Add a --presign flag to emit the json output to stdout instead of publishing the exit
This commit is contained in:
Hamdi Allam
2025-04-24 01:38:05 -04:00
committed by GitHub
parent 1324d3d3c4
commit 6fad18644b
3 changed files with 34 additions and 3 deletions

1
Cargo.lock generated
View File

@@ -30,6 +30,7 @@ dependencies = [
"filesystem",
"safe_arith",
"sensitive_url",
"serde_json",
"slashing_protection",
"slot_clock",
"tempfile",

View File

@@ -22,6 +22,7 @@ eth2_wallet_manager = { path = "../common/eth2_wallet_manager" }
filesystem = { workspace = true }
safe_arith = { workspace = true }
sensitive_url = { workspace = true }
serde_json = { workspace = true }
slashing_protection = { workspace = true }
slot_clock = { workspace = true }
tokio = { workspace = true }

View File

@@ -11,6 +11,7 @@ use eth2_keystore::Keystore;
use eth2_network_config::Eth2NetworkConfig;
use safe_arith::SafeArith;
use sensitive_url::SensitiveUrl;
use serde_json;
use slot_clock::{SlotClock, SystemTimeSlotClock};
use std::path::{Path, PathBuf};
use std::time::Duration;
@@ -24,6 +25,7 @@ pub const BEACON_SERVER_FLAG: &str = "beacon-node";
pub const NO_WAIT: &str = "no-wait";
pub const NO_CONFIRMATION: &str = "no-confirmation";
pub const PASSWORD_PROMPT: &str = "Enter the keystore password";
pub const PRESIGN: &str = "presign";
pub const DEFAULT_BEACON_NODE: &str = "http://localhost:5052/";
pub const CONFIRMATION_PHRASE: &str = "Exit my validator";
@@ -74,6 +76,15 @@ pub fn cli_app() -> Command {
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
)
.arg(
Arg::new(PRESIGN)
.long(PRESIGN)
.help("Only presign the voluntary exit message without publishing it")
.default_value("false")
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.display_order(0)
)
}
pub fn cli_run<E: EthSpec>(matches: &ArgMatches, env: Environment<E>) -> Result<(), String> {
@@ -84,6 +95,7 @@ pub fn cli_run<E: EthSpec>(matches: &ArgMatches, env: Environment<E>) -> Result<
let stdin_inputs = cfg!(windows) || matches.get_flag(STDIN_INPUTS_FLAG);
let no_wait = matches.get_flag(NO_WAIT);
let no_confirmation = matches.get_flag(NO_CONFIRMATION);
let presign = matches.get_flag(PRESIGN);
let spec = env.eth2_config().spec.clone();
let server_url: String = clap_utils::parse_required(matches, BEACON_SERVER_FLAG)?;
@@ -107,6 +119,7 @@ pub fn cli_run<E: EthSpec>(matches: &ArgMatches, env: Environment<E>) -> Result<
&eth2_network_config,
no_wait,
no_confirmation,
presign,
))?;
Ok(())
@@ -123,6 +136,7 @@ async fn publish_voluntary_exit<E: EthSpec>(
eth2_network_config: &Eth2NetworkConfig,
no_wait: bool,
no_confirmation: bool,
presign: bool,
) -> Result<(), String> {
let genesis_data = get_geneisis_data(client).await?;
let testnet_genesis_root = eth2_network_config
@@ -154,6 +168,23 @@ async fn publish_voluntary_exit<E: EthSpec>(
validator_index,
};
// Sign the voluntary exit. We sign ahead of the prompt as that step is only important for the broadcast
let signed_voluntary_exit =
voluntary_exit.sign(&keypair.sk, genesis_data.genesis_validators_root, spec);
if presign {
eprintln!(
"Successfully pre-signed voluntary exit for validator {}. Not publishing.",
keypair.pk
);
// Convert to JSON and print
let string_output = serde_json::to_string_pretty(&signed_voluntary_exit)
.map_err(|e| format!("Unable to convert to JSON: {}", e))?;
println!("{}", string_output);
return Ok(());
}
eprintln!(
"Publishing a voluntary exit for validator: {} \n",
keypair.pk
@@ -174,9 +205,7 @@ async fn publish_voluntary_exit<E: EthSpec>(
};
if confirmation == CONFIRMATION_PHRASE {
// Sign and publish the voluntary exit to network
let signed_voluntary_exit =
voluntary_exit.sign(&keypair.sk, genesis_data.genesis_validators_root, spec);
// Publish the voluntary exit to network
client
.post_beacon_pool_voluntary_exits(&signed_voluntary_exit)
.await