use crate::{
error::Error,
id::{Proof, PublicId, SecretId},
network_event::NetworkEvent,
observation::{ConsensusMode, Observation, ObservationHash, ObservationKey, ObservationStore},
peer_list::PeerIndex,
serialise,
};
use serde::de::DeserializeOwned;
use std::fmt::{self, Debug, Formatter};
#[serde(bound(deserialize = "T: DeserializeOwned"))]
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Vote<T: NetworkEvent, P: PublicId> {
payload: Observation<T, P>,
signature: P::Signature,
}
impl<T: NetworkEvent, P: PublicId> Vote<T, P> {
pub fn new<S: SecretId<PublicId = P>>(secret_id: &S, payload: Observation<T, P>) -> Self {
let signature = secret_id.sign_detached(&serialise(&payload));
Self { payload, signature }
}
pub fn payload(&self) -> &Observation<T, P> {
&self.payload
}
pub fn signature(&self) -> &P::Signature {
&self.signature
}
pub fn is_valid(&self, public_id: &P) -> bool {
public_id.verify_signature(&self.signature, &serialise(&self.payload))
}
pub fn create_proof(&self, public_id: &P) -> Result<Proof<P>, Error> {
if self.is_valid(public_id) {
return Ok(Proof {
public_id: public_id.clone(),
signature: self.signature.clone(),
});
}
Err(Error::SignatureFailure)
}
}
impl<T: NetworkEvent, P: PublicId> Debug for Vote<T, P> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?}", self.payload)
}
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
pub(crate) struct VoteKey<P: PublicId> {
payload_key: ObservationKey,
signature: P::Signature,
}
impl<P: PublicId> VoteKey<P> {
pub fn new<T: NetworkEvent>(
vote: Vote<T, P>,
creator: PeerIndex,
consensus_mode: ConsensusMode,
) -> (Self, Observation<T, P>) {
let consensus_mode = consensus_mode.of(&vote.payload);
let hash = ObservationHash::from(&vote.payload);
let payload_key = ObservationKey::new(hash, creator, consensus_mode);
let vote_key = Self {
payload_key,
signature: vote.signature,
};
(vote_key, vote.payload)
}
pub fn resolve<T: NetworkEvent>(
&self,
observations: &ObservationStore<T, P>,
) -> Result<Vote<T, P>, Error> {
Ok(Vote {
payload: observations
.get(&self.payload_key)
.map(|info| info.observation.clone())
.ok_or(Error::UnknownPayload)?,
signature: self.signature.clone(),
})
}
pub fn payload_key(&self) -> &ObservationKey {
&self.payload_key
}
}
impl<P: PublicId> Debug for VoteKey<P> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:?}", self.payload_key)
}
}