@@ -618,19 +618,61 @@ pub struct LoadedProgramsForTxBatch {
618
618
entries : HashMap < Pubkey , Arc < LoadedProgram > > ,
619
619
slot : Slot ,
620
620
pub environments : ProgramRuntimeEnvironments ,
621
+ /// Anticipated replacement for `environments` at the next epoch.
622
+ ///
623
+ /// This is `None` during most of an epoch, and only `Some` around the boundaries (at the end and beginning of an epoch).
624
+ /// More precisely, it starts with the recompilation phase a few hundred slots before the epoch boundary,
625
+ /// and it ends with the first rerooting after the epoch boundary.
626
+ /// Needed when a program is deployed at the last slot of an epoch, becomes effective in the next epoch.
627
+ /// So needs to be compiled with the environment for the next epoch.
628
+ pub upcoming_environments : Option < ProgramRuntimeEnvironments > ,
629
+ /// The epoch of the last rerooting
630
+ pub latest_root_epoch : Epoch ,
621
631
pub hit_max_limit : bool ,
622
632
}
623
633
624
634
impl LoadedProgramsForTxBatch {
625
- pub fn new ( slot : Slot , environments : ProgramRuntimeEnvironments ) -> Self {
635
+ pub fn new (
636
+ slot : Slot ,
637
+ environments : ProgramRuntimeEnvironments ,
638
+ upcoming_environments : Option < ProgramRuntimeEnvironments > ,
639
+ latest_root_epoch : Epoch ,
640
+ ) -> Self {
626
641
Self {
627
642
entries : HashMap :: new ( ) ,
628
643
slot,
629
644
environments,
645
+ upcoming_environments,
646
+ latest_root_epoch,
630
647
hit_max_limit : false ,
631
648
}
632
649
}
633
650
651
+ pub fn new_from_cache < FG : ForkGraph > (
652
+ slot : Slot ,
653
+ epoch : Epoch ,
654
+ cache : & ProgramCache < FG > ,
655
+ ) -> Self {
656
+ Self {
657
+ entries : HashMap :: new ( ) ,
658
+ slot,
659
+ environments : cache. get_environments_for_epoch ( epoch) . clone ( ) ,
660
+ upcoming_environments : cache. get_upcoming_environments_for_epoch ( epoch) ,
661
+ latest_root_epoch : cache. latest_root_epoch ,
662
+ hit_max_limit : false ,
663
+ }
664
+ }
665
+
666
+ /// Returns the current environments depending on the given epoch
667
+ pub fn get_environments_for_epoch ( & self , epoch : Epoch ) -> & ProgramRuntimeEnvironments {
668
+ if epoch != self . latest_root_epoch {
669
+ if let Some ( upcoming_environments) = self . upcoming_environments . as_ref ( ) {
670
+ return upcoming_environments;
671
+ }
672
+ }
673
+ & self . environments
674
+ }
675
+
634
676
/// Refill the cache with a single entry. It's typically called during transaction loading, and
635
677
/// transaction processing (for program management instructions).
636
678
/// It replaces the existing entry (if any) with the provided entry. The return value contains
@@ -710,6 +752,17 @@ impl<FG: ForkGraph> ProgramCache<FG> {
710
752
& self . environments
711
753
}
712
754
755
+ /// Returns the upcoming environments depending on the given epoch
756
+ pub fn get_upcoming_environments_for_epoch (
757
+ & self ,
758
+ epoch : Epoch ,
759
+ ) -> Option < ProgramRuntimeEnvironments > {
760
+ if epoch == self . latest_root_epoch {
761
+ return self . upcoming_environments . clone ( ) ;
762
+ }
763
+ None
764
+ }
765
+
713
766
/// Insert a single entry. It's typically called during transaction loading,
714
767
/// when the cache doesn't contain the entry corresponding to program `key`.
715
768
pub fn assign_program ( & mut self , key : Pubkey , entry : Arc < LoadedProgram > ) -> bool {
@@ -2057,7 +2110,7 @@ mod tests {
2057
2110
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 3 ) ) ,
2058
2111
( program4, ( LoadedProgramMatchCriteria :: NoCriteria , 4 ) ) ,
2059
2112
] ;
2060
- let mut extracted = LoadedProgramsForTxBatch :: new ( 22 , cache. environments . clone ( ) ) ;
2113
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 22 , cache. environments . clone ( ) , None , 0 ) ;
2061
2114
cache. extract ( & mut missing, & mut extracted, true ) ;
2062
2115
2063
2116
assert ! ( match_slot( & extracted, & program1, 20 , 22 ) ) ;
@@ -2073,7 +2126,7 @@ mod tests {
2073
2126
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2074
2127
( program4, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2075
2128
] ;
2076
- let mut extracted = LoadedProgramsForTxBatch :: new ( 15 , cache. environments . clone ( ) ) ;
2129
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 15 , cache. environments . clone ( ) , None , 0 ) ;
2077
2130
cache. extract ( & mut missing, & mut extracted, true ) ;
2078
2131
2079
2132
assert ! ( match_slot( & extracted, & program1, 0 , 15 ) ) ;
@@ -2096,7 +2149,7 @@ mod tests {
2096
2149
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2097
2150
( program4, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2098
2151
] ;
2099
- let mut extracted = LoadedProgramsForTxBatch :: new ( 18 , cache. environments . clone ( ) ) ;
2152
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 18 , cache. environments . clone ( ) , None , 0 ) ;
2100
2153
cache. extract ( & mut missing, & mut extracted, true ) ;
2101
2154
2102
2155
assert ! ( match_slot( & extracted, & program1, 0 , 18 ) ) ;
@@ -2114,7 +2167,7 @@ mod tests {
2114
2167
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2115
2168
( program4, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2116
2169
] ;
2117
- let mut extracted = LoadedProgramsForTxBatch :: new ( 23 , cache. environments . clone ( ) ) ;
2170
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 23 , cache. environments . clone ( ) , None , 0 ) ;
2118
2171
cache. extract ( & mut missing, & mut extracted, true ) ;
2119
2172
2120
2173
assert ! ( match_slot( & extracted, & program1, 0 , 23 ) ) ;
@@ -2132,7 +2185,7 @@ mod tests {
2132
2185
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2133
2186
( program4, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2134
2187
] ;
2135
- let mut extracted = LoadedProgramsForTxBatch :: new ( 11 , cache. environments . clone ( ) ) ;
2188
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 11 , cache. environments . clone ( ) , None , 0 ) ;
2136
2189
cache. extract ( & mut missing, & mut extracted, true ) ;
2137
2190
2138
2191
assert ! ( match_slot( & extracted, & program1, 0 , 11 ) ) ;
@@ -2170,7 +2223,7 @@ mod tests {
2170
2223
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2171
2224
( program4, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2172
2225
] ;
2173
- let mut extracted = LoadedProgramsForTxBatch :: new ( 21 , cache. environments . clone ( ) ) ;
2226
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 21 , cache. environments . clone ( ) , None , 0 ) ;
2174
2227
cache. extract ( & mut missing, & mut extracted, true ) ;
2175
2228
2176
2229
// Since the fork was pruned, we should not find the entry deployed at slot 20.
@@ -2187,7 +2240,7 @@ mod tests {
2187
2240
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2188
2241
( program4, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2189
2242
] ;
2190
- let mut extracted = LoadedProgramsForTxBatch :: new ( 27 , cache. environments . clone ( ) ) ;
2243
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 27 , cache. environments . clone ( ) , None , 0 ) ;
2191
2244
cache. extract ( & mut missing, & mut extracted, true ) ;
2192
2245
2193
2246
assert ! ( match_slot( & extracted, & program1, 0 , 27 ) ) ;
@@ -2219,7 +2272,7 @@ mod tests {
2219
2272
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2220
2273
( program4, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2221
2274
] ;
2222
- let mut extracted = LoadedProgramsForTxBatch :: new ( 23 , cache. environments . clone ( ) ) ;
2275
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 23 , cache. environments . clone ( ) , None , 0 ) ;
2223
2276
cache. extract ( & mut missing, & mut extracted, true ) ;
2224
2277
2225
2278
assert ! ( match_slot( & extracted, & program1, 0 , 23 ) ) ;
@@ -2274,7 +2327,7 @@ mod tests {
2274
2327
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2275
2328
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2276
2329
] ;
2277
- let mut extracted = LoadedProgramsForTxBatch :: new ( 12 , cache. environments . clone ( ) ) ;
2330
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 12 , cache. environments . clone ( ) , None , 0 ) ;
2278
2331
cache. extract ( & mut missing, & mut extracted, true ) ;
2279
2332
2280
2333
assert ! ( match_slot( & extracted, & program1, 0 , 12 ) ) ;
@@ -2294,7 +2347,7 @@ mod tests {
2294
2347
) ,
2295
2348
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2296
2349
] ;
2297
- let mut extracted = LoadedProgramsForTxBatch :: new ( 12 , cache. environments . clone ( ) ) ;
2350
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 12 , cache. environments . clone ( ) , None , 0 ) ;
2298
2351
cache. extract ( & mut missing, & mut extracted, true ) ;
2299
2352
2300
2353
assert ! ( match_slot( & extracted, & program2, 11 , 12 ) ) ;
@@ -2360,7 +2413,7 @@ mod tests {
2360
2413
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2361
2414
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2362
2415
] ;
2363
- let mut extracted = LoadedProgramsForTxBatch :: new ( 19 , cache. environments . clone ( ) ) ;
2416
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 19 , cache. environments . clone ( ) , None , 0 ) ;
2364
2417
cache. extract ( & mut missing, & mut extracted, true ) ;
2365
2418
2366
2419
assert ! ( match_slot( & extracted, & program1, 0 , 19 ) ) ;
@@ -2374,7 +2427,7 @@ mod tests {
2374
2427
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2375
2428
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2376
2429
] ;
2377
- let mut extracted = LoadedProgramsForTxBatch :: new ( 27 , cache. environments . clone ( ) ) ;
2430
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 27 , cache. environments . clone ( ) , None , 0 ) ;
2378
2431
cache. extract ( & mut missing, & mut extracted, true ) ;
2379
2432
2380
2433
assert ! ( match_slot( & extracted, & program1, 0 , 27 ) ) ;
@@ -2388,7 +2441,7 @@ mod tests {
2388
2441
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2389
2442
( program3, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2390
2443
] ;
2391
- let mut extracted = LoadedProgramsForTxBatch :: new ( 22 , cache. environments . clone ( ) ) ;
2444
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 22 , cache. environments . clone ( ) , None , 0 ) ;
2392
2445
cache. extract ( & mut missing, & mut extracted, true ) ;
2393
2446
2394
2447
assert ! ( match_slot( & extracted, & program1, 20 , 22 ) ) ;
@@ -2469,7 +2522,7 @@ mod tests {
2469
2522
cache. prune ( 10 , 0 ) ;
2470
2523
2471
2524
let mut missing = vec ! [ ( program1, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ] ;
2472
- let mut extracted = LoadedProgramsForTxBatch :: new ( 20 , cache. environments . clone ( ) ) ;
2525
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 20 , cache. environments . clone ( ) , None , 0 ) ;
2473
2526
cache. extract ( & mut missing, & mut extracted, true ) ;
2474
2527
2475
2528
// The cache should have the program deployed at slot 0
@@ -2513,7 +2566,7 @@ mod tests {
2513
2566
( program1, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2514
2567
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2515
2568
] ;
2516
- let mut extracted = LoadedProgramsForTxBatch :: new ( 20 , cache. environments . clone ( ) ) ;
2569
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 20 , cache. environments . clone ( ) , None , 0 ) ;
2517
2570
cache. extract ( & mut missing, & mut extracted, true ) ;
2518
2571
2519
2572
assert ! ( match_slot( & extracted, & program1, 0 , 20 ) ) ;
@@ -2523,7 +2576,7 @@ mod tests {
2523
2576
( program1, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2524
2577
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2525
2578
] ;
2526
- let mut extracted = LoadedProgramsForTxBatch :: new ( 6 , cache. environments . clone ( ) ) ;
2579
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 6 , cache. environments . clone ( ) , None , 0 ) ;
2527
2580
cache. extract ( & mut missing, & mut extracted, true ) ;
2528
2581
2529
2582
assert ! ( match_slot( & extracted, & program1, 5 , 6 ) ) ;
@@ -2537,7 +2590,7 @@ mod tests {
2537
2590
( program1, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2538
2591
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2539
2592
] ;
2540
- let mut extracted = LoadedProgramsForTxBatch :: new ( 20 , cache. environments . clone ( ) ) ;
2593
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 20 , cache. environments . clone ( ) , None , 0 ) ;
2541
2594
cache. extract ( & mut missing, & mut extracted, true ) ;
2542
2595
2543
2596
assert ! ( match_slot( & extracted, & program1, 0 , 20 ) ) ;
@@ -2547,7 +2600,7 @@ mod tests {
2547
2600
( program1, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2548
2601
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2549
2602
] ;
2550
- let mut extracted = LoadedProgramsForTxBatch :: new ( 6 , cache. environments . clone ( ) ) ;
2603
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 6 , cache. environments . clone ( ) , None , 0 ) ;
2551
2604
cache. extract ( & mut missing, & mut extracted, true ) ;
2552
2605
2553
2606
assert ! ( match_slot( & extracted, & program1, 0 , 6 ) ) ;
@@ -2561,7 +2614,7 @@ mod tests {
2561
2614
( program1, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2562
2615
( program2, ( LoadedProgramMatchCriteria :: NoCriteria , 1 ) ) ,
2563
2616
] ;
2564
- let mut extracted = LoadedProgramsForTxBatch :: new ( 20 , cache. environments . clone ( ) ) ;
2617
+ let mut extracted = LoadedProgramsForTxBatch :: new ( 20 , cache. environments . clone ( ) , None , 0 ) ;
2565
2618
cache. extract ( & mut missing, & mut extracted, true ) ;
2566
2619
2567
2620
assert ! ( match_slot( & extracted, & program1, 0 , 20 ) ) ;
0 commit comments