use std::convert::{TryFrom, TryInto};
use multiaddr::Multiaddr;
use serde_derive::{Deserialize, Serialize};
use tari_utilities::ByteArrayError;
use crate::{
peer_manager::{IdentitySignature, PeerFeatures, PeerManagerError},
proto::identity::PeerIdentityMsg,
types::CommsPublicKey,
};
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct PeerIdentityClaim {
pub addresses: Vec<Multiaddr>,
pub features: PeerFeatures,
pub signature: IdentitySignature,
}
impl PeerIdentityClaim {
pub fn new(addresses: Vec<Multiaddr>, features: PeerFeatures, signature: IdentitySignature) -> Self {
Self {
addresses,
features,
signature,
}
}
pub fn is_valid(&self, public_key: &CommsPublicKey) -> Result<bool, ByteArrayError> {
self.signature.is_valid(public_key, self.features, &self.addresses)
}
}
impl TryFrom<PeerIdentityMsg> for PeerIdentityClaim {
type Error = PeerManagerError;
fn try_from(value: PeerIdentityMsg) -> Result<Self, Self::Error> {
let addresses = value
.addresses
.into_iter()
.map(Multiaddr::try_from)
.collect::<Result<Vec<_>, _>>()
.map_err(|e| PeerManagerError::MultiaddrError(e.to_string()))?;
if addresses.is_empty() {
return Err(PeerManagerError::PeerIdentityNoValidAddresses);
}
let features = PeerFeatures::from_bits(value.features).ok_or(PeerManagerError::ProtocolError(format!(
"Invalid message flag, does not match any flags ({})",
value.features
)))?;
if let Some(signature) = value.identity_signature {
Ok(Self {
addresses,
features,
signature: signature.try_into()?,
})
} else {
Err(PeerManagerError::MissingIdentitySignature)
}
}
}