Skip to content

Commit

Permalink
feat/parsec: add related_info to Observation::Genesis
Browse files Browse the repository at this point in the history
- Add `genesis_related_info` parameter to `Parsec::from_genesis` for specifying the related_info on the genesis event.
- Some dot files had to be modified/regenerated because the hash of `Observation::Genesis` changed.
- A bogus clippy lint silenced by slightly reshuffling the code (clippy issue: rust-lang/rust-clippy#4133)
  • Loading branch information
madadam committed May 29, 2019
1 parent 8c0d9d0 commit 0ebfb42
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 52 deletions.
7 changes: 6 additions & 1 deletion examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,12 @@ impl Peer {
fn from_genesis(our_id: PeerId, genesis_group: &BTreeSet<PeerId>) -> Self {
Self {
id: our_id.clone(),
parsec: Parsec::from_genesis(our_id, genesis_group, ConsensusMode::Supermajority),
parsec: Parsec::from_genesis(
our_id,
genesis_group,
vec![],
ConsensusMode::Supermajority,
),
observations: vec![],
blocks: vec![],
}
Expand Down
2 changes: 1 addition & 1 deletion input_graphs/benches/minimal.dot
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ digraph GossipGraph {

/// ===== meta-elections =====
/// consensus_history:
/// a137c1b54c5895b13a1e204869f650636920286bd5b903e0576a9a15a2f58c2c
/// d98f8abc4ba966aadc391bb857a6879a122602074766f19fadf22ce59dd0410e
/// c93ff2cda7e9dd6a49b12c4fccdbaa0fe1b25b1e92421f288b06bfe53122be0f

/// interesting_events: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/// Carol: PeerState(VOTE|SEND|RECV)
/// Claire: PeerState(VOTE|SEND|RECV)
/// }
/// consensus_mode: Supermajority
digraph GossipGraph {
splines=false
rankdir=BT
Expand Down Expand Up @@ -1163,7 +1164,7 @@ digraph GossipGraph {

/// ===== meta-elections =====
/// consensus_history:
/// ece3eaf86a7f7396aed2e4bdd0c67cf7b67df5aabbd5eced04924b154d0f3841
/// 5d1bc22c2cce50873bffc1ba00ecbecce52085dc3bd15e8b43f5167bf72962cd

/// interesting_events: {
/// Annie -> ["An_19"]
Expand All @@ -1174,10 +1175,6 @@ digraph GossipGraph {
/// all_voters: {Annie, B, Carol, Claire}
/// unconsensused_events: {"An_13", "B_9", "Ca_6", "Cl_10"}
/// meta_events: {
/// An_13 -> {
/// observees: {}
/// interesting_content: []
/// }
/// An_14 -> {
/// observees: {}
/// interesting_content: []
Expand Down Expand Up @@ -1353,10 +1350,6 @@ digraph GossipGraph {
/// observees: {}
/// interesting_content: []
/// }
/// B_9 -> {
/// observees: {}
/// interesting_content: []
/// }
/// B_10 -> {
/// observees: {}
/// interesting_content: []
Expand Down Expand Up @@ -1467,10 +1460,6 @@ digraph GossipGraph {
/// Cl: 0/0 t t t t
/// }
/// }
/// Ca_6 -> {
/// observees: {}
/// interesting_content: []
/// }
/// Ca_7 -> {
/// observees: {}
/// interesting_content: []
Expand Down Expand Up @@ -1620,10 +1609,6 @@ digraph GossipGraph {
/// observees: {}
/// interesting_content: []
/// }
/// Cl_10 -> {
/// observees: {}
/// interesting_content: []
/// }
/// Cl_11 -> {
/// observees: {}
/// interesting_content: []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ digraph GossipGraph {

/// ===== meta-elections =====
/// consensus_history:
/// a137c1b54c5895b13a1e204869f650636920286bd5b903e0576a9a15a2f58c2c
/// d98f8abc4ba966aadc391bb857a6879a122602074766f19fadf22ce59dd0410e

/// interesting_events: {
/// Alice -> ["A_14"]
Expand Down
5 changes: 4 additions & 1 deletion src/dev_utils/dot_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,10 @@ fn parse_invalid() -> Parser<u8, MaliceInput> {
}

fn parse_genesis() -> Parser<u8, Observation<Transaction, PeerId>> {
(seq(b"Genesis(") * parse_peers() - seq(b")")).map(Observation::Genesis)
(seq(b"Genesis(") * parse_peers() - seq(b")")).map(|group| Observation::Genesis {
group,
related_info: vec![],
})
}

fn parse_add() -> Parser<u8, Observation<Transaction, PeerId>> {
Expand Down
6 changes: 3 additions & 3 deletions src/dev_utils/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,16 +425,16 @@ impl Network {

for block_group in block_groups {
for block in block_group {
if let ParsecObservation::Genesis(ref g) = *block.payload() {
valid_voters = g.clone();
if let ParsecObservation::Genesis { ref group, .. } = *block.payload() {
valid_voters = group.clone();
}

self.check_block_signatories(block, &valid_voters)?;
}

for block in block_group {
match *block.payload() {
ParsecObservation::Genesis(_) => (),
ParsecObservation::Genesis { .. } => (),
ParsecObservation::Add { ref peer_id, .. } => {
let _ = valid_voters.insert(peer_id.clone());
}
Expand Down
1 change: 1 addition & 0 deletions src/dev_utils/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ impl Peer {
Self::new(WrappedParsec::Good(Parsec::from_genesis(
id,
genesis_group,
vec![],
consensus_mode,
)))
}
Expand Down
12 changes: 8 additions & 4 deletions src/dev_utils/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ impl Record {
}

pub fn play(self) -> Parsec<Transaction, PeerId> {
let mut parsec =
Parsec::from_genesis(self.our_id, &self.genesis_group, self.consensus_mode);
let mut parsec = Parsec::from_genesis(
self.our_id,
&self.genesis_group,
vec![],
self.consensus_mode,
);

for action in self.actions {
action.run(&mut parsec)
Expand Down Expand Up @@ -213,8 +217,8 @@ fn extract_genesis_group<'a>(
.and_then(|key| observations.get(key))
.map(|info| &info.observation)
.and_then(|observation| {
if let Observation::Genesis(ref genesis_group) = *observation {
Some(genesis_group)
if let Observation::Genesis { ref group, .. } = *observation {
Some(group)
} else {
None
}
Expand Down
2 changes: 1 addition & 1 deletion src/dump_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ mod detail {
short_peer_ids: &PeerIndexMap<String>,
) -> Self {
let value = match observation {
Observation::Genesis(group) => format!(
Observation::Genesis { group, .. } => format!(
"Genesis({:?})",
group.iter().map(sanitise_peer_id).collect::<BTreeSet<_>>()
),
Expand Down
38 changes: 28 additions & 10 deletions src/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,13 @@ fn from_genesis() {
assert_eq!(*parsec.event_creator_id(&genesis_observation), our_id);
match parsec.event_payload(&genesis_observation) {
Some(payload) => {
assert_eq!(*payload, Observation::Genesis(peers));
assert_eq!(
*payload,
Observation::Genesis {
group: peers,
related_info: vec![]
}
);
}
None => panic!("Expected observation, but event carried no vote"),
}
Expand Down Expand Up @@ -341,6 +347,7 @@ fn unpolled_observations() {
peer_id: PeerId::new("Eric"),
related_info: vec![],
};

assert_eq!(alice.our_unpolled_observations().count(), 1);
assert_eq!(*unwrap!(alice.our_unpolled_observations().next()), add_eric);

Expand Down Expand Up @@ -389,7 +396,7 @@ fn our_unpolled_observations_with_consensus_mode_single() {
let mut alice = Record::from(parse_test_dot_file("alice.dot")).play();

let block = unwrap!(alice.poll());
if let Observation::Genesis(_) = block.payload() {
if let Observation::Genesis { .. } = block.payload() {
} else {
panic!();
}
Expand Down Expand Up @@ -587,9 +594,13 @@ mod handle_malice {
));
let d_1_index = dave_contents.add_event(d_1);

let d_2 = unwrap!(
dave_contents.new_event_from_observation(d_1_index, Observation::Genesis(genesis),)
);
let d_2 = unwrap!(dave_contents.new_event_from_observation(
d_1_index,
Observation::Genesis {
group: genesis,
related_info: vec![]
}
));
let d_2_hash = *d_2.hash();
let _ = dave_contents.add_event(d_2);

Expand Down Expand Up @@ -642,9 +653,13 @@ mod handle_malice {
let e_0 = Event::new_initial(eric_contents.event_context());
let e_0_index = eric_contents.add_event(e_0);

let e_1 = unwrap!(
eric_contents.new_event_from_observation(e_0_index, Observation::Genesis(genesis),)
);
let e_1 = unwrap!(eric_contents.new_event_from_observation(
e_0_index,
Observation::Genesis {
group: genesis,
related_info: vec![]
},
));
let e_1_hash = *e_1.hash();
let _ = eric_contents.add_event(e_1);

Expand Down Expand Up @@ -703,7 +718,7 @@ mod handle_malice {
// Pop Alice's last event, which is her genesis vote.
let (_, genesis_event) = unwrap!(alice.remove_last_event());
match unwrap!(alice.event_payload(&genesis_event)) {
Observation::Genesis(_) => (),
Observation::Genesis { .. } => (),
_ => panic!("This should be Alice's genesis vote."),
}

Expand Down Expand Up @@ -735,7 +750,10 @@ mod handle_malice {
bob.our_pub_id().clone(),
PeerId::new("Derp")
];
unwrap!(alice.vote_for(Observation::Genesis(invalid_genesis)));
unwrap!(alice.vote_for(Observation::Genesis {
group: invalid_genesis,
related_info: vec![]
}));

// Create request from Alice to Carol.
let request = unwrap!(alice.create_gossip(carol.our_pub_id()));
Expand Down
9 changes: 7 additions & 2 deletions src/observation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ use std::{
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Observation<T: NetworkEvent, P: PublicId> {
/// Genesis group
Genesis(BTreeSet<P>),
Genesis {
/// Members of the genesis group.
group: BTreeSet<P>,
/// Extra arbitrary information for use by the client.
related_info: Vec<u8>,
},
/// Vote to add the indicated peer to the network.
Add {
/// Public id of the peer to be added
Expand Down Expand Up @@ -67,7 +72,7 @@ impl<T: NetworkEvent, P: PublicId> Observation<T, P> {
impl<T: NetworkEvent, P: PublicId> Debug for Observation<T, P> {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
match self {
Observation::Genesis(group) => write!(formatter, "Genesis({:?})", group),
Observation::Genesis { group, .. } => write!(formatter, "Genesis({:?})", group),
Observation::Add { peer_id, .. } => write!(formatter, "Add({:?})", peer_id),
Observation::Remove { peer_id, .. } => write!(formatter, "Remove({:?})", peer_id),
Observation::Accusation { offender, malice } => {
Expand Down
33 changes: 22 additions & 11 deletions src/parsec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,14 @@ impl<T: NetworkEvent, S: SecretId> Parsec<T, S> {
/// * `our_id` is the value that will identify the owning peer in the network.
/// * `genesis_group` is the set of public IDs of the peers that are present at the network
/// startup.
/// * `genesis_related_info` extra arbitrary information attached to the genesis event for use
/// by the client.
/// * `consensus_mode` determines how many votes are needed for an observation to become a
/// candidate for consensus. For more details, see [ConsensusMode](enum.ConsensusMode.html)
pub fn from_genesis(
our_id: S,
genesis_group: &BTreeSet<S::PublicId>,
genesis_related_info: Vec<u8>,
consensus_mode: ConsensusMode,
) -> Self {
if !genesis_group.contains(our_id.public_id()) {
Expand All @@ -147,7 +150,10 @@ impl<T: NetworkEvent, S: SecretId> Parsec<T, S> {
parsec.add_initial_event();

// Add event carrying genesis observation.
let genesis_observation = Observation::Genesis(genesis_group.clone());
let genesis_observation = Observation::Genesis {
group: genesis_group.clone(),
related_info: genesis_related_info,
};
let event = parsec.our_last_event_index().and_then(|self_parent| {
parsec.new_event_from_observation(self_parent, genesis_observation)
});
Expand Down Expand Up @@ -821,7 +827,7 @@ impl<T: NetworkEvent, S: SecretId> Parsec<T, S> {

self.handle_remove_peer(event_index, offender)
}
Some(Observation::Genesis(_)) | Some(Observation::OpaquePayload(_)) => None,
Some(Observation::Genesis { .. }) | Some(Observation::OpaquePayload(_)) => None,
None => {
log_or_panic!("Failed to get observation from hash.");
None
Expand Down Expand Up @@ -1589,7 +1595,7 @@ impl<T: NetworkEvent, S: SecretId> Parsec<T, S> {

// Detect if the event carries an `Observation::Genesis` that doesn't match what we'd expect.
fn detect_incorrect_genesis(&mut self, event: &Event<S::PublicId>) -> Result<()> {
if let Some(Observation::Genesis(ref group)) = self.event_payload(event) {
if let Some(Observation::Genesis { ref group, .. }) = self.event_payload(event) {
if self.genesis_group() == group.iter().collect() {
return Ok(());
}
Expand Down Expand Up @@ -1667,7 +1673,7 @@ impl<T: NetworkEvent, S: SecretId> Parsec<T, S> {
return;
};

let genesis_group = if let Observation::Genesis(ref group) = *payload {
let genesis_group = if let Observation::Genesis { ref group, .. } = *payload {
group
} else {
return;
Expand Down Expand Up @@ -1699,7 +1705,7 @@ impl<T: NetworkEvent, S: SecretId> Parsec<T, S> {
return;
}

if let Some(&Observation::Genesis(_)) = self.event_payload(event) {
if let Some(&Observation::Genesis { .. }) = self.event_payload(event) {
return;
}

Expand Down Expand Up @@ -1966,9 +1972,9 @@ impl<T: NetworkEvent, S: SecretId> Parsec<T, S> {
};

let starting_index = self.peer_list.accomplice_event_checkpoint_by(creator);
for (_, malice) in
self.detect_accomplice_for_our_accusations(event_index, starting_index)?
{
let accusations =
self.detect_accomplice_for_our_accusations(event_index, starting_index)?;
for (_, malice) in accusations {
self.accuse(creator, Malice::Accomplice(event_hash, Box::new(malice)));
}

Expand Down Expand Up @@ -2026,8 +2032,8 @@ impl<T: NetworkEvent, S: SecretId> Parsec<T, S> {
.iter()
.filter_map(|event| {
let observation = self.event_payload(&*event)?;
if let Observation::Genesis(ref gen) = *observation {
Some(gen.iter().collect())
if let Observation::Genesis { ref group, .. } = *observation {
Some(group.iter().collect())
} else {
None
}
Expand Down Expand Up @@ -2157,7 +2163,12 @@ impl<T: NetworkEvent, S: SecretId> TestParsec<T, S> {
genesis_group: &BTreeSet<S::PublicId>,
consensus_mode: ConsensusMode,
) -> Self {
TestParsec(Parsec::from_genesis(our_id, genesis_group, consensus_mode))
TestParsec(Parsec::from_genesis(
our_id,
genesis_group,
vec![],
consensus_mode,
))
}

pub fn from_existing(
Expand Down

0 comments on commit 0ebfb42

Please sign in to comment.