Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Vertex
  • Loading branch information
Damian Leśniak committed Jan 2, 2023
commit 27a342dce5d41879ef1f40208a3d0097b4b87804
99 changes: 50 additions & 49 deletions finality-aleph/src/sync/forest/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::collections::HashSet;

pub mod graph;
use graph::{Error, Forest as Graph};
use log::error;

#[derive(Clone, std::cmp::PartialEq, std::cmp::Eq, std::hash::Hash)]
pub struct Hash;
Expand All @@ -12,52 +10,39 @@ pub struct HashNumber {
number: u32,
}

#[derive(Clone, std::cmp::PartialEq, std::cmp::Eq, std::hash::Hash)]
pub struct PeerID;

#[derive(Clone)]
pub struct Justification;
pub struct Header;

struct Vertex {
body_imported: bool,
justification: Option<Justification>,
know_most: HashSet<PeerID>,
required: bool,
impl Header {
pub fn parent_hashnumber(&self) -> HashNumber {
HashNumber{ hash: Hash, number: 0 }
}
}

impl Vertex {
fn new(holder: Option<PeerID>, required: bool) -> Self {
let know_most = match holder {
Some(peer_id) => HashSet::from([peer_id]),
None => HashSet::new(),
};
Vertex {
body_imported: false,
justification: None,
know_most,
required,
}
}
#[derive(Clone, std::cmp::PartialEq, std::cmp::Eq)]
pub struct Justification;

fn add_holder(&mut self, holder: Option<PeerID>) {
if let Some(peer_id) = holder {
self.know_most.insert(peer_id);
};
impl Justification {
pub fn header(&self) -> Header {
Header
}
}

#[derive(std::cmp::PartialEq, std::cmp::Eq)]
enum State {
Unknown,
Empty,
EmptyRequired,
Header,
HeaderRequired,
Body,
JustifiedHeader,
Full,
HopelessFork,
BelowMinimal,
#[derive(Clone, std::cmp::PartialEq, std::cmp::Eq, std::hash::Hash)]
pub struct PeerID;

// TODO - merge graph with forest
pub mod graph;
pub mod vertex;

use graph::{Error, Forest as Graph};
use vertex::{Vertex, Error as VertexError, Importance, Content};

pub enum VertexState {
Unknown,
HopelessFork,
BelowMinimal,
HighestFinalized,
Candidate(Content, Importance),
}

pub enum RequestType {
Expand All @@ -67,14 +52,30 @@ pub enum RequestType {
}

/// TODO: RETHINK
impl From<State> for Option<RequestType> {
fn from(state: State) -> Self {
use State::*;
impl From<VertexState> for Option<RequestType> {
fn from(state: VertexState) -> Self {
use VertexState::*;
use Content::*;
use Importance::*;
use RequestType::{Header as RHeader, Body, JustificationsBelow};
match state {
Unknown | HopelessFork | BelowMinimal => None,
Empty => Some(RequestType::Header),
EmptyRequired | HeaderRequired | Header => Some(RequestType::Body),
Body | JustifiedHeader | Full => Some(RequestType::JustificationsBelow),
Unknown | HopelessFork | BelowMinimal | HighestFinalized => None,
Candidate(Empty, Auxiliary) => Some(RHeader),
Candidate(Empty, TopRequired) => Some(Body),
Candidate(Empty, Required) => Some(Body),
Candidate(Empty, Imported) => {
error!(target: "aleph-sync", "Forbidden state combination: (Empty, Imported), interpreting as (Header, Imported)");
Some(JustificationsBelow)
},
Candidate(Header, Auxiliary) => None,
Candidate(Header, TopRequired) => Some(Body),
Candidate(Header, Required) => Some(Body),
Candidate(Header, Imported) => Some(JustificationsBelow),
Candidate(Justification, Auxiliary) => {
error!(target: "aleph-sync", "Forbidden state combination: (Justification, Auxiliary), interpreting as (Justification, _)");
Some(JustificationsBelow)
},
Candidate(Justification, _) => Some(JustificationsBelow),
}
}
}
Expand Down
140 changes: 140 additions & 0 deletions finality-aleph/src/sync/forest/vertex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
use std::collections::HashSet;

use super::{Justification, PeerID, HashNumber, Header};

pub enum Error {
ContentCorrupted,
InvalidTransition,
InvalidHeader,
InvalidJustification,
}

#[derive(Clone, std::cmp::PartialEq, std::cmp::Eq)]
pub enum Importance {
Auxiliary,
TopRequired,
Required,
Imported,
}

#[derive(Clone, std::cmp::PartialEq, std::cmp::Eq)]
pub enum Content {
Empty,
Header,
Justification,
}

pub struct Vertex {
know_most: HashSet<PeerID>,
importance: Importance,
parent: Option<HashNumber>,
justification: Option<Justification>,
}

impl Vertex {
pub fn new(holder: Option<PeerID>) -> Self {
let know_most = match holder {
Some(peer_id) => HashSet::from([peer_id]),
None => HashSet::new(),
};
Vertex {
know_most,
importance: Importance::Auxiliary,
parent: None,
justification: None,
}
}

fn content(&self) -> Result<Content, Error> {
match (self.parent, self.justification) {
(Some(_), Some(_)) => Ok(Content::Justification),
(Some(_), None) => Ok(Content::Header),
(None, Some(_)) => Err(Error::ContentCorrupted),
(None, None) => Ok(Content::Empty),
}
}

pub fn state(&self) -> Result<(Content, Importance), Error> {
Ok((self.content()?, self.importance.clone()))
}

pub fn know_most(&self) -> HashSet<PeerID> {
self.know_most
}

pub fn parent(&self) -> Option<HashNumber> {
self.parent
}

pub fn justification(self) -> Option<Justification> {
self.justification
}

pub fn add_holder(&mut self, holder: Option<PeerID>) {
if let Some(peer_id) = holder {
self.know_most.insert(peer_id);
};
}

// STATE CHANGING METHODS

pub fn bump_required(&mut self, is_top: bool) -> Result<bool, Error> {
use Importance::*;
match (self.importance, is_top) {
(Auxiliary, true) => {
self.importance = Importance::TopRequired;
Ok(true)
},
(Auxiliary, false) => {
self.importance = Importance::Required;
Ok(true)
},
(TopRequired, false) => {
self.importance = Importance::Required;
Ok(true)
},
(Required, true) => Err(Error::InvalidTransition),
_ => Ok(false),
}
}

pub fn insert_header(&mut self, header: Header) -> Result<bool, Error> {
match self.parent {
Some(hashnumber) => {
if hashnumber != header.parent_hashnumber() {
return Err(Error::InvalidHeader);
};
Ok(false)
},
None => {
self.parent = Some(header.parent_hashnumber());
Ok(true)
},
}
}

pub fn insert_body(&mut self, header: Header) -> Result<bool, Error> {
Ok(self.insert_header(header)? || match self.importance {
Importance::Imported => false,
_ => {
self.importance = Importance::Imported;
true
},
})
}

pub fn insert_justification(&mut self, justification: Justification) -> Result<bool, Error> {
Ok(self.insert_header(justification.header())? || match self.justification {
Some(current_justification) => {
if justification != current_justification {
return Err(Error::InvalidJustification);
};
false
},
None => {
self.justification = Some(justification);
true
},
})
}
}