use crate::{Error, Frame, Recipient};
use identity::Identity;
use {
std::hash::{BuildHasher, Hasher},
twox_hash::{RandomXxHashBuilder64 as RXHash64, XxHash64},
};
pub type SeqId = Identity;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct XxSignature {
sig: u64,
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: SeqId,
pub next: Option<u64>,
}
pub struct SeqBuilder {
#[doc(hidden)]
pub seqid: SeqId,
#[doc(hidden)]
pub sender: Identity,
#[doc(hidden)]
pub recp: Recipient,
#[doc(hidden)]
pub data: Vec<Vec<u8>>,
}
impl SeqBuilder {
pub fn new(sender: Identity, recp: Recipient, seqid: SeqId) -> 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,
seq,
payload: data.to_vec(),
})
.collect()
}
pub fn restore(buf: &mut Vec<Frame>) -> Vec<u8> {
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();
let r: Result<Vec<u8>, Error> = 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(Error::DesequenceFault);
}
if last && !seqb.sig.verify(&b.payload) {
res = Err(Error::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(Error::DesequenceFault),
}
},
);
r.expect("SeqBuilder::restore failed with invalid inputs!")
}
pub fn seqid(&self) -> &SeqId {
&self.seqid
}
pub fn sender(&self) -> Identity {
self.sender
}
pub fn recp(&self) -> Recipient {
self.recp
}
pub fn data(&self) -> Vec<u8> {
self.data.get(0).unwrap().clone()
}
}
#[cfg(test)]
fn setup() -> Vec<Frame> {
let sender = Identity::with_digest(&vec![1]);
let recp = Identity::with_digest(&vec![2]);
SeqBuilder::new(sender, Recipient::User(recp), Identity::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);
}