@@ -1329,11 +1329,13 @@ impl Backend {
1329
1329
env. evm_env . block_env . basefee = current_base_fee;
1330
1330
env. evm_env . block_env . blob_excess_gas_and_price = current_excess_blob_gas_and_price;
1331
1331
1332
- // pick a random value for prevrandao
1333
- env. evm_env . block_env . prevrandao = Some ( B256 :: random ( ) ) ;
1334
-
1335
1332
let best_hash = self . blockchain . storage . read ( ) . best_hash ;
1336
1333
1334
+ let mut input = Vec :: with_capacity ( 40 ) ;
1335
+ input. extend_from_slice ( best_hash. as_slice ( ) ) ;
1336
+ input. extend_from_slice ( & block_number. to_le_bytes ( ) ) ;
1337
+ env. evm_env . block_env . prevrandao = Some ( keccak256 ( & input) ) ;
1338
+
1337
1339
if self . prune_state_history_config . is_state_history_supported ( ) {
1338
1340
let db = self . db . read ( ) . await . current_state ( ) ;
1339
1341
// store current state before executing all transactions
@@ -3659,3 +3661,62 @@ pub fn op_haltreason_to_instruction_result(op_reason: OpHaltReason) -> Instructi
3659
3661
OpHaltReason :: FailedDeposit => InstructionResult :: Stop ,
3660
3662
}
3661
3663
}
3664
+
3665
+ #[ cfg( test) ]
3666
+ mod tests {
3667
+ use crate :: { NodeConfig , spawn} ;
3668
+
3669
+ #[ tokio:: test]
3670
+ async fn test_deterministic_block_mining ( ) {
3671
+ // Test that mine_block produces deterministic block hashes with same initial conditions
3672
+ let genesis_timestamp = 1743944919u64 ;
3673
+
3674
+ // Create two identical backends
3675
+ let config_a = NodeConfig :: test ( ) . with_genesis_timestamp ( genesis_timestamp. into ( ) ) ;
3676
+ let config_b = NodeConfig :: test ( ) . with_genesis_timestamp ( genesis_timestamp. into ( ) ) ;
3677
+
3678
+ let ( api_a, _handle_a) = spawn ( config_a) . await ;
3679
+ let ( api_b, _handle_b) = spawn ( config_b) . await ;
3680
+
3681
+ // Mine empty blocks (no transactions) on both backends
3682
+ let outcome_a_1 = api_a. backend . mine_block ( vec ! [ ] ) . await ;
3683
+ let outcome_b_1 = api_b. backend . mine_block ( vec ! [ ] ) . await ;
3684
+
3685
+ // Both should mine the same block number
3686
+ assert_eq ! ( outcome_a_1. block_number, outcome_b_1. block_number) ;
3687
+
3688
+ // Get the actual blocks to compare hashes
3689
+ let block_a_1 =
3690
+ api_a. block_by_number ( outcome_a_1. block_number . into ( ) ) . await . unwrap ( ) . unwrap ( ) ;
3691
+ let block_b_1 =
3692
+ api_b. block_by_number ( outcome_b_1. block_number . into ( ) ) . await . unwrap ( ) . unwrap ( ) ;
3693
+
3694
+ // The block hashes should be identical
3695
+ assert_eq ! (
3696
+ block_a_1. header. hash, block_b_1. header. hash,
3697
+ "Block hashes should be deterministic. Got {} vs {}" ,
3698
+ block_a_1. header. hash, block_b_1. header. hash
3699
+ ) ;
3700
+
3701
+ // Mine another block to ensure it remains deterministic
3702
+ let outcome_a_2 = api_a. backend . mine_block ( vec ! [ ] ) . await ;
3703
+ let outcome_b_2 = api_b. backend . mine_block ( vec ! [ ] ) . await ;
3704
+
3705
+ let block_a_2 =
3706
+ api_a. block_by_number ( outcome_a_2. block_number . into ( ) ) . await . unwrap ( ) . unwrap ( ) ;
3707
+ let block_b_2 =
3708
+ api_b. block_by_number ( outcome_b_2. block_number . into ( ) ) . await . unwrap ( ) . unwrap ( ) ;
3709
+
3710
+ assert_eq ! (
3711
+ block_a_2. header. hash, block_b_2. header. hash,
3712
+ "Second block hashes should also be deterministic. Got {} vs {}" ,
3713
+ block_a_2. header. hash, block_b_2. header. hash
3714
+ ) ;
3715
+
3716
+ // Ensure the blocks are different (sanity check)
3717
+ assert_ne ! (
3718
+ block_a_1. header. hash, block_a_2. header. hash,
3719
+ "Different blocks should have different hashes"
3720
+ ) ;
3721
+ }
3722
+ }
0 commit comments