use crate::common::{Address as RewardsAddress, Amount, QuoteHash};
use crate::cryptography::hash as crypto_hash;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::time::SystemTime;
use xor_name::XorName;
#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)]
pub struct EncodedPeerId(#[serde(with = "serde_byte_array")] [u8; 32]);
impl EncodedPeerId {
pub fn new(bytes: [u8; 32]) -> Self {
Self(bytes)
}
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
}
impl fmt::Debug for EncodedPeerId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let hex = hex::encode(self.0);
write!(f, "EncodedPeerId({hex})")
}
}
impl From<[u8; 32]> for EncodedPeerId {
fn from(bytes: [u8; 32]) -> Self {
Self(bytes)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)]
pub struct ProofOfPayment {
pub peer_quotes: Vec<(EncodedPeerId, PaymentQuote)>,
}
impl ProofOfPayment {
pub fn digest(&self) -> Vec<(QuoteHash, Amount, RewardsAddress)> {
self.peer_quotes
.clone()
.into_iter()
.map(|(_, quote)| (quote.hash(), quote.price, quote.rewards_address))
.collect()
}
}
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct PaymentQuote {
pub content: XorName,
pub timestamp: SystemTime,
pub price: Amount,
pub rewards_address: RewardsAddress,
pub pub_key: Vec<u8>,
pub signature: Vec<u8>,
}
impl fmt::Debug for PaymentQuote {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PaymentQuote")
.field("content", &self.content)
.field("timestamp", &self.timestamp)
.field("price", &self.price)
.field("rewards_address", &self.rewards_address)
.finish_non_exhaustive()
}
}
impl PaymentQuote {
pub fn hash(&self) -> QuoteHash {
let mut bytes = self.bytes_for_sig();
bytes.extend_from_slice(self.pub_key.as_slice());
bytes.extend_from_slice(self.signature.as_slice());
crypto_hash(bytes)
}
pub fn bytes_for_signing(
xorname: XorName,
timestamp: SystemTime,
price: &Amount,
rewards_address: &RewardsAddress,
) -> Vec<u8> {
let mut bytes = xorname.to_vec();
let secs = timestamp
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
bytes.extend_from_slice(&secs.to_le_bytes());
bytes.extend_from_slice(&price.to_le_bytes::<32>());
bytes.extend_from_slice(rewards_address.as_slice());
bytes
}
pub fn bytes_for_sig(&self) -> Vec<u8> {
Self::bytes_for_signing(
self.content,
self.timestamp,
&self.price,
&self.rewards_address,
)
}
}
mod serde_byte_array {
use serde::{Deserialize, Deserializer, Serializer};
pub fn serialize<S: Serializer>(bytes: &[u8; 32], serializer: S) -> Result<S::Ok, S::Error> {
serde::Serialize::serialize(&bytes[..], serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<[u8; 32], D::Error> {
let bytes: Vec<u8> = Vec::deserialize(deserializer)?;
bytes.try_into().map_err(|v: Vec<u8>| {
let len = v.len();
serde::de::Error::custom(format!("Expected 32 bytes, got {len}"))
})
}
}