Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion lcli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,10 +492,20 @@ fn main() {
.long("jwt-output-path")
.value_name("PATH")
.action(ArgAction::Set)
.required(true)
.required_unless_present("jwt-secret-path")
.conflicts_with("jwt-secret-path")
.help("Path to write the JWT secret.")
.display_order(0)
)
.arg(
Arg::new("jwt-secret-path")
.long("jwt-secret-path")
.value_name("PATH")
.action(ArgAction::Set)
.help("Path to an existing hex-encoded JWT secret file. \
When provided, this secret is used instead of the default.")
.display_order(0)
)
.arg(
Arg::new("listen-address")
.long("listen-address")
Expand Down
24 changes: 20 additions & 4 deletions lcli/src/mock_el.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use clap::ArgMatches;
use clap_utils::{parse_optional, parse_required};
use environment::Environment;
use execution_layer::{
auth::JwtKey,
auth::{JwtKey, strip_prefix},
test_utils::{
Config, DEFAULT_JWT_SECRET, DEFAULT_TERMINAL_BLOCK, MockExecutionConfig, MockServer,
},
Expand All @@ -13,7 +13,8 @@ use std::sync::Arc;
use types::*;

pub fn run<E: EthSpec>(mut env: Environment<E>, matches: &ArgMatches) -> Result<(), String> {
let jwt_path: PathBuf = parse_required(matches, "jwt-output-path")?;
let jwt_output_path: Option<PathBuf> = parse_optional(matches, "jwt-output-path")?;
let jwt_secret_path: Option<PathBuf> = parse_optional(matches, "jwt-secret-path")?;
let listen_addr: Ipv4Addr = parse_required(matches, "listen-address")?;
let listen_port: u16 = parse_required(matches, "listen-port")?;
let all_payloads_valid: bool = parse_required(matches, "all-payloads-valid")?;
Expand All @@ -25,8 +26,23 @@ pub fn run<E: EthSpec>(mut env: Environment<E>, matches: &ArgMatches) -> Result<

let handle = env.core_context().executor.handle().unwrap();
let spec = Arc::new(E::default_spec());
let jwt_key = JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap();
std::fs::write(jwt_path, hex::encode(DEFAULT_JWT_SECRET)).unwrap();

let jwt_key = if let Some(secret_path) = jwt_secret_path {
let hex_str = std::fs::read_to_string(&secret_path)
.map_err(|e| format!("Failed to read JWT secret file: {}", e))?;
let secret_bytes = hex::decode(strip_prefix(hex_str.trim()))
.map_err(|e| format!("Invalid hex in JWT secret file: {}", e))?;
JwtKey::from_slice(&secret_bytes)
.map_err(|e| format!("Invalid JWT secret length (expected 32 bytes): {}", e))?
} else if let Some(jwt_path) = jwt_output_path {
let jwt_key = JwtKey::from_slice(&DEFAULT_JWT_SECRET)
.map_err(|e| format!("Default JWT secret invalid: {}", e))?;
std::fs::write(jwt_path, hex::encode(jwt_key.as_bytes()))
.map_err(|e| format!("Failed to write JWT secret to output path: {}", e))?;
jwt_key
} else {
return Err("either --jwt-secret-path or --jwt-output-path must be provided".to_string());
};

let config = MockExecutionConfig {
server_config: Config {
Expand Down