pub mod test_block;
use std::{
cell::{Cell, RefCell},
collections::HashMap,
rc::Rc,
};
use crate::snowman::snowball::tree::Tree;
use avalanche_types::{
choices::{decidable::Decidable, status::Status},
ids::Id,
verify::Verifiable,
};
use bytes::Bytes;
pub trait Block: Clone + Verifiable + Decidable {
fn bytes(&self) -> Bytes;
fn height(&self) -> u64;
fn timestamp(&self) -> u64;
fn parent(&self) -> Id;
}
type Blocks<B> = Rc<RefCell<HashMap<Id, Rc<RefCell<B>>>>>;
#[derive(Debug, Clone)]
pub struct SnowmanBlock<B: Block> {
parameters: crate::Parameters,
pub blk: Option<Rc<RefCell<B>>>,
pub sb: Option<Box<Tree>>,
pub children: Option<Blocks<B>>,
pub should_falter: Cell<bool>,
}
impl<B> SnowmanBlock<B>
where
B: Block,
{
pub fn new(parameters: crate::Parameters) -> Self {
Self {
parameters,
blk: None,
sb: None,
children: None,
should_falter: Cell::new(false),
}
}
pub fn new_with_block(parameters: crate::Parameters, blk: Rc<RefCell<B>>) -> Self {
Self {
parameters,
blk: Some(blk),
sb: None,
children: None,
should_falter: Cell::new(false),
}
}
pub fn id(&self) -> Option<Id> {
if self.blk.is_none() {
None
} else {
Some(self.blk.as_ref().unwrap().borrow().id())
}
}
pub fn height(&self) -> Option<u64> {
if self.blk.is_none() {
None
} else {
Some(self.blk.as_ref().unwrap().borrow().height())
}
}
pub fn status(&self) -> Option<Status> {
if self.blk.is_none() {
None
} else {
Some(self.blk.as_ref().unwrap().borrow().status())
}
}
pub fn accepted(&self) -> bool {
if self.blk.is_none() {
return true;
}
self.blk.as_ref().unwrap().borrow().status() == Status::Accepted
}
pub fn add_child(&mut self, child: Rc<RefCell<B>>) {
let child_id = child.borrow().id();
if let Some(sb) = self.sb.as_mut() {
sb.add(&child_id);
} else {
let sb = Tree::new(self.parameters.clone(), child_id);
self.sb = Some(Box::new(sb));
self.children = Some(Rc::new(RefCell::new(HashMap::new())));
}
if let Some(children) = self.children.as_mut() {
children.borrow_mut().insert(child_id, child);
} else {
panic!("unexpected None children")
}
}
}