Skip to content

Commit 737def5

Browse files
committed
Simplify consensus check to select only longer chain
1 parent f678a1b commit 737def5

1 file changed

Lines changed: 4 additions & 120 deletions

File tree

Lines changed: 4 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,22 @@
1-
use std::cmp::{max, min};
2-
31
use blake2::{Blake2b512, Digest};
42
use serde::Deserialize;
53

6-
const SLOTS_PER_EPOCH: u32 = 7140;
7-
const GRACE_PERIOD_END: u32 = 1440;
8-
const SLOTS_PER_SUB_WINDOW: u32 = 7;
9-
const SUB_WINDOWS_PER_WINDOW: u32 = 11;
10-
// FIXME: retrieve this through archive node
11-
const SUB_WINDOW_DENSITIES: [u32; 11] = [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7];
12-
134
#[derive(Clone)]
145
pub struct ConsensusState {
15-
pub slot_since_genesis: u32,
16-
pub epoch_count: u32,
17-
pub staking_epoch_data: EpochData,
18-
pub next_epoch_data: EpochData,
19-
pub min_window_density: u32,
206
pub block_height: u32,
217
pub last_vrf_output: String,
228
}
239

24-
#[derive(Debug, Clone, Deserialize)]
25-
#[serde(rename_all = "camelCase")]
26-
pub struct EpochData {
27-
pub lock_checkpoint: String,
28-
}
29-
3010
#[derive(Clone, Deserialize)]
3111
#[serde(rename_all = "camelCase")]
3212
pub struct ConsensusStateQuery {
33-
pub slot_since_genesis: String,
34-
pub epoch_count: String,
35-
pub staking_epoch_data: EpochData,
36-
pub next_epoch_data: EpochData,
37-
pub min_window_density: String,
3813
pub block_height: String,
3914
pub last_vrf_output: String,
4015
}
4116

4217
impl From<ConsensusStateQuery> for ConsensusState {
4318
fn from(value: ConsensusStateQuery) -> Self {
4419
Self {
45-
slot_since_genesis: u32::from_str_radix(&value.slot_since_genesis, 10).unwrap(),
46-
epoch_count: u32::from_str_radix(&value.epoch_count, 10).unwrap(),
47-
staking_epoch_data: value.staking_epoch_data,
48-
next_epoch_data: value.next_epoch_data,
49-
min_window_density: u32::from_str_radix(&value.min_window_density, 10).unwrap(),
5020
block_height: u32::from_str_radix(&value.block_height, 10).unwrap(),
5121
last_vrf_output: value.last_vrf_output,
5222
}
@@ -68,99 +38,14 @@ impl ConsensusState {
6838
.ok_or("Could not parse consensus state: JSON structure is unexpected")?
6939
.to_owned();
7040

71-
dbg!(consensus_state_query_value.to_owned());
72-
7341
let consensus_state_query: ConsensusStateQuery =
7442
serde_json::from_value(consensus_state_query_value)
7543
.map_err(|err| format!("Could not parse mina consensus state: {err}"))?;
7644

7745
Ok(consensus_state_query.into())
7846
}
7947

80-
pub fn select_secure_chain(&self, other: &Self) -> Self {
81-
if self.is_short_range(other) {
82-
self.select_longer_chain(other)
83-
} else {
84-
let tip_density = self.relative_min_window_density(other);
85-
let candidate_density = other.relative_min_window_density(self);
86-
if candidate_density > tip_density {
87-
other.clone()
88-
} else if candidate_density == tip_density {
89-
self.select_longer_chain(other)
90-
} else {
91-
self.clone()
92-
}
93-
}
94-
}
95-
96-
fn is_short_range(&self, other: &Self) -> bool {
97-
if self.epoch_count == other.epoch_count {
98-
// Simple case: blocks have same previous epoch, so compare previous epochs' lock_checkpoints
99-
self.staking_epoch_data.lock_checkpoint == other.staking_epoch_data.lock_checkpoint
100-
} else {
101-
// Check for previous epoch case using both orientations
102-
self.check(other) || other.check(self)
103-
}
104-
}
105-
106-
fn check(&self, other: &Self) -> bool {
107-
if self.epoch_count == other.epoch_count + 1
108-
&& other.epoch_slot() >= 2 / 3 * SLOTS_PER_EPOCH
109-
{
110-
// S1 is one epoch ahead of S2 and S2 is not in the seed update range
111-
self.staking_epoch_data.lock_checkpoint == other.next_epoch_data.lock_checkpoint
112-
} else {
113-
false
114-
}
115-
}
116-
117-
fn epoch_slot(&self) -> u32 {
118-
self.slot_since_genesis % SLOTS_PER_EPOCH
119-
}
120-
121-
fn relative_min_window_density(&self, other: &Self) -> u32 {
122-
let max_slot = max(self.slot_since_genesis, other.slot_since_genesis);
123-
124-
// Grace-period rule
125-
if max_slot < GRACE_PERIOD_END {
126-
return self.min_window_density;
127-
}
128-
129-
// Compute B1's window projected to max_slot
130-
let projected_window = {
131-
// Compute shift count
132-
let mut shift_count = min(
133-
max(max_slot - self.slot_since_genesis - 1, 0),
134-
SUB_WINDOWS_PER_WINDOW,
135-
);
136-
137-
// Initialize projected window
138-
// FIXME: retrieve this through archive node
139-
let mut projected_window = SUB_WINDOW_DENSITIES;
140-
141-
// Ring-shift
142-
let mut i = self.relative_sub_window() as usize;
143-
while shift_count > 0 {
144-
i = (i + 1) % SUB_WINDOWS_PER_WINDOW as usize;
145-
projected_window[i] = 0;
146-
shift_count -= 1;
147-
}
148-
149-
projected_window
150-
};
151-
152-
// Compute projected window density
153-
let projected_window_density = projected_window.iter().fold(0, |acc, w| acc + w);
154-
155-
// Compute minimum window density
156-
return min(self.min_window_density, projected_window_density);
157-
}
158-
159-
fn relative_sub_window(&self) -> u32 {
160-
(self.slot_since_genesis / SLOTS_PER_SUB_WINDOW) % SUB_WINDOWS_PER_WINDOW
161-
}
162-
163-
fn select_longer_chain(&self, other: &Self) -> Self {
48+
pub fn select_longer_chain(&self, other: &Self) -> Self {
16449
if self.block_height < other.block_height {
16550
return other.clone();
16651
}
@@ -199,12 +84,11 @@ impl ConsensusState {
19984
mod tests {
20085
use super::ConsensusState;
20186

202-
const MINA_CONSENSUS_STATE_QUERY: &str = include_str!(
203-
"../../../../../batcher/aligned/test_files/mina/mina_devnet_protocol_query.json"
204-
);
87+
const MINA_CONSENSUS_STATE_QUERY: &str =
88+
include_str!("../../../../batcher/aligned/test_files/mina/mina_devnet_protocol_query.json");
20589

20690
#[test]
207-
fn test_parse_consensus_state() {
91+
fn parsing_consensus_state_works() {
20892
ConsensusState::from_json(MINA_CONSENSUS_STATE_QUERY).unwrap();
20993
}
21094
}

0 commit comments

Comments
 (0)