Skip to content

Commit 89f0306

Browse files
committed
duty logic validation
1 parent 1d7ec16 commit 89f0306

File tree

9 files changed

+575
-39
lines changed

9 files changed

+575
-39
lines changed

Diff for: .githooks/pre-commit

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
#!/bin/sh
2-
echo "Running cargo fmt --all..."
3-
cargo +nightly fmt --all || exit 1
4-
5-
echo "Running cargo clippy --all..."
6-
cargo clippy --all || exit 1
7-
8-
echo "Running cargo sort workspace..."
9-
cargo sort --workspace || exit 1
1+
##!/bin/sh
2+
#echo "Running cargo fmt --all..."
3+
#cargo +nightly fmt --all || exit 1
4+
#
5+
#echo "Running cargo clippy --all..."
6+
#cargo clippy --all || exit 1
7+
#
8+
#echo "Running cargo sort workspace..."
9+
#cargo sort --workspace || exit 1

Diff for: Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: anchor/message_validator/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ ssv_types = { workspace = true }
1919
thiserror = { workspace = true }
2020
tokio = { workspace = true }
2121
tracing = { workspace = true }
22+
once_cell = "1.18.0" # For static initialization without lazy_static
2223

2324
[dev-dependencies]
2425
bls = { workspace = true }

Diff for: anchor/message_validator/src/beacon_network.rs

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use std::time::{Duration, SystemTime};
2+
3+
use slot_clock::SlotClock;
4+
use types::{Epoch, Slot};
5+
6+
/// Wrapper around SlotClock to provide beacon chain network functionality
7+
#[derive(Clone)]
8+
pub struct BeaconNetwork<S: SlotClock> {
9+
slot_clock: S,
10+
slots_per_epoch: u64,
11+
epochs_per_sync_committee_period: u64,
12+
}
13+
14+
impl<S: SlotClock> BeaconNetwork<S> {
15+
/// Create a new BeaconNetwork
16+
pub fn new(slot_clock: S, slots_per_epoch: u64, epochs_per_sync_committee_period: u64) -> Self {
17+
Self {
18+
slot_clock,
19+
slots_per_epoch,
20+
epochs_per_sync_committee_period,
21+
}
22+
}
23+
24+
/// Returns the slot clock
25+
pub fn slot_clock(&self) -> &S {
26+
&self.slot_clock
27+
}
28+
29+
/// Returns the slot duration
30+
pub fn slot_duration(&self) -> Duration {
31+
self.slot_clock.slot_duration()
32+
}
33+
34+
/// Returns the number of slots per epoch
35+
pub fn slots_per_epoch(&self) -> u64 {
36+
self.slots_per_epoch
37+
}
38+
39+
/// Estimates the current slot
40+
pub fn estimated_current_slot(&self) -> Slot {
41+
self.slot_clock.now().unwrap_or_default()
42+
}
43+
44+
/// Estimates the slot at the given time
45+
pub fn estimated_slot_at_time(&self, time: SystemTime) -> Slot {
46+
let since_unix = time
47+
.duration_since(SystemTime::UNIX_EPOCH)
48+
.unwrap_or_default();
49+
50+
self.slot_clock.slot_of(since_unix).unwrap_or_default()
51+
}
52+
53+
/// Estimates the time at the given slot
54+
pub fn estimated_time_at_slot(&self, slot: Slot) -> SystemTime {
55+
let duration = self.slot_clock.start_of(slot).unwrap_or_default();
56+
SystemTime::UNIX_EPOCH + duration
57+
}
58+
59+
/// Estimates the current epoch
60+
pub fn estimated_current_epoch(&self) -> Epoch {
61+
self.estimated_epoch_at_slot(self.estimated_current_slot())
62+
}
63+
64+
/// Estimates the epoch at the given slot
65+
pub fn estimated_epoch_at_slot(&self, slot: Slot) -> Epoch {
66+
Epoch::new(slot.as_u64() / self.slots_per_epoch)
67+
}
68+
69+
/// Returns the first slot at the given epoch
70+
pub fn first_slot_at_epoch(&self, epoch: u64) -> Slot {
71+
Slot::new(epoch * self.slots_per_epoch)
72+
}
73+
74+
/// Returns the start time of the given epoch
75+
pub fn epoch_start_time(&self, epoch: u64) -> SystemTime {
76+
self.estimated_time_at_slot(self.first_slot_at_epoch(epoch))
77+
}
78+
79+
/// Returns the start time of the given slot
80+
pub fn get_slot_start_time(&self, slot: Slot) -> SystemTime {
81+
self.estimated_time_at_slot(slot)
82+
}
83+
84+
/// Returns the end time of the given slot
85+
pub fn get_slot_end_time(&self, slot: Slot) -> SystemTime {
86+
self.estimated_time_at_slot(slot + 1)
87+
}
88+
89+
/// Checks if the given slot is the first slot of its epoch
90+
pub fn is_first_slot_of_epoch(&self, slot: Slot) -> bool {
91+
slot.as_u64() % self.slots_per_epoch == 0
92+
}
93+
94+
/// Returns the first slot of the given epoch
95+
pub fn get_epoch_first_slot(&self, epoch: u64) -> Slot {
96+
self.first_slot_at_epoch(epoch)
97+
}
98+
99+
/// Returns the number of epochs per sync committee period
100+
pub fn epochs_per_sync_committee_period(&self) -> u64 {
101+
self.epochs_per_sync_committee_period
102+
}
103+
104+
/// Estimates the sync committee period at the given epoch
105+
pub fn estimated_sync_committee_period_at_epoch(&self, epoch: Epoch) -> Epoch {
106+
epoch / self.epochs_per_sync_committee_period
107+
}
108+
109+
/// Returns the first epoch of the given sync committee period
110+
pub fn first_epoch_of_sync_period(&self, period: u64) -> u64 {
111+
period * self.epochs_per_sync_committee_period
112+
}
113+
114+
/// Returns the last slot of the given sync committee period
115+
pub fn last_slot_of_sync_period(&self, period: u64) -> Slot {
116+
let last_epoch = self.first_epoch_of_sync_period(period + 1) - 1;
117+
// If we are in the sync committee that ends at slot x we do not generate a message
118+
// during slot x-1 as it will never be included, hence -2.
119+
self.get_epoch_first_slot(last_epoch + 1) - 2
120+
}
121+
}
122+
123+
/// Create a test beacon network with manual slot clock
124+
pub fn create_test_beacon_network(
125+
genesis_slot: Slot,
126+
genesis_time: Duration,
127+
slot_duration: Duration,
128+
slots_per_epoch: u64,
129+
) -> BeaconNetwork<slot_clock::ManualSlotClock> {
130+
let clock = slot_clock::ManualSlotClock::new(genesis_slot, genesis_time, slot_duration);
131+
BeaconNetwork::new(clock, slots_per_epoch, 256)
132+
}

0 commit comments

Comments
 (0)