@@ -10,16 +10,15 @@ use {
1010 hash:: Hash ,
1111 pubkey:: Pubkey ,
1212 rent:: Rent ,
13- slot_hashes:: SlotHashes ,
14- stake_history:: StakeHistory ,
13+ slot_hashes:: { self , SlotHashes } ,
14+ stake_history:: { StakeHistory , StakeHistoryEntry } ,
1515 sysvar:: { self , last_restart_slot:: LastRestartSlot , Sysvar , SysvarId } ,
1616 } ,
1717} ;
1818
1919// Agave's sysvar cache is difficult to work with, so Mollusk offers a wrapper
2020// around it for modifying its contents.
2121/// Mollusk sysvars.
22- #[ derive( Default ) ]
2322pub struct Sysvars {
2423 pub clock : Clock ,
2524 pub epoch_rewards : EpochRewards ,
@@ -30,6 +29,35 @@ pub struct Sysvars {
3029 pub stake_history : StakeHistory ,
3130}
3231
32+ impl Default for Sysvars {
33+ fn default ( ) -> Self {
34+ let clock = Clock :: default ( ) ;
35+ let epoch_rewards = EpochRewards :: default ( ) ;
36+ let epoch_schedule = EpochSchedule :: default ( ) ;
37+ let last_restart_slot = LastRestartSlot :: default ( ) ;
38+ let rent = Rent :: default ( ) ;
39+
40+ let slot_hashes = {
41+ let mut default_slot_hashes = vec ! [ ( 0 , Hash :: default ( ) ) ; slot_hashes:: MAX_ENTRIES ] ;
42+ default_slot_hashes[ 0 ] = ( clock. slot , Hash :: default ( ) ) ;
43+ SlotHashes :: new ( & default_slot_hashes)
44+ } ;
45+
46+ let mut stake_history = StakeHistory :: default ( ) ;
47+ stake_history. add ( clock. slot , StakeHistoryEntry :: default ( ) ) ;
48+
49+ Self {
50+ clock,
51+ epoch_rewards,
52+ epoch_schedule,
53+ last_restart_slot,
54+ rent,
55+ slot_hashes,
56+ stake_history,
57+ }
58+ }
59+ }
60+
3361impl Sysvars {
3462 fn sysvar_account < T : SysvarId + Sysvar > ( & self , sysvar : & T ) -> ( Pubkey , AccountSharedData ) {
3563 let data = bincode:: serialize :: < T > ( sysvar) . unwrap ( ) ;
@@ -88,15 +116,18 @@ impl Sysvars {
88116 } ;
89117
90118 // Then update `SlotHashes`.
91- let mut i = 0 ;
92- if let Some ( most_recent_slot_hash) = self . slot_hashes . first ( ) {
93- i = most_recent_slot_hash. 0 ;
94- }
95- let mut new_slot_hashes = vec ! [ ] ;
96- for slot in i..slot + 1 {
97- new_slot_hashes. push ( ( slot, Hash :: default ( ) ) ) ;
119+ let i = if let Some ( most_recent_slot_hash) = self . slot_hashes . first ( ) {
120+ most_recent_slot_hash. 0
121+ } else {
122+ // By default, this zero is never used, but a user can overwrite
123+ // `SlotHashes`.
124+ 0
125+ } ;
126+ // Don't include the target slot, since it will become the "current"
127+ // slot.
128+ for slot in i..slot {
129+ self . slot_hashes . add ( slot, Hash :: default ( ) ) ;
98130 }
99- self . slot_hashes = SlotHashes :: new ( & new_slot_hashes) ;
100131 }
101132}
102133
@@ -137,16 +168,30 @@ mod tests {
137168 #[ test]
138169 fn test_warp_to_slot ( ) {
139170 let mut sysvars = Sysvars :: default ( ) ;
140- assert_eq ! ( sysvars. clock. slot, 0 ) ;
141171
142- sysvars. warp_to_slot ( 200 ) ;
143- assert_eq ! ( sysvars. clock. slot, 200 ) ;
172+ let slot = 0 ;
173+ assert_eq ! ( sysvars. clock. slot, slot) ;
174+ assert_eq ! ( sysvars. clock. epoch, sysvars. epoch_schedule. get_epoch( slot) ) ;
175+ assert_eq ! (
176+ sysvars. slot_hashes. as_slice( ) ,
177+ & [ ( slot, Hash :: default ( ) ) ; slot_hashes:: MAX_ENTRIES ]
178+ ) ;
179+ assert_eq ! ( sysvars. slot_hashes. len( ) , slot_hashes:: MAX_ENTRIES ) ;
144180
145- sysvars. warp_to_slot ( 4_000 ) ;
146- assert_eq ! ( sysvars. clock. slot, 4_000 ) ;
181+ let mut warp_and_check = |slot : Slot | {
182+ sysvars. warp_to_slot ( slot) ;
183+ assert_eq ! ( sysvars. clock. slot, slot) ;
184+ assert_eq ! ( sysvars. clock. epoch, sysvars. epoch_schedule. get_epoch( slot) ) ;
185+ assert_eq ! (
186+ sysvars. slot_hashes. first( ) ,
187+ Some ( & ( slot - 1 , Hash :: default ( ) ) ) ,
188+ ) ;
189+ assert_eq ! ( sysvars. slot_hashes. len( ) , slot_hashes:: MAX_ENTRIES ) ;
190+ } ;
147191
148- sysvars. warp_to_slot ( 800_000 ) ;
149- assert_eq ! ( sysvars. clock. slot, 800_000 ) ;
192+ warp_and_check ( 200 ) ;
193+ warp_and_check ( 4_000 ) ;
194+ warp_and_check ( 800_000 ) ;
150195 }
151196
152197 #[ test]
0 commit comments