Skip to content

Commit d5a3f59

Browse files
authored
Fix: slot hash warping (#24)
1 parent 78ff9dd commit d5a3f59

File tree

2 files changed

+64
-20
lines changed

2 files changed

+64
-20
lines changed

harness/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ use {
5252
hash::Hash,
5353
instruction::Instruction,
5454
pubkey::Pubkey,
55-
rent::Rent,
5655
transaction_context::{InstructionAccount, TransactionContext},
5756
},
5857
std::sync::Arc,
@@ -225,7 +224,7 @@ impl Mollusk {
225224

226225
let mut transaction_context = TransactionContext::new(
227226
transaction_accounts,
228-
Rent::default(),
227+
self.sysvars.rent.clone(),
229228
self.compute_budget.max_instruction_stack_depth,
230229
self.compute_budget.max_instruction_trace_length,
231230
);

harness/src/sysvar.rs

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
2322
pub 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+
3361
impl 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

Comments
 (0)