Skip to content
This repository has been archived by the owner on Jun 25, 2021. It is now read-only.

Remove version and prefix from SectionProofChain #2091

Merged
merged 11 commits into from May 11, 2020
6 changes: 2 additions & 4 deletions src/consensus/event_accumulator.rs
Expand Up @@ -279,7 +279,7 @@ mod test {
consensus::generate_bls_threshold_secret_key,
id::FullId,
rng::{self, MainRng},
section::{EldersInfo, SectionKeyInfo},
section::EldersInfo,
unwrap,
};
use parsec::SecretId;
Expand Down Expand Up @@ -354,9 +354,7 @@ mod test {
EventType::WithSignature => {
let elders_info = empty_elders_info();
let (sig_payload, keys) = random_section_info_sig_payload(rng);
let key_info =
SectionKeyInfo::new(elders_info.prefix, elders_info.version, keys.public_key());
let event = AccumulatingEvent::SectionInfo(elders_info, key_info);
let event = AccumulatingEvent::SectionInfo(elders_info, keys.public_key());

TestData {
our_id: *id.public_id(),
Expand Down
2 changes: 1 addition & 1 deletion src/consensus/mod.rs
Expand Up @@ -191,7 +191,7 @@ impl ConsensusEngine {
| AccumulatingEvent::Online(_)
| AccumulatingEvent::Offline(_)
| AccumulatingEvent::NeighbourInfo(_)
| AccumulatingEvent::TheirKeyInfo(_)
| AccumulatingEvent::TheirKeyInfo { .. }
| AccumulatingEvent::AckMessage(_)
| AccumulatingEvent::ParsecPrune
| AccumulatingEvent::Relocate(_)
Expand Down
40 changes: 22 additions & 18 deletions src/consensus/network_event.rs
Expand Up @@ -8,10 +8,9 @@

use crate::{
consensus::{DkgResultWrapper, Observation, ParsecNetworkEvent},
error::RoutingError,
id::{P2pNode, PublicId},
relocation::RelocateDetails,
section::{EldersInfo, SectionKeyInfo, SectionMap},
section::{EldersInfo, SectionMap},
Prefix, XorName,
};
use hex_fmt::HexFmt;
Expand All @@ -29,16 +28,16 @@ pub struct AckMessagePayload {
pub dst_name: XorName,
/// The prefix of our section when we acknowledge their SectionInfo of version ack_version.
pub src_prefix: Prefix<XorName>,
/// The version acknowledged.
pub ack_version: u64,
/// The key acknowledged.
pub ack_key: bls::PublicKey,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub struct SendAckMessagePayload {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this whole Ack approach can be deleted here actually. Perhaps when the pull mechanism in place would be more correct. Happy to waiton that PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that will be part of the pull model.

/// The prefix acknowledged.
pub ack_prefix: Prefix<XorName>,
/// The version acknowledged.
pub ack_version: u64,
/// The key acknowledged.
pub ack_key: bls::PublicKey,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
Expand All @@ -50,17 +49,15 @@ pub struct EventSigPayload {
}

impl EventSigPayload {
pub fn new_for_section_key_info(
key_share: &bls::SecretKeyShare,
section_key_info: &SectionKeyInfo,
) -> Result<Self, RoutingError> {
let sig_share = key_share.sign(&section_key_info.serialise_for_signature()?);
#[cfg_attr(feature = "mock_base", allow(clippy::trivially_copy_pass_by_ref))]
pub fn new(key_share: &bls::SecretKeyShare, section_key: &bls::PublicKey) -> Self {
let sig_share = key_share.sign(&section_key.to_bytes()[..]);
let pub_key_share = key_share.public_key_share();

Ok(Self {
Self {
pub_key_share,
sig_share,
})
}
}
}

Expand All @@ -70,8 +67,8 @@ pub struct OnlinePayload {
pub p2p_node: P2pNode,
// The age the node should have after joining.
pub age: u8,
// The version of the destination section that the joining node knows, if any.
pub their_knowledge: Option<u64>,
// The key of the destination section that the joining node knows, if any.
pub their_knowledge: Option<bls::PublicKey>,
}

/// Routing Network events
Expand Down Expand Up @@ -99,13 +96,16 @@ pub enum AccumulatingEvent {
/// Voted for node we no longer consider online.
Offline(PublicId),

SectionInfo(EldersInfo, SectionKeyInfo),
SectionInfo(EldersInfo, bls::PublicKey),

// Voted for received message with info to update neighbour_info.
NeighbourInfo(EldersInfo),

// Voted for received message with keys to update their_keys
TheirKeyInfo(SectionKeyInfo),
TheirKeyInfo {
prefix: Prefix<XorName>,
key: bls::PublicKey,
},

// Voted for received AckMessage to update their_knowledge
AckMessage(AckMessagePayload),
Expand Down Expand Up @@ -168,7 +168,11 @@ impl Debug for AccumulatingEvent {
Self::Offline(id) => write!(formatter, "Offline({})", id),
Self::SectionInfo(info, _) => write!(formatter, "SectionInfo({:?})", info),
Self::NeighbourInfo(info) => write!(formatter, "NeighbourInfo({:?})", info),
Self::TheirKeyInfo(payload) => write!(formatter, "TheirKeyInfo({:?})", payload),
Self::TheirKeyInfo { prefix, key } => write!(
formatter,
"TheirKeyInfo {{ prefix: {:?}, key: {:?} }}",
prefix, key
),
Self::AckMessage(payload) => write!(formatter, "AckMessage({:?})", payload),
Self::SendAckMessage(payload) => write!(formatter, "SendAckMessage({:?})", payload),
Self::ParsecPrune => write!(formatter, "ParsecPrune"),
Expand Down
4 changes: 1 addition & 3 deletions src/lib.rs
Expand Up @@ -111,9 +111,7 @@ pub use self::{
network_params::NetworkParams,
relocation::Overrides as RelocationOverrides,
routing_table::delivery_group_size,
section::{
quorum_count, EldersInfo, SectionKeyInfo, SectionKeyShare, SectionProofChain, MIN_AGE,
},
section::{quorum_count, EldersInfo, SectionKeyShare, SectionProofChain, MIN_AGE},
xor_space::Xorable,
};

Expand Down
32 changes: 12 additions & 20 deletions src/messages/accumulating_message.rs
Expand Up @@ -168,24 +168,23 @@ mod tests {
consensus::generate_bls_threshold_secret_key,
messages::VerifyStatus,
rng::{self, MainRng},
section::SectionKeyInfo,
unwrap, Prefix,
};
use rand::{self, Rng};
use std::{collections::BTreeMap, iter};
use std::iter;

#[test]
fn combine_signatures() {
let mut rng = rng::new();
let sk_set = generate_bls_threshold_secret_key(&mut rng, 4);
let pk_set = sk_set.public_keys();
let pk = pk_set.public_key();

let sk_share_0 = SectionKeyShare::new_with_position(0, sk_set.secret_key_share(0));
let sk_share_1 = SectionKeyShare::new_with_position(1, sk_set.secret_key_share(1));

let content = gen_message(&mut rng);
let proof = make_proof_chain(&pk_set);
let their_key_infos = make_their_key_infos(&pk_set);

let mut msg_0 = unwrap!(AccumulatingMessage::new(
content.clone(),
Expand All @@ -205,22 +204,25 @@ mod tests {
assert!(msg_0.check_fully_signed());

let msg = unwrap!(msg_0.combine_signatures());
assert_eq!(unwrap!(msg.verify(&their_key_infos)), VerifyStatus::Full);
assert_eq!(
unwrap!(msg.verify(iter::once((&Prefix::default(), &pk)))),
VerifyStatus::Full
);
}

#[test]
fn invalid_signatures() {
let mut rng = rng::new();
let sk_set = generate_bls_threshold_secret_key(&mut rng, 4);
let pk_set = sk_set.public_keys();
let pk = pk_set.public_key();

let sk_share_0 = SectionKeyShare::new_with_position(0, sk_set.secret_key_share(0));
let sk_share_1 = SectionKeyShare::new_with_position(1, sk_set.secret_key_share(1));
let sk_share_2 = SectionKeyShare::new_with_position(2, sk_set.secret_key_share(2));

let content = gen_message(&mut rng);
let proof = make_proof_chain(&pk_set);
let their_key_infos = make_their_key_infos(&pk_set);

// Message with valid signature
let mut msg_0 = unwrap!(AccumulatingMessage::new(
Expand Down Expand Up @@ -258,24 +260,14 @@ mod tests {
assert!(msg_0.check_fully_signed());

let msg = unwrap!(msg_0.combine_signatures());
assert_eq!(unwrap!(msg.verify(&their_key_infos)), VerifyStatus::Full);
}

fn make_section_key_info(pk_set: &bls::PublicKeySet) -> SectionKeyInfo {
let prefix = Prefix::default();
let version = 0u64;
SectionKeyInfo::new(prefix, version, pk_set.public_key())
assert_eq!(
unwrap!(msg.verify(iter::once((&Prefix::default(), &pk)))),
VerifyStatus::Full
);
}

fn make_proof_chain(pk_set: &bls::PublicKeySet) -> SectionProofChain {
SectionProofChain::new(make_section_key_info(pk_set))
}

fn make_their_key_infos(
pk_set: &bls::PublicKeySet,
) -> BTreeMap<Prefix<XorName>, SectionKeyInfo> {
let key_info = make_section_key_info(pk_set);
iter::once((key_info.prefix, key_info)).collect()
SectionProofChain::new(pk_set.public_key())
}

fn gen_message(rng: &mut MainRng) -> PlainMessage {
Expand Down
29 changes: 15 additions & 14 deletions src/messages/mod.rs
Expand Up @@ -23,7 +23,6 @@ use crate::{
error::{Result, RoutingError},
id::{FullId, PublicId},
location::DstLocation,
section::SectionKeyInfo,
xor_space::{Prefix, XorName},
};
use bytes::Bytes;
Expand Down Expand Up @@ -85,18 +84,19 @@ impl Message {
}

/// Verify this message is properly signed and trusted.
pub(crate) fn verify<'a, I>(&'a self, their_key_infos: I) -> Result<VerifyStatus>
pub(crate) fn verify<'a, I>(&'a self, their_keys: I) -> Result<VerifyStatus>
where
I: IntoIterator<Item = (&'a Prefix<XorName>, &'a SectionKeyInfo)>,
I: IntoIterator<Item = (&'a Prefix<XorName>, &'a bls::PublicKey)>,
{
self.src.verify(&self.dst, &self.variant, their_key_infos)
self.src.verify(&self.dst, &self.variant, their_keys)
}

/// Returns the latest section key from the message proof.
pub fn source_section_key_info(&self) -> Option<&SectionKeyInfo> {
/// If this message is from a section, returns its prefix and the latest section key from the
/// message proof. Otherwise `None`.
pub fn source_section_key_info(&self) -> Option<(&Prefix<XorName>, &bls::PublicKey)> {
match &self.src {
SrcAuthority::Node { .. } => None,
SrcAuthority::Section { proof, .. } => Some(proof.last_key_info()),
SrcAuthority::Section { prefix, proof, .. } => Some((prefix, proof.last_key())),
}
}

Expand Down Expand Up @@ -127,16 +127,17 @@ impl Debug for Message {
pub enum VerifyStatus {
// The message has been fully verified.
Full,
// The message trust and integrity cannot be verified because it's proof is too new. It should
// be relayed to other nodes who might be able to verify it.
ProofTooNew,
// The message trust and integrity cannot be verified because it's proof is not trusted by us,
// even though it is valid. The message should be relayed to other nodes who might be able to
// verify it.
Unknown,
}

impl VerifyStatus {
pub fn require_full(self) -> Result<(), RoutingError> {
match self {
Self::Full => Ok(()),
Self::ProofTooNew => Err(RoutingError::UntrustedMessage),
Self::Unknown => Err(RoutingError::UntrustedMessage),
}
}
}
Expand All @@ -146,17 +147,17 @@ pub struct QueuedMessage {
pub sender: Option<SocketAddr>,
}

pub fn log_verify_failure<'a, T, I>(msg: &T, error: &RoutingError, their_key_infos: I)
pub fn log_verify_failure<'a, T, I>(msg: &T, error: &RoutingError, their_keys: I)
where
T: Debug,
I: IntoIterator<Item = (&'a Prefix<XorName>, &'a SectionKeyInfo)>,
I: IntoIterator<Item = (&'a Prefix<XorName>, &'a bls::PublicKey)>,
{
log_or_panic!(
log::Level::Error,
"Verification failed: {:?} - {:?} --- [{:?}]",
msg,
error,
their_key_infos.into_iter().format(", ")
their_keys.into_iter().format(", ")
)
}

Expand Down
25 changes: 16 additions & 9 deletions src/messages/src_authority.rs
Expand Up @@ -12,7 +12,7 @@ use crate::{
error::{Result, RoutingError},
id::{P2pNode, PublicId},
location::{DstLocation, SrcLocation},
section::{SectionKeyInfo, SectionProofChain, TrustStatus},
section::{SectionProofChain, TrustStatus},
xor_space::{Prefix, XorName},
};
use std::net::SocketAddr;
Expand Down Expand Up @@ -62,10 +62,10 @@ impl SrcAuthority {
&'a self,
dst: &DstLocation,
variant: &Variant,
their_key_infos: I,
trusted_key_infos: I,
) -> Result<VerifyStatus>
where
I: IntoIterator<Item = (&'a Prefix<XorName>, &'a SectionKeyInfo)>,
I: IntoIterator<Item = (&'a Prefix<XorName>, &'a bls::PublicKey)>,
{
match self {
Self::Node {
Expand All @@ -78,16 +78,23 @@ impl SrcAuthority {
}
}
Self::Section {
signature, proof, ..
prefix,
signature,
proof,
} => {
let public_key = match proof.check_trust(their_key_infos) {
TrustStatus::Trusted(key) => key,
TrustStatus::ProofTooNew => return Ok(VerifyStatus::ProofTooNew),
TrustStatus::ProofInvalid => return Err(RoutingError::UntrustedMessage),
let trusted_key_infos = trusted_key_infos
.into_iter()
.filter(|(known_prefix, _)| prefix.is_compatible(known_prefix))
.map(|(_, key_info)| key_info);

match proof.check_trust(trusted_key_infos) {
TrustStatus::Trusted => (),
TrustStatus::Unknown => return Ok(VerifyStatus::Unknown),
TrustStatus::Invalid => return Err(RoutingError::UntrustedMessage),
};

let bytes = super::serialize_for_section_signing(dst, variant)?;
if !public_key.verify(signature, &bytes) {
if !proof.last_key().verify(signature, &bytes) {
return Err(RoutingError::FailedSignature);
}
}
Expand Down