anvil_zksync_core/node/inner/
time.rs1use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
2use zksync_error::anvil_zksync::{self, node::AnvilNodeResult};
3
4pub trait ReadTime: Send + Sync {
6 fn dyn_cloned(&self) -> Box<dyn ReadTime>;
8
9 fn current_timestamp(&self) -> u64;
11}
12
13impl Clone for Box<dyn ReadTime> {
14 fn clone(&self) -> Self {
15 self.dyn_cloned()
16 }
17}
18
19#[derive(Debug, Clone)]
20pub(super) struct Time {
21 internal: Arc<RwLock<TimeState>>,
22}
23
24impl ReadTime for Time {
25 fn dyn_cloned(&self) -> Box<dyn ReadTime> {
26 Box::new(self.clone())
27 }
28
29 fn current_timestamp(&self) -> u64 {
30 self.get().current_timestamp
31 }
32}
33
34impl Time {
35 pub(super) fn new(current_timestamp: u64) -> Self {
36 let internal = Arc::new(RwLock::new(TimeState {
37 current_timestamp,
38 next_timestamp: None,
39 interval: None,
40 }));
41
42 Self { internal }
43 }
44
45 fn get(&self) -> RwLockReadGuard<TimeState> {
46 self.internal
47 .read()
48 .expect("TimestampWriter lock is poisoned")
49 }
50
51 fn get_mut(&self) -> RwLockWriteGuard<TimeState> {
52 self.internal
53 .write()
54 .expect("TimestampWriter lock is poisoned")
55 }
56
57 pub(super) fn set_current_timestamp_unchecked(&self, timestamp: u64) -> i128 {
60 let mut this = self.get_mut();
61 let diff = (timestamp as i128).saturating_sub(this.current_timestamp as i128);
62 this.next_timestamp.take();
63 this.current_timestamp = timestamp;
64 diff
65 }
66
67 pub(super) fn enforce_next_timestamp(&self, timestamp: u64) -> AnvilNodeResult<()> {
72 let mut this = self.get_mut();
73 if timestamp <= this.current_timestamp {
74 Err(anvil_zksync::node::TimestampBackwardsError {
75 timestamp_requested: timestamp.into(),
76 timestamp_now: this.current_timestamp.into(),
77 })
78 } else {
79 this.next_timestamp.replace(timestamp);
80 Ok(())
81 }
82 }
83
84 pub(super) fn increase_time(&self, seconds: u64) -> u64 {
86 let mut this = self.get_mut();
87 let next = this.current_timestamp.saturating_add(seconds);
88 this.next_timestamp.take();
89 this.current_timestamp = next;
90 next
91 }
92
93 pub(super) fn get_block_timestamp_interval(&self) -> Option<u64> {
94 self.get().interval
95 }
96
97 pub(super) fn set_block_timestamp_interval(&self, seconds: Option<u64>) {
102 self.get_mut().interval = seconds;
103 }
104
105 pub(super) fn remove_block_timestamp_interval(&self) -> bool {
107 self.get_mut().interval.take().is_some()
108 }
109
110 pub(super) fn peek_next_timestamp(&self) -> u64 {
112 let internal = self.get();
113 internal.next_timestamp.unwrap_or_else(|| {
114 internal
115 .current_timestamp
116 .saturating_add(internal.interval())
117 })
118 }
119
120 pub(super) fn advance_timestamp(&self) -> u64 {
125 let mut internal = self.get_mut();
126 let next_timestamp = match internal.next_timestamp.take() {
127 Some(next_timestamp) => next_timestamp,
128 None => internal
129 .current_timestamp
130 .saturating_add(internal.interval()),
131 };
132
133 internal.current_timestamp = next_timestamp;
134 next_timestamp
135 }
136
137 pub(super) fn reset_to(&self, timestamp: u64) {
140 let mut internal = self.get_mut();
141 internal.next_timestamp.take();
142 internal.current_timestamp = timestamp;
143 }
144}
145
146#[derive(Debug, Default)]
147struct TimeState {
148 current_timestamp: u64,
152 next_timestamp: Option<u64>,
154 interval: Option<u64>,
156}
157
158impl TimeState {
159 fn interval(&self) -> u64 {
160 self.interval.unwrap_or(1)
161 }
162}