@@ -162,33 +162,6 @@ impl MiningConfig {
162162 } . ensure_keys_available ( )
163163 }
164164
165- /// Ensures `validator_address` is populated by deriving it from the configured key material.
166- /// Returns an error if a key source is configured but cannot be decoded.
167- pub fn derive_validator_address_from_keys ( & mut self ) -> Result < ( ) , String > {
168- if self . validator_address . is_some ( ) {
169- return Ok ( ( ) ) ;
170- }
171-
172- if let Some ( ref pk_hex) = self . private_key_hex {
173- let signing_key = keystore:: load_private_key_from_hex ( pk_hex)
174- . map_err ( |err| format ! ( "Failed to load mining private key: {err}" ) ) ?;
175- self . validator_address = Some ( keystore:: get_validator_address ( & signing_key) ) ;
176- return Ok ( ( ) ) ;
177- }
178-
179- if let Some ( ref path) = self . keystore_path {
180- let password = self
181- . keystore_password
182- . as_deref ( )
183- . ok_or_else ( || "Keystore password must be provided when deriving validator address" . to_string ( ) ) ?;
184- let signing_key = keystore:: load_private_key_from_keystore ( path, password)
185- . map_err ( |err| format ! ( "Failed to decrypt keystore {}: {err}" , path. display( ) ) ) ?;
186- self . validator_address = Some ( keystore:: get_validator_address ( & signing_key) ) ;
187- }
188-
189- Ok ( ( ) )
190- }
191-
192165 /// Load configuration from environment variables
193166 pub fn from_env ( ) -> Self {
194167 let enabled = std:: env:: var ( "BSC_MINING_ENABLED" )
@@ -224,8 +197,17 @@ impl MiningConfig {
224197 ..Default :: default ( )
225198 } ;
226199
227- if let Err ( err) = cfg. derive_validator_address_from_keys ( ) {
228- tracing:: warn!( "Failed to derive validator address from configured keys: {err}" ) ;
200+ // If a private key is present but validator_address is not, derive it automatically.
201+ if cfg. validator_address . is_none ( ) {
202+ if let Some ( ref pk_hex) = cfg. private_key_hex {
203+ if let Ok ( sk) = keystore:: load_private_key_from_hex ( pk_hex) {
204+ cfg. validator_address = Some ( keystore:: get_validator_address ( & sk) ) ;
205+ }
206+ } else if let ( Some ( ref path) , Some ( ref pass) ) = ( & cfg. keystore_path , & cfg. keystore_password ) {
207+ if let Ok ( sk) = keystore:: load_private_key_from_keystore ( path, pass) {
208+ cfg. validator_address = Some ( keystore:: get_validator_address ( & sk) ) ;
209+ }
210+ }
229211 }
230212
231213 cfg. ensure_keys_available ( )
@@ -304,23 +286,6 @@ pub mod keystore {
304286#[ cfg( test) ]
305287mod tests {
306288 use super :: * ;
307- use std:: { fs, io:: Write , path:: PathBuf } ;
308- use uuid:: Uuid ;
309-
310- const SAMPLE_KEYSTORE_JSON : & str = r#"{"address":"bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf0","crypto":{"cipher":"aes-128-ctr","ciphertext":"f7505ced32fe3037d6dc25ae7e9716858e516bacfb0dc28c9995f01cf7fee84a","cipherparams":{"iv":"d93e5314f18ccfc8330e1ad37534fa29"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"1fb8f954f70fb0ddb8be5b1fb57d821df21dda700682f382baed311dde95a6c7"},"mac":"c501bb033f94cb9efc3c63fe1547555fc1412d3abb8b400cacda37bd9de888ec"},"id":"7246dc9c-d170-4009-8878-8628be169836","version":3}"# ;
311- const SAMPLE_KEYSTORE_PASSWORD : & str = "0123456789" ;
312- const SAMPLE_KEYSTORE_ADDRESS : & str = "0xbcdd0d2cda5f6423e57b6a4dcd75decbe31aecf0" ;
313-
314- fn write_sample_keystore ( ) -> PathBuf {
315- let mut path: PathBuf = std:: env:: temp_dir ( ) ;
316- let fname =
317- format ! ( "UTC--test-{}--bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf0" , Uuid :: new_v4( ) ) ;
318- path. push ( fname) ;
319- let mut file = fs:: File :: create ( & path) . unwrap ( ) ;
320- file. write_all ( SAMPLE_KEYSTORE_JSON . as_bytes ( ) ) . unwrap ( ) ;
321- file. sync_all ( ) . unwrap ( ) ;
322- path
323- }
324289
325290 #[ test]
326291 fn test_mining_config_validation ( ) {
@@ -349,39 +314,37 @@ mod tests {
349314
350315 #[ test]
351316 fn test_load_private_key_from_keystore_file ( ) {
317+ use std:: fs;
318+ use std:: io:: Write ;
319+ use std:: path:: PathBuf ;
320+ use uuid:: Uuid ;
321+
322+ // This is a real V3 keystore JSON (address bcdd0d2c...) with password "0123456789"
323+ let keystore_json = r#"{"address":"bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf0","crypto":{"cipher":"aes-128-ctr","ciphertext":"f7505ced32fe3037d6dc25ae7e9716858e516bacfb0dc28c9995f01cf7fee84a","cipherparams":{"iv":"d93e5314f18ccfc8330e1ad37534fa29"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"1fb8f954f70fb0ddb8be5b1fb57d821df21dda700682f382baed311dde95a6c7"},"mac":"c501bb033f94cb9efc3c63fe1547555fc1412d3abb8b400cacda37bd9de888ec"},"id":"7246dc9c-d170-4009-8878-8628be169836","version":3}"# ;
324+
352325 // Write to a temporary file
353- let path = write_sample_keystore ( ) ;
326+ let mut path: PathBuf = std:: env:: temp_dir ( ) ;
327+ let fname = format ! ( "UTC--test-{}--bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf0" , Uuid :: new_v4( ) ) ;
328+ path. push ( fname) ;
329+ {
330+ let mut f = fs:: File :: create ( & path) . unwrap ( ) ;
331+ f. write_all ( keystore_json. as_bytes ( ) ) . unwrap ( ) ;
332+ f. sync_all ( ) . unwrap ( ) ;
333+ }
354334
355335 // Decrypt with the known password
356- let signing_key =
357- keystore:: load_private_key_from_keystore ( & path, SAMPLE_KEYSTORE_PASSWORD ) . unwrap ( ) ;
336+ let signing_key = keystore:: load_private_key_from_keystore ( & path, "0123456789" ) . unwrap ( ) ;
358337 // convert signing_key to hex string
359338 let signing_key_hex = alloy_primitives:: hex:: encode ( signing_key. to_bytes ( ) ) ;
360339 println ! ( "signing_key: 0x{}" , signing_key_hex) ;
361340
362341 let address = keystore:: get_validator_address ( & signing_key) ;
363342
364343 // Expect derived address to match the keystore address
365- let expected: Address = SAMPLE_KEYSTORE_ADDRESS . parse ( ) . unwrap ( ) ;
344+ let expected: Address = "0xbcdd0d2cda5f6423e57b6a4dcd75decbe31aecf0" . parse ( ) . unwrap ( ) ;
366345 assert_eq ! ( address, expected) ;
367346
368347 // Cleanup best-effort
369348 let _ = fs:: remove_file ( & path) ;
370349 }
371-
372- #[ test]
373- fn derive_validator_address_from_keystore_config ( ) {
374- let path = write_sample_keystore ( ) ;
375- let mut cfg = MiningConfig {
376- enabled : true ,
377- validator_address : None ,
378- keystore_path : Some ( path. clone ( ) ) ,
379- keystore_password : Some ( SAMPLE_KEYSTORE_PASSWORD . to_string ( ) ) ,
380- ..Default :: default ( )
381- } ;
382-
383- cfg. derive_validator_address_from_keys ( ) . unwrap ( ) ;
384- assert_eq ! ( cfg. validator_address, Some ( SAMPLE_KEYSTORE_ADDRESS . parse( ) . unwrap( ) ) ) ;
385- let _ = fs:: remove_file ( path) ;
386- }
387350}
0 commit comments