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

View File

@ -8,9 +8,10 @@ mod committee;
pub use committee::{Committee, CommitteeId};
mod node_id;
pub use node_id::NodeId;
mod block_id;
pub use block_id::BlockId;
pub type View = i64;
pub type BlockId = [u8; 32];
/// The way the consensus engine communicates with the rest of the system is by returning
/// actions to be performed.
@ -116,7 +117,7 @@ impl Block {
pub fn genesis() -> Self {
Self {
id: [0; 32],
id: BlockId::zeros(),
view: 0,
parent_qc: Qc::Standard(StandardQc::genesis()),
leader_proof: LeaderProof::LeaderId {
@ -144,7 +145,7 @@ impl StandardQc {
pub fn genesis() -> Self {
Self {
view: -1,
id: [0; 32],
id: BlockId::zeros(),
}
}
}
@ -197,11 +198,11 @@ mod test {
fn standard_qc() {
let standard_qc = StandardQc {
view: 10,
id: [0; 32],
id: BlockId::zeros(),
};
let qc = Qc::Standard(standard_qc.clone());
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);
}
@ -211,12 +212,12 @@ mod test {
view: 20,
high_qc: StandardQc {
view: 10,
id: [0; 32],
id: BlockId::zeros(),
},
};
let qc = Qc::Aggregated(aggregated_qc.clone());
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);
}
@ -226,26 +227,26 @@ mod test {
2,
StandardQc {
view: 1,
id: [0; 32],
id: BlockId::zeros(),
},
NodeId::new([0; 32]),
);
assert_eq!(timeout_qc.view(), 2);
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]));
let timeout_qc = TimeoutQc::new(
2,
StandardQc {
view: 2,
id: [0; 32],
id: BlockId::zeros(),
},
NodeId::new([0; 32]),
);
assert_eq!(timeout_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]));
}
@ -258,7 +259,7 @@ mod test {
1,
StandardQc {
view: 2,
id: [0; 32],
id: BlockId::zeros(),
},
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> {
let genesis_block = Block {
view: 0,
id: [0; 32],
id: BlockId::zeros(),
parent_qc: Qc::Standard(StandardQc::genesis()),
leader_proof: LEADER_PROOF.clone(),
};
@ -332,7 +332,7 @@ impl RefState {
let current_view = self.current_view();
Just(Transition::ReceiveSafeBlock(Block {
id: rand::thread_rng().gen(),
id: BlockId::random(&mut rand::thread_rng()),
view: current_view + 1,
parent_qc: Qc::Aggregated(AggregateQc {
high_qc: self.high_qc(),
@ -395,7 +395,7 @@ impl RefState {
fn consecutive_block(parent: &Block) -> Block {
Block {
// 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,
parent_qc: Qc::Standard(StandardQc {
view: parent.view,

View File

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

View File

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

View File

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