use super::Core;
use crate::{
messages::{MessageStatus, SrcAuthorityUtils},
section::{SectionAuthorityProviderUtils, SectionUtils},
Result,
};
use sn_messaging::{
node::{
JoinAsRelocatedResponse, JoinResponse, Proposal, RelocatePromise, RoutingMsg, SignedShare,
Variant,
},
DstLocation,
};
use xor_name::XorName;
impl Core {
pub(crate) fn decide_message_status(&self, msg: &RoutingMsg) -> Result<MessageStatus> {
match &msg.variant {
Variant::SectionKnowledge { .. } | Variant::StartConnectivityTest(_) => {
if !self.is_elder() {
return Ok(MessageStatus::Useless);
}
}
Variant::UserMessage(_) => {
if !self.is_elder() && msg.dst != DstLocation::Node(self.node.name()) {
return Ok(MessageStatus::Useless);
}
}
Variant::JoinRequest(req) => {
if !self.is_elder() && req.section_key == *self.section.chain().last_key() {
return Ok(MessageStatus::Useless);
}
}
Variant::JoinAsRelocatedRequest(req) => {
if !self.is_elder() && req.section_key == *self.section.chain().last_key() {
return Ok(MessageStatus::Useless);
}
}
Variant::DkgStart {
elder_candidates, ..
} => {
if !elder_candidates.elders.contains_key(&self.node.name()) {
return Ok(MessageStatus::Useless);
}
}
Variant::JoinResponse(resp) => match **resp {
JoinResponse::Approval { .. }
| JoinResponse::Retry(_)
| JoinResponse::Redirect(_)
| JoinResponse::Rejected(_) => {
return Ok(MessageStatus::Useful);
}
JoinResponse::ResourceChallenge { .. } => {}
},
Variant::JoinAsRelocatedResponse(resp) => match **resp {
JoinAsRelocatedResponse::Approval { .. }
| JoinAsRelocatedResponse::Retry(_)
| JoinAsRelocatedResponse::Redirect(_)
| JoinAsRelocatedResponse::NodeNotReachable(_) => {
return Ok(MessageStatus::Useful);
}
},
Variant::Sync { section, .. } => {
if !section.prefix().matches(&self.node.name()) {
return Ok(MessageStatus::Useless);
}
}
Variant::Propose {
content,
signed_share,
..
} => {
if let Some(status) =
self.decide_propose_status(&msg.src.name(), content, signed_share)
{
return Ok(status);
}
}
Variant::RelocatePromise(promise) => {
if let Some(status) = self.decide_relocate_promise_status(promise) {
return Ok(status);
}
}
Variant::Relocate(_)
| Variant::BouncedUntrustedMessage { .. }
| Variant::DkgMessage { .. }
| Variant::DkgFailureObservation { .. }
| Variant::DkgFailureAgreement { .. }
| Variant::SectionKnowledgeQuery { .. } => {}
}
if self.verify_message(msg)? {
Ok(MessageStatus::Useful)
} else {
Ok(MessageStatus::Untrusted)
}
}
pub(crate) fn decide_propose_status(
&self,
sender: &XorName,
proposal: &Proposal,
signed_share: &SignedShare,
) -> Option<MessageStatus> {
match proposal {
Proposal::SectionInfo(section_auth)
if section_auth.prefix == *self.section.prefix()
|| section_auth.prefix.is_extension_of(self.section.prefix()) =>
{
if section_auth.contains_elder(sender) {
None
} else {
Some(MessageStatus::Useless)
}
}
_ => {
if self
.section
.chain()
.has_key(&signed_share.public_key_set.public_key())
{
None
} else {
Some(MessageStatus::Untrusted)
}
}
}
}
pub(crate) fn decide_relocate_promise_status(
&self,
promise: &RelocatePromise,
) -> Option<MessageStatus> {
if promise.name == self.node.name() {
if self.relocate_state.is_some() {
return Some(MessageStatus::Useless);
}
} else {
if !self.is_elder() || self.section.is_elder(&promise.name) {
return Some(MessageStatus::Useless);
}
}
None
}
}