use crate::types::{Address, Frame, Id, RatmanError, Recipient};
use serde::{Deserialize, Serialize};
use std::hash::{BuildHasher, Hasher};
use twox_hash::{RandomXxHashBuilder64 as RXHash64, XxHash64};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct XxSignature {
pub sig: u64,
pub seed: u64,
}
impl XxSignature {
fn new(data: &Vec<u8>) -> Self {
let mut hasher = RXHash64::default().build_hasher();
hasher.write(data);
Self {
sig: hasher.finish(),
seed: hasher.seed(),
}
}
fn verify(&self, data: &Vec<u8>) -> bool {
let mut hasher = XxHash64::with_seed(self.seed);
hasher.write(data);
hasher.finish() == self.sig
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct SeqData {
pub num: u32,
pub sig: XxSignature,
pub seqid: Id,
pub next: Option<u64>,
}
pub struct SeqBuilder {
#[doc(hidden)]
pub seqid: Id,
#[doc(hidden)]
pub sender: Address,
#[doc(hidden)]
pub recp: Recipient,
#[doc(hidden)]
pub data: Vec<Vec<u8>>,
}
impl SeqBuilder {
pub fn new(sender: Address, recp: Recipient, seqid: Id) -> Self {
Self {
sender,
recp,
seqid,
data: vec![],
}
}
pub fn add(mut self, data: Vec<u8>) -> Self {
self.data.push(data);
self
}
pub fn build(self) -> Vec<Frame> {
let seqid = self.seqid;
let sender = self.sender;
let recipient = self.recp;
let signed = self
.data
.into_iter()
.map(|d| (XxSignature::new(&d), d))
.collect::<Vec<_>>();
(0..signed.len())
.enumerate()
.map(|(num, i)| match (signed.get(i), signed.get(i + 1)) {
(
Some((ref sig, data)),
Some((
XxSignature {
sig: ref next,
seed: _,
},
_,
)),
) => (
SeqData {
num: num as u32,
seqid,
sig: *sig,
next: Some(*next),
},
data,
),
(Some((ref sig, data)), None) => (
SeqData {
num: num as u32,
seqid,
sig: *sig,
next: None,
},
data,
),
_ => unreachable!(),
})
.map(|(seq, data)| Frame {
sender,
recipient: recipient.clone(),
seq,
payload: data.to_vec(),
})
.collect()
}
pub fn restore(buf: &mut Vec<Frame>) -> Result<Vec<u8>, RatmanError> {
let fake = if buf.len() == 1 {
buf.push(buf.get(0).unwrap().clone());
true
} else {
false
};
let wins = buf.windows(2);
let len = wins.len();
wins.enumerate()
.into_iter()
.fold(Ok(Vec::with_capacity(buf.len())), |mut res, (i, win)| {
let last = i == (len - 1);
let a = &win[0];
let seqa = &a.seq;
let b = &win[1];
let seqb = &b.seq;
if !seqa.sig.verify(&a.payload) {
res = Err(RatmanError::DesequenceFault);
}
if last && !seqb.sig.verify(&b.payload) {
res = Err(RatmanError::DesequenceFault);
}
fn append(vec: &mut Vec<u8>, other: &Vec<u8>) {
let mut f = other.clone();
vec.append(&mut f);
}
match (res, last) {
(Ok(mut vec), false) => {
append(&mut vec, &a.payload);
Ok(vec)
}
(Ok(mut vec), true) => {
append(&mut vec, &a.payload);
if !fake {
append(&mut vec, &b.payload);
}
Ok(vec)
}
_ => Err(RatmanError::DesequenceFault),
}
})
}
pub fn seqid(&self) -> &Id {
&self.seqid
}
pub fn sender(&self) -> Address {
self.sender
}
pub fn recp(&self) -> Recipient {
self.recp.clone()
}
pub fn data(&self) -> Vec<u8> {
self.data.get(0).unwrap().clone()
}
}
#[cfg(test)]
fn setup() -> Vec<Frame> {
let sender = Address::expand_input(&vec![1]);
let recp = Address::expand_input(&vec![2]);
SeqBuilder::new(sender, Recipient::Standard(vec![recp]), Id::random())
.add(vec![42])
.add(vec![13, 12])
.add(vec![13, 37])
.build()
}
#[test]
fn simple() {
let seq = setup();
assert!(seq.len() == 3);
assert!(seq.get(0).unwrap().seq.next == Some(seq.get(1).unwrap().seq.sig.sig));
}
#[test]
fn seq_num() {
let seq = setup();
assert_eq!(seq[0].seq.num, 0);
assert_eq!(seq[1].seq.num, 1);
assert_eq!(seq[2].seq.num, 2);
}
#[test]
fn hash_seq() {
let seq = setup();
assert_eq!(seq[0].seq.next, Some(seq[1].seq.sig.sig));
assert_eq!(seq[1].seq.next, Some(seq[2].seq.sig.sig));
assert_eq!(seq[2].seq.next, None);
}