@@ -41,6 +41,7 @@ use solana_sdk::{
41
41
genesis_config:: ClusterType ,
42
42
hash:: Hash ,
43
43
pubkey:: Pubkey ,
44
+ signature:: Signature ,
44
45
signature:: { Keypair , Signer } ,
45
46
timing:: timestamp,
46
47
transaction:: Transaction ,
@@ -63,6 +64,7 @@ pub const SUPERMINORITY_THRESHOLD: f64 = 1f64 / 3f64;
63
64
pub const MAX_UNCONFIRMED_SLOTS : usize = 5 ;
64
65
pub const DUPLICATE_LIVENESS_THRESHOLD : f64 = 0.1 ;
65
66
pub const DUPLICATE_THRESHOLD : f64 = 1.0 - SWITCH_FORK_THRESHOLD - DUPLICATE_LIVENESS_THRESHOLD ;
67
+ const MAX_VOTE_SIGNATURES : usize = 200 ;
66
68
67
69
#[ derive( PartialEq , Debug ) ]
68
70
pub ( crate ) enum HeaviestForkFailures {
@@ -111,6 +113,7 @@ pub struct ReplayStageConfig {
111
113
pub rewards_recorder_sender : Option < RewardsRecorderSender > ,
112
114
pub cache_block_time_sender : Option < CacheBlockTimeSender > ,
113
115
pub bank_notification_sender : Option < BankNotificationSender > ,
116
+ pub wait_for_vote_to_start_leader : bool ,
114
117
}
115
118
116
119
#[ derive( Default ) ]
@@ -282,6 +285,7 @@ impl ReplayStage {
282
285
rewards_recorder_sender,
283
286
cache_block_time_sender,
284
287
bank_notification_sender,
288
+ wait_for_vote_to_start_leader,
285
289
} = config;
286
290
287
291
trace ! ( "replay stage" ) ;
@@ -312,6 +316,8 @@ impl ReplayStage {
312
316
let mut skipped_slots_info = SkippedSlotsInfo :: default ( ) ;
313
317
let mut replay_timing = ReplayTiming :: default ( ) ;
314
318
let mut gossip_duplicate_confirmed_slots: GossipDuplicateConfirmedSlots = BTreeMap :: new ( ) ;
319
+ let mut voted_signatures = Vec :: new ( ) ;
320
+ let mut has_new_vote_been_rooted = !wait_for_vote_to_start_leader;
315
321
loop {
316
322
let allocated = thread_mem_usage:: Allocatedp :: default ( ) ;
317
323
@@ -523,6 +529,8 @@ impl ReplayStage {
523
529
& cache_block_time_sender,
524
530
& bank_notification_sender,
525
531
& mut gossip_duplicate_confirmed_slots,
532
+ & mut voted_signatures,
533
+ & mut has_new_vote_been_rooted,
526
534
) ;
527
535
} ;
528
536
voting_time. stop ( ) ;
@@ -614,6 +622,7 @@ impl ReplayStage {
614
622
& progress,
615
623
& retransmit_slots_sender,
616
624
& mut skipped_slots_info,
625
+ has_new_vote_been_rooted,
617
626
) ;
618
627
619
628
let poh_bank = poh_recorder. lock ( ) . unwrap ( ) . bank ( ) ;
@@ -1020,7 +1029,12 @@ impl ReplayStage {
1020
1029
progress_map : & ProgressMap ,
1021
1030
retransmit_slots_sender : & RetransmitSlotsSender ,
1022
1031
skipped_slots_info : & mut SkippedSlotsInfo ,
1032
+ has_new_vote_been_rooted : bool ,
1023
1033
) {
1034
+ if !has_new_vote_been_rooted {
1035
+ info ! ( "Haven't landed a vote, so skipping my leader slot" ) ;
1036
+ return ;
1037
+ }
1024
1038
// all the individual calls to poh_recorder.lock() are designed to
1025
1039
// increase granularity, decrease contention
1026
1040
@@ -1238,6 +1252,8 @@ impl ReplayStage {
1238
1252
cache_block_time_sender : & Option < CacheBlockTimeSender > ,
1239
1253
bank_notification_sender : & Option < BankNotificationSender > ,
1240
1254
gossip_duplicate_confirmed_slots : & mut GossipDuplicateConfirmedSlots ,
1255
+ vote_signatures : & mut Vec < Signature > ,
1256
+ has_new_vote_been_rooted : & mut bool ,
1241
1257
) {
1242
1258
if bank. is_empty ( ) {
1243
1259
inc_new_counter_info ! ( "replay_stage-voted_empty_bank" , 1 ) ;
@@ -1290,6 +1306,8 @@ impl ReplayStage {
1290
1306
highest_confirmed_root,
1291
1307
heaviest_subtree_fork_choice,
1292
1308
gossip_duplicate_confirmed_slots,
1309
+ has_new_vote_been_rooted,
1310
+ vote_signatures,
1293
1311
) ;
1294
1312
subscriptions. notify_roots ( rooted_slots) ;
1295
1313
if let Some ( sender) = bank_notification_sender {
@@ -1319,6 +1337,8 @@ impl ReplayStage {
1319
1337
last_vote,
1320
1338
& tower_slots,
1321
1339
switch_fork_decision,
1340
+ vote_signatures,
1341
+ * has_new_vote_been_rooted,
1322
1342
) ;
1323
1343
}
1324
1344
@@ -1330,6 +1350,8 @@ impl ReplayStage {
1330
1350
vote : Vote ,
1331
1351
tower : & [ Slot ] ,
1332
1352
switch_fork_decision : & SwitchForkDecision ,
1353
+ vote_signatures : & mut Vec < Signature > ,
1354
+ has_new_vote_been_rooted : bool ,
1333
1355
) {
1334
1356
if authorized_voter_keypairs. is_empty ( ) {
1335
1357
return ;
@@ -1399,6 +1421,14 @@ impl ReplayStage {
1399
1421
1400
1422
let mut vote_tx = Transaction :: new_with_payer ( & [ vote_ix] , Some ( & node_keypair. pubkey ( ) ) ) ;
1401
1423
1424
+ if !has_new_vote_been_rooted {
1425
+ vote_signatures. push ( vote_tx. signatures [ 0 ] ) ;
1426
+ if vote_signatures. len ( ) > MAX_VOTE_SIGNATURES {
1427
+ vote_signatures. remove ( 0 ) ;
1428
+ }
1429
+ } else {
1430
+ vote_signatures. clear ( ) ;
1431
+ }
1402
1432
let blockhash = bank. last_blockhash ( ) ;
1403
1433
vote_tx. partial_sign ( & [ node_keypair. as_ref ( ) ] , blockhash) ;
1404
1434
vote_tx. partial_sign ( & [ authorized_voter_keypair. as_ref ( ) ] , blockhash) ;
@@ -2125,13 +2155,27 @@ impl ReplayStage {
2125
2155
highest_confirmed_root : Option < Slot > ,
2126
2156
heaviest_subtree_fork_choice : & mut HeaviestSubtreeForkChoice ,
2127
2157
gossip_duplicate_confirmed_slots : & mut GossipDuplicateConfirmedSlots ,
2158
+ has_new_vote_been_rooted : & mut bool ,
2159
+ voted_signatures : & mut Vec < Signature > ,
2128
2160
) {
2129
2161
bank_forks. write ( ) . unwrap ( ) . set_root (
2130
2162
new_root,
2131
2163
accounts_background_request_sender,
2132
2164
highest_confirmed_root,
2133
2165
) ;
2134
2166
let r_bank_forks = bank_forks. read ( ) . unwrap ( ) ;
2167
+ let new_root_bank = & r_bank_forks[ new_root] ;
2168
+ if !* has_new_vote_been_rooted {
2169
+ for signature in voted_signatures. iter ( ) {
2170
+ if new_root_bank. get_signature_status ( signature) . is_some ( ) {
2171
+ * has_new_vote_been_rooted = true ;
2172
+ break ;
2173
+ }
2174
+ }
2175
+ if * has_new_vote_been_rooted {
2176
+ std:: mem:: take ( voted_signatures) ;
2177
+ }
2178
+ }
2135
2179
progress. handle_new_root ( & r_bank_forks) ;
2136
2180
heaviest_subtree_fork_choice. set_root ( new_root) ;
2137
2181
let mut slots_ge_root = gossip_duplicate_confirmed_slots. split_off ( & new_root) ;
@@ -2553,6 +2597,8 @@ pub(crate) mod tests {
2553
2597
None ,
2554
2598
& mut heaviest_subtree_fork_choice,
2555
2599
& mut gossip_duplicate_confirmed_slots,
2600
+ & mut true ,
2601
+ & mut Vec :: new ( ) ,
2556
2602
) ;
2557
2603
assert_eq ! ( bank_forks. read( ) . unwrap( ) . root( ) , root) ;
2558
2604
assert_eq ! ( progress. len( ) , 1 ) ;
@@ -2609,6 +2655,8 @@ pub(crate) mod tests {
2609
2655
Some ( confirmed_root) ,
2610
2656
& mut heaviest_subtree_fork_choice,
2611
2657
& mut BTreeMap :: new ( ) ,
2658
+ & mut true ,
2659
+ & mut Vec :: new ( ) ,
2612
2660
) ;
2613
2661
assert_eq ! ( bank_forks. read( ) . unwrap( ) . root( ) , root) ;
2614
2662
assert ! ( bank_forks. read( ) . unwrap( ) . get( confirmed_root) . is_some( ) ) ;
0 commit comments