Finish `BlockId` wrapper (#253)

* finish BlockId wrapper
This commit is contained in:
Al Liu 2023-07-12 19:15:29 +08:00 committed by GitHub
parent 2135676606
commit 7a776af530
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 89 additions and 40 deletions

View File

@ -406,7 +406,7 @@ mod test {
*nodes.first().unwrap(), *nodes.first().unwrap(),
Block { Block {
view: 0, view: 0,
id: [0; 32], id: BlockId::zeros(),
parent_qc: Qc::Standard(StandardQc::genesis()), parent_qc: Qc::Standard(StandardQc::genesis()),
leader_proof: LeaderProof::LeaderId { leader_proof: LeaderProof::LeaderId {
leader_id: *nodes.first().unwrap(), leader_id: *nodes.first().unwrap(),
@ -422,7 +422,7 @@ mod test {
fn next_block(engine: &Carnot<FlatOverlay<RoundRobin>>, block: &Block) -> Block { fn next_block(engine: &Carnot<FlatOverlay<RoundRobin>>, block: &Block) -> Block {
let mut next_id = block.id; let mut next_id = block.id;
next_id[0] += 1; next_id.0[0] += 1;
Block { Block {
view: block.view + 1, view: block.view + 1,
@ -498,10 +498,10 @@ mod test {
fn receive_block_with_unknown_parent() { fn receive_block_with_unknown_parent() {
let engine = init(vec![NodeId::new([0; 32])]); let engine = init(vec![NodeId::new([0; 32])]);
let mut parent_block_id = engine.genesis_block().id; let mut parent_block_id = engine.genesis_block().id;
parent_block_id[0] += 1; // generate an unknown parent block ID parent_block_id.0[0] += 1; // generate an unknown parent block ID
let block = Block { let block = Block {
view: engine.current_view() + 1, view: engine.current_view() + 1,
id: [1; 32], id: BlockId::new([1; 32]),
parent_qc: Qc::Standard(StandardQc { parent_qc: Qc::Standard(StandardQc {
view: engine.current_view(), view: engine.current_view(),
id: parent_block_id, id: parent_block_id,
@ -601,7 +601,7 @@ mod test {
// a future block should be rejected // a future block should be rejected
let future_block = Block { let future_block = Block {
id: [10; 32], id: BlockId::new([10; 32]),
view: 11, // a future view view: 11, // a future view
parent_qc: Qc::Aggregated(AggregateQc { parent_qc: Qc::Aggregated(AggregateQc {
view: 10, view: 10,
@ -619,7 +619,7 @@ mod test {
// a past block should be also rejected // a past block should be also rejected
let mut past_block = block1; // with the same view as block1 let mut past_block = block1; // with the same view as block1
past_block.id = [10; 32]; past_block.id = BlockId::new([10; 32]);
assert!(engine.receive_block(past_block).is_err()); assert!(engine.receive_block(past_block).is_err());
} }
@ -696,7 +696,7 @@ mod test {
sender: NodeId::new([0; 32]), sender: NodeId::new([0; 32]),
high_qc: StandardQc { high_qc: StandardQc {
view: 0, // genesis view: 0, // genesis
id: [0; 32], id: BlockId::zeros(),
}, },
timeout_qc: None timeout_qc: None
}), }),
@ -719,7 +719,7 @@ mod test {
1, 1,
StandardQc { StandardQc {
view: 0, // genesis view: 0, // genesis
id: [0; 32], id: BlockId::zeros(),
}, },
NodeId::new([0; 32]), NodeId::new([0; 32]),
); );
@ -744,7 +744,7 @@ mod test {
1, 1,
StandardQc { StandardQc {
view: 0, // genesis view: 0, // genesis
id: [0; 32], id: BlockId::zeros(),
}, },
NodeId::new([0; 32]), NodeId::new([0; 32]),
); );
@ -771,7 +771,7 @@ mod test {
1, 1,
StandardQc { StandardQc {
view: 0, // genesis view: 0, // genesis
id: [0; 32], id: BlockId::zeros(),
}, },
NodeId::new([0; 32]), NodeId::new([0; 32]),
); );
@ -813,7 +813,7 @@ mod test {
1, 1,
StandardQc { StandardQc {
view: 0, // genesis view: 0, // genesis
id: [0; 32], id: BlockId::zeros(),
}, },
NodeId::new([0; 32]), NodeId::new([0; 32]),
); );
@ -826,7 +826,7 @@ mod test {
2, 2,
StandardQc { StandardQc {
view: 0, // genesis view: 0, // genesis
id: [0; 32], id: BlockId::zeros(),
}, },
NodeId::new([0; 32]), NodeId::new([0; 32]),
); );

View File

@ -8,9 +8,10 @@ mod committee;
pub use committee::{Committee, CommitteeId}; pub use committee::{Committee, CommitteeId};
mod node_id; mod node_id;
pub use node_id::NodeId; pub use node_id::NodeId;
mod block_id;
pub use block_id::BlockId;
pub type View = i64; pub type View = i64;
pub type BlockId = [u8; 32];
/// The way the consensus engine communicates with the rest of the system is by returning /// The way the consensus engine communicates with the rest of the system is by returning
/// actions to be performed. /// actions to be performed.
@ -116,7 +117,7 @@ impl Block {
pub fn genesis() -> Self { pub fn genesis() -> Self {
Self { Self {
id: [0; 32], id: BlockId::zeros(),
view: 0, view: 0,
parent_qc: Qc::Standard(StandardQc::genesis()), parent_qc: Qc::Standard(StandardQc::genesis()),
leader_proof: LeaderProof::LeaderId { leader_proof: LeaderProof::LeaderId {
@ -144,7 +145,7 @@ impl StandardQc {
pub fn genesis() -> Self { pub fn genesis() -> Self {
Self { Self {
view: -1, view: -1,
id: [0; 32], id: BlockId::zeros(),
} }
} }
} }
@ -197,11 +198,11 @@ mod test {
fn standard_qc() { fn standard_qc() {
let standard_qc = StandardQc { let standard_qc = StandardQc {
view: 10, view: 10,
id: [0; 32], id: BlockId::zeros(),
}; };
let qc = Qc::Standard(standard_qc.clone()); let qc = Qc::Standard(standard_qc.clone());
assert_eq!(qc.view(), 10); assert_eq!(qc.view(), 10);
assert_eq!(qc.block(), [0; 32]); assert_eq!(qc.block(), BlockId::new([0; 32]));
assert_eq!(qc.high_qc(), standard_qc); assert_eq!(qc.high_qc(), standard_qc);
} }
@ -211,12 +212,12 @@ mod test {
view: 20, view: 20,
high_qc: StandardQc { high_qc: StandardQc {
view: 10, view: 10,
id: [0; 32], id: BlockId::zeros(),
}, },
}; };
let qc = Qc::Aggregated(aggregated_qc.clone()); let qc = Qc::Aggregated(aggregated_qc.clone());
assert_eq!(qc.view(), 20); assert_eq!(qc.view(), 20);
assert_eq!(qc.block(), [0; 32]); assert_eq!(qc.block(), BlockId::new([0; 32]));
assert_eq!(qc.high_qc(), aggregated_qc.high_qc); assert_eq!(qc.high_qc(), aggregated_qc.high_qc);
} }
@ -226,26 +227,26 @@ mod test {
2, 2,
StandardQc { StandardQc {
view: 1, view: 1,
id: [0; 32], id: BlockId::zeros(),
}, },
NodeId::new([0; 32]), NodeId::new([0; 32]),
); );
assert_eq!(timeout_qc.view(), 2); assert_eq!(timeout_qc.view(), 2);
assert_eq!(timeout_qc.high_qc().view, 1); assert_eq!(timeout_qc.high_qc().view, 1);
assert_eq!(timeout_qc.high_qc().id, [0; 32]); assert_eq!(timeout_qc.high_qc().id, BlockId::new([0; 32]));
assert_eq!(timeout_qc.sender(), NodeId::new([0; 32])); assert_eq!(timeout_qc.sender(), NodeId::new([0; 32]));
let timeout_qc = TimeoutQc::new( let timeout_qc = TimeoutQc::new(
2, 2,
StandardQc { StandardQc {
view: 2, view: 2,
id: [0; 32], id: BlockId::zeros(),
}, },
NodeId::new([0; 32]), NodeId::new([0; 32]),
); );
assert_eq!(timeout_qc.view(), 2); assert_eq!(timeout_qc.view(), 2);
assert_eq!(timeout_qc.high_qc().view, 2); assert_eq!(timeout_qc.high_qc().view, 2);
assert_eq!(timeout_qc.high_qc().id, [0; 32]); assert_eq!(timeout_qc.high_qc().id, BlockId::new([0; 32]));
assert_eq!(timeout_qc.sender(), NodeId::new([0; 32])); assert_eq!(timeout_qc.sender(), NodeId::new([0; 32]));
} }
@ -258,7 +259,7 @@ mod test {
1, 1,
StandardQc { StandardQc {
view: 2, view: 2,
id: [0; 32], id: BlockId::zeros(),
}, },
NodeId::new([0; 32]), NodeId::new([0; 32]),
); );

View File

@ -0,0 +1,50 @@
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct BlockId(pub(crate) [u8; 32]);
impl BlockId {
pub const fn new(val: [u8; 32]) -> Self {
Self(val)
}
pub const fn zeros() -> Self {
Self([0; 32])
}
/// Returns a random block id, only avaliable with feature `simulation` or test
#[cfg(any(test, feature = "simulation"))]
pub fn random<R: rand::Rng>(rng: &mut R) -> Self {
let mut bytes = [0u8; 32];
rng.fill_bytes(&mut bytes);
Self(bytes)
}
}
impl From<[u8; 32]> for BlockId {
fn from(id: [u8; 32]) -> Self {
Self(id)
}
}
impl From<&[u8; 32]> for BlockId {
fn from(id: &[u8; 32]) -> Self {
Self(*id)
}
}
impl From<BlockId> for [u8; 32] {
fn from(id: BlockId) -> Self {
id.0
}
}
impl core::fmt::Display for BlockId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "0x")?;
for v in self.0 {
write!(f, "{:02x}", v)?;
}
Ok(())
}
}

View File

@ -42,7 +42,7 @@ impl ReferenceStateMachine for RefState {
fn init_state() -> BoxedStrategy<Self::State> { fn init_state() -> BoxedStrategy<Self::State> {
let genesis_block = Block { let genesis_block = Block {
view: 0, view: 0,
id: [0; 32], id: BlockId::zeros(),
parent_qc: Qc::Standard(StandardQc::genesis()), parent_qc: Qc::Standard(StandardQc::genesis()),
leader_proof: LEADER_PROOF.clone(), leader_proof: LEADER_PROOF.clone(),
}; };
@ -332,7 +332,7 @@ impl RefState {
let current_view = self.current_view(); let current_view = self.current_view();
Just(Transition::ReceiveSafeBlock(Block { Just(Transition::ReceiveSafeBlock(Block {
id: rand::thread_rng().gen(), id: BlockId::random(&mut rand::thread_rng()),
view: current_view + 1, view: current_view + 1,
parent_qc: Qc::Aggregated(AggregateQc { parent_qc: Qc::Aggregated(AggregateQc {
high_qc: self.high_qc(), high_qc: self.high_qc(),
@ -395,7 +395,7 @@ impl RefState {
fn consecutive_block(parent: &Block) -> Block { fn consecutive_block(parent: &Block) -> Block {
Block { Block {
// use rand because we don't want this to be shrinked by proptest // use rand because we don't want this to be shrinked by proptest
id: rand::thread_rng().gen(), id: BlockId::random(&mut rand::thread_rng()),
view: parent.view + 1, view: parent.view + 1,
parent_qc: Qc::Standard(StandardQc { parent_qc: Qc::Standard(StandardQc {
view: parent.view, view: parent.view,

View File

@ -22,7 +22,7 @@ impl ConsensusEngineTest {
NodeId::new([0; 32]), NodeId::new([0; 32]),
Block { Block {
view: 0, view: 0,
id: [0; 32], id: BlockId::zeros(),
parent_qc: Qc::Standard(StandardQc::genesis()), parent_qc: Qc::Standard(StandardQc::genesis()),
leader_proof: LeaderProof::LeaderId { leader_proof: LeaderProof::LeaderId {
leader_id: NodeId::new([0; 32]), leader_id: NodeId::new([0; 32]),

View File

@ -5,6 +5,7 @@ use core::hash::Hash;
// crates // crates
use crate::wire; use crate::wire;
use bytes::Bytes; use bytes::Bytes;
pub use consensus_engine::BlockId;
use consensus_engine::{LeaderProof, NodeId, Qc, View}; use consensus_engine::{LeaderProof, NodeId, Qc, View};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -20,9 +21,6 @@ pub struct Block<TxId: Clone + Eq + Hash> {
beacon: RandomBeaconState, beacon: RandomBeaconState,
} }
/// Identifier of a block
pub type BlockId = [u8; 32];
impl<TxId: Clone + Eq + Hash + Serialize + DeserializeOwned> Block<TxId> { impl<TxId: Clone + Eq + Hash + Serialize + DeserializeOwned> Block<TxId> {
pub fn new( pub fn new(
view: View, view: View,
@ -33,7 +31,7 @@ impl<TxId: Clone + Eq + Hash + Serialize + DeserializeOwned> Block<TxId> {
) -> Self { ) -> Self {
let transactions = txs.collect(); let transactions = txs.collect();
let header = consensus_engine::Block { let header = consensus_engine::Block {
id: [0; 32], id: BlockId::zeros(),
view, view,
parent_qc, parent_qc,
leader_proof: LeaderProof::LeaderId { leader_proof: LeaderProof::LeaderId {
@ -74,7 +72,7 @@ pub fn block_id_from_wire_content<Tx: Clone + Eq + Hash + Serialize + Deserializ
let bytes = block.as_bytes(); let bytes = block.as_bytes();
let mut hasher = Blake2b::<U32>::new(); let mut hasher = Blake2b::<U32>::new();
hasher.update(bytes); hasher.update(bytes);
hasher.finalize().into() BlockId::new(hasher.finalize().into())
} }
impl<TxId: Clone + Eq + Hash + Serialize + DeserializeOwned> Block<TxId> { impl<TxId: Clone + Eq + Hash + Serialize + DeserializeOwned> Block<TxId> {

View File

@ -177,7 +177,7 @@ where
let overlay = O::new(overlay_settings); let overlay = O::new(overlay_settings);
let genesis = consensus_engine::Block { let genesis = consensus_engine::Block {
id: [0; 32], id: BlockId::zeros(),
view: 0, view: 0,
parent_qc: Qc::Standard(StandardQc::genesis()), parent_qc: Qc::Standard(StandardQc::genesis()),
leader_proof: LeaderProof::LeaderId { leader_proof: LeaderProof::LeaderId {
@ -560,7 +560,7 @@ where
let mut output = None; let mut output = None;
mempool_relay mempool_relay
.send(MempoolMsg::View { .send(MempoolMsg::View {
ancestor_hint: [0; 32], ancestor_hint: BlockId::zeros(),
reply_channel, reply_channel,
}) })
.await .await
@ -864,16 +864,16 @@ mod tests {
highest_voted_view: -1, highest_voted_view: -1,
local_high_qc: StandardQc { local_high_qc: StandardQc {
view: 0, view: 0,
id: [0; 32], id: BlockId::zeros(),
}, },
safe_blocks: HashMap::from([( safe_blocks: HashMap::from([(
[0; 32], BlockId::zeros(),
Block { Block {
id: [0; 32], id: BlockId::zeros(),
view: 0, view: 0,
parent_qc: Qc::Standard(StandardQc { parent_qc: Qc::Standard(StandardQc {
view: 0, view: 0,
id: [0; 32], id: BlockId::zeros(),
}), }),
leader_proof: LeaderProof::LeaderId { leader_proof: LeaderProof::LeaderId {
leader_id: NodeId::new([0; 32]), leader_id: NodeId::new([0; 32]),
@ -881,7 +881,7 @@ mod tests {
}, },
)]), )]),
last_view_timeout_qc: None, last_view_timeout_qc: None,
committed_blocks: vec![[0; 32]], committed_blocks: vec![BlockId::zeros()],
}; };
let serialized = serde_json::to_string(&info).unwrap(); let serialized = serde_json::to_string(&info).unwrap();