tmp
This commit is contained in:
parent
a237b05d25
commit
c4a0af34ad
|
@ -1,3 +1,10 @@
|
|||
mod ref_state;
|
||||
pub mod sut;
|
||||
mod transition;
|
||||
|
||||
type Block = carnot_engine::Block<[u8; 32]>;
|
||||
type AggregateQc = carnot_engine::AggregateQc<[u8; 32]>;
|
||||
type Qc = carnot_engine::Qc<[u8; 32]>;
|
||||
type StandardQc = carnot_engine::StandardQc<[u8; 32]>;
|
||||
type TimeoutQc = carnot_engine::TimeoutQc<[u8; 32]>;
|
||||
type NewView = carnot_engine::NewView<[u8; 32]>;
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
use carnot_engine::{
|
||||
AggregateQc, Block, BlockId, LeaderProof, NodeId, Qc, StandardQc, TimeoutQc, View,
|
||||
};
|
||||
use carnot_engine::{LeaderProof, NodeId, View};
|
||||
use proptest::prelude::*;
|
||||
use proptest::strategy::BoxedStrategy;
|
||||
use proptest_state_machine::ReferenceStateMachine;
|
||||
|
||||
use crate::fuzz::transition::Transition;
|
||||
use crate::fuzz::{AggregateQc, Block, Qc, StandardQc, TimeoutQc};
|
||||
|
||||
// A reference state machine (RefState) is used to generated state transitions.
|
||||
// To generate some kinds of transition, we may need to keep historical blocks in RefState.
|
||||
|
@ -42,8 +41,8 @@ impl ReferenceStateMachine for RefState {
|
|||
fn init_state() -> BoxedStrategy<Self::State> {
|
||||
let genesis_block = Block {
|
||||
view: View::new(0),
|
||||
id: BlockId::zeros(),
|
||||
parent_qc: Qc::Standard(StandardQc::genesis()),
|
||||
id: [0; 32],
|
||||
parent_qc: Qc::Standard(StandardQc::genesis([0; 32])),
|
||||
leader_proof: LEADER_PROOF.clone(),
|
||||
};
|
||||
|
||||
|
@ -330,10 +329,11 @@ impl RefState {
|
|||
fn transition_receive_safe_block_with_aggregated_qc(&self) -> BoxedStrategy<Transition> {
|
||||
//TODO: more randomness
|
||||
let current_view = self.current_view();
|
||||
|
||||
let mut id = [0; 32];
|
||||
rand::thread_rng().fill_bytes(&mut id);
|
||||
Just(Transition::ReceiveSafeBlock(Block {
|
||||
view: current_view.next(),
|
||||
id: BlockId::random(&mut rand::thread_rng()),
|
||||
id,
|
||||
parent_qc: Qc::Aggregated(AggregateQc {
|
||||
high_qc: self.high_qc(),
|
||||
view: current_view,
|
||||
|
@ -360,9 +360,13 @@ impl RefState {
|
|||
pub fn high_qc(&self) -> StandardQc {
|
||||
self.chain
|
||||
.values()
|
||||
.map(|entry| entry.high_qc().unwrap_or_else(StandardQc::genesis))
|
||||
.map(|entry| {
|
||||
entry
|
||||
.high_qc()
|
||||
.unwrap_or_else(|| StandardQc::genesis([0; 32]))
|
||||
})
|
||||
.max_by_key(|qc| qc.view)
|
||||
.unwrap_or_else(StandardQc::genesis)
|
||||
.unwrap_or_else(|| StandardQc::genesis([0; 32]))
|
||||
}
|
||||
|
||||
pub fn latest_timeout_qcs(&self) -> Vec<TimeoutQc> {
|
||||
|
@ -386,17 +390,19 @@ impl RefState {
|
|||
self.contains_block(block.parent_qc.block())
|
||||
}
|
||||
|
||||
fn contains_block(&self, block_id: BlockId) -> bool {
|
||||
fn contains_block(&self, block_id: [u8; 32]) -> bool {
|
||||
self.chain
|
||||
.iter()
|
||||
.any(|(_, entry)| entry.blocks.iter().any(|block| block.id == block_id))
|
||||
}
|
||||
|
||||
fn consecutive_block(parent: &Block) -> Block {
|
||||
let mut id = [0; 32];
|
||||
rand::thread_rng().fill_bytes(&mut id);
|
||||
Block {
|
||||
// use rand because we don't want this to be shrinked by proptest
|
||||
view: parent.view.next(),
|
||||
id: BlockId::random(&mut rand::thread_rng()),
|
||||
id,
|
||||
parent_qc: Qc::Standard(StandardQc {
|
||||
view: parent.view,
|
||||
id: parent.id,
|
||||
|
|
|
@ -8,13 +8,13 @@ use carnot_engine::{
|
|||
use proptest_state_machine::{ReferenceStateMachine, StateMachineTest};
|
||||
|
||||
use crate::fuzz::ref_state::RefState;
|
||||
use crate::fuzz::transition::Transition;
|
||||
use crate::fuzz::{transition::Transition, Block};
|
||||
|
||||
// ConsensusEngineTest defines a state that we want to test.
|
||||
// This is called as SUT (System Under Test).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ConsensusEngineTest {
|
||||
pub engine: Carnot<FlatOverlay<RoundRobin, FreezeMembership>>,
|
||||
pub engine: Carnot<FlatOverlay<RoundRobin, FreezeMembership>, [u8; 32]>,
|
||||
}
|
||||
|
||||
impl ConsensusEngineTest {
|
||||
|
@ -23,8 +23,8 @@ impl ConsensusEngineTest {
|
|||
NodeId::new([0; 32]),
|
||||
Block {
|
||||
view: View::new(0),
|
||||
id: BlockId::zeros(),
|
||||
parent_qc: Qc::Standard(StandardQc::genesis()),
|
||||
id: [0; 32],
|
||||
parent_qc: Qc::Standard(StandardQc::genesis([0; 32])),
|
||||
leader_proof: LeaderProof::LeaderId {
|
||||
leader_id: NodeId::new([0; 32]),
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use carnot_engine::{Block, NewView, TimeoutQc};
|
||||
use crate::fuzz::{Block, NewView, TimeoutQc};
|
||||
|
||||
// State transtitions that will be picked randomly
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
@ -22,6 +22,7 @@ thiserror = "1.0"
|
|||
bincode = "1.3"
|
||||
once_cell = "1.0"
|
||||
indexmap = { version = "1.9", features = ["serde"] }
|
||||
const-hex = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.8"
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::utils::display_hex_bytes_newtype;
|
||||
use crate::utils::{display_hex_bytes_newtype, serde_bytes_newtype};
|
||||
|
||||
pub mod carnot;
|
||||
pub mod cryptarchia;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash, Serialize, Deserialize, PartialOrd, Ord)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash, PartialOrd, Ord)]
|
||||
pub struct HeaderId([u8; 32]);
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)]
|
||||
pub struct ContentId([u8; 32]);
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -73,3 +73,15 @@ impl From<ContentId> for [u8; 32] {
|
|||
|
||||
display_hex_bytes_newtype!(HeaderId);
|
||||
display_hex_bytes_newtype!(ContentId);
|
||||
|
||||
serde_bytes_newtype!(HeaderId, 32);
|
||||
serde_bytes_newtype!(ContentId, 32);
|
||||
|
||||
#[test]
|
||||
fn test_serde() {
|
||||
assert_eq!(
|
||||
crate::wire::deserialize::<HeaderId>(&crate::wire::serialize(&HeaderId([0; 32])).unwrap())
|
||||
.unwrap(),
|
||||
HeaderId([0; 32])
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,4 +14,40 @@ macro_rules! display_hex_bytes_newtype {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! serde_bytes_newtype {
|
||||
($newtype:ty, $len:expr) => {
|
||||
impl serde::Serialize for $newtype {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
const_hex::const_encode::<$len, false>(&self.0)
|
||||
.as_str()
|
||||
.serialize(serializer)
|
||||
} else {
|
||||
self.0.serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for $newtype {
|
||||
fn deserialize<D>(deserializer: D) -> Result<$newtype, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
let s = <&str>::deserialize(deserializer)?;
|
||||
const_hex::decode_to_array(s)
|
||||
.map(Self)
|
||||
.map_err(serde::de::Error::custom)
|
||||
} else {
|
||||
<[u8; $len]>::deserialize(deserializer).map(Self)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use display_hex_bytes_newtype;
|
||||
pub(crate) use serde_bytes_newtype;
|
||||
|
|
|
@ -306,6 +306,7 @@ where
|
|||
);
|
||||
|
||||
if carnot.is_next_leader() {
|
||||
tracing::info!("is next leader, gathering vores");
|
||||
let network_adapter = adapter.clone();
|
||||
task_manager.push(genesis_block.view.next(), async move {
|
||||
let Event::Approve { qc, .. } = Self::gather_votes(
|
||||
|
@ -319,6 +320,7 @@ where
|
|||
tracing::debug!("Failed to gather initial votes");
|
||||
return Event::None;
|
||||
};
|
||||
tracing::info!("got enough votes");
|
||||
Event::ProposeBlock { qc }
|
||||
});
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ impl NetworkAdapter for Libp2pAdapter {
|
|||
}
|
||||
}
|
||||
NetworkMessage::Vote(msg) => {
|
||||
tracing::debug!("received vote");
|
||||
tracing::debug!("received vote {:?}", msg);
|
||||
let mut cache = cache.cache.lock().unwrap();
|
||||
let view = msg.vote.view;
|
||||
if let Some(messages) = cache.get_mut(&view) {
|
||||
|
|
|
@ -86,7 +86,7 @@ impl TimeoutQcMsg {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum NetworkMessage {
|
||||
Timeout(TimeoutMsg),
|
||||
TimeoutQc(TimeoutQcMsg),
|
||||
|
|
|
@ -84,7 +84,6 @@ impl Tally for CarnotTally {
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
Err(CarnotTallyError::StreamEnded)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use nomos_core::{
|
||||
block::BlockId,
|
||||
header::HeaderId,
|
||||
tx::mock::{MockTransaction, MockTxId},
|
||||
};
|
||||
use nomos_log::{Logger, LoggerSettings};
|
||||
|
@ -23,7 +23,7 @@ struct MockPoolNode {
|
|||
mockpool: ServiceHandle<
|
||||
MempoolService<
|
||||
MockAdapter,
|
||||
MockPool<BlockId, MockTransaction<MockMessage>, MockTxId>,
|
||||
MockPool<HeaderId, MockTransaction<MockMessage>, MockTxId>,
|
||||
Transaction,
|
||||
>,
|
||||
>,
|
||||
|
@ -80,7 +80,7 @@ fn test_mockmempool() {
|
|||
let network = app.handle().relay::<NetworkService<Mock>>();
|
||||
let mempool = app.handle().relay::<MempoolService<
|
||||
MockAdapter,
|
||||
MockPool<BlockId, MockTransaction<MockMessage>, MockTxId>,
|
||||
MockPool<HeaderId, MockTransaction<MockMessage>, MockTxId>,
|
||||
Transaction,
|
||||
>>();
|
||||
|
||||
|
@ -102,7 +102,7 @@ fn test_mockmempool() {
|
|||
let (mtx, mrx) = tokio::sync::oneshot::channel();
|
||||
mempool_outbound
|
||||
.send(MempoolMsg::View {
|
||||
ancestor_hint: BlockId::default(),
|
||||
ancestor_hint: [0; 32].into(),
|
||||
reply_channel: mtx,
|
||||
})
|
||||
.await
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
use carnot_consensus::CarnotInfo;
|
||||
use carnot_engine::{Block, NodeId, TimeoutQc, View};
|
||||
use carnot_engine::{NodeId, View};
|
||||
use fraction::Fraction;
|
||||
use futures::stream::{self, StreamExt};
|
||||
use nomos_core::header::HeaderId;
|
||||
use std::{collections::HashSet, time::Duration};
|
||||
use tests::{adjust_timeout, ConsensusConfig, MixNode, Node, NomosNode, SpawnConfig};
|
||||
|
||||
const TARGET_VIEW: View = View::new(20);
|
||||
const DUMMY_NODE_ID: NodeId = NodeId::new([0u8; 32]);
|
||||
|
||||
type Block = carnot_engine::Block<HeaderId>;
|
||||
type TimeoutQc = carnot_engine::TimeoutQc<HeaderId>;
|
||||
|
||||
#[tokio::test]
|
||||
async fn ten_nodes_one_down() {
|
||||
let (_mixnodes, mixnet_config) = MixNode::spawn_nodes(3).await;
|
||||
|
|
Loading…
Reference in New Issue