zeropool-tx 0.1.1

ZeroPool transaction format
Documentation
use std::io::{Error, ErrorKind, Read, Result, Write};

use byteorder::ByteOrder;
use fawkes_crypto::{
    backend::bellman_groth16::{
        engines::Engine,
        group::{G1Point, G2Point},
        prover::Proof,
    },
    ff_uint::{Num, NumRepr, PrimeField, Uint},
};

#[derive(Eq, PartialEq)]
pub enum Endianness {
    Little,
    Big,
}

pub trait ByteOrderExt: ByteOrder {
    const ENDIANNESS: Endianness;
}

impl ByteOrderExt for byteorder::LittleEndian {
    const ENDIANNESS: Endianness = Endianness::Little;
}

impl ByteOrderExt for byteorder::BigEndian {
    const ENDIANNESS: Endianness = Endianness::Big;
}

pub fn read_num<O: ByteOrderExt, R: Read, P: PrimeField>(r: &mut R) -> Result<Num<P>> {
    let mut bytes = [0u8; 32];
    r.read_exact(&mut bytes)?;

    let uint = if O::ENDIANNESS == Endianness::Little {
        P::Inner::from_little_endian(&bytes)
    } else {
        P::Inner::from_big_endian(&bytes)
    };

    Num::from_uint(NumRepr(uint))
        .ok_or_else(|| Error::new(ErrorKind::InvalidData, "invalid field element"))
}

pub fn read_proof<O: ByteOrderExt, R: Read, E: Engine>(r: &mut R) -> Result<Proof<E>> {
    let a = G1Point(read_num::<O, _, E::Fq>(r)?, read_num::<O, _, E::Fq>(r)?);
    let b = G2Point(
        (read_num::<O, _, E::Fq>(r)?, read_num::<O, _, E::Fq>(r)?),
        (read_num::<O, _, E::Fq>(r)?, read_num::<O, _, E::Fq>(r)?),
    );
    let c = G1Point(read_num::<O, _, E::Fq>(r)?, read_num::<O, _, E::Fq>(r)?);

    Ok(Proof { a, b, c })
}

pub fn write_num<O: ByteOrderExt, W: Write, P: PrimeField>(
    buf: &mut W,
    num: &Num<P>,
) -> Result<()> {
    let mut bytes = [0u8; 32];
    let uint = num.to_uint().0;

    if O::ENDIANNESS == Endianness::Little {
        uint.put_little_endian(&mut bytes);
    } else {
        uint.put_big_endian(&mut bytes);
    }

    buf.write_all(&bytes)
}

pub fn write_proof<O: ByteOrderExt, W: Write, E: Engine>(
    buf: &mut W,
    proof: &Proof<E>,
) -> Result<()> {
    let mut bytes = [0u8; 32 * 8];

    {
        let w = &mut &mut bytes[..];
        write_num::<O, _, E::Fq>(w, &proof.a.0)?;
        write_num::<O, _, E::Fq>(w, &proof.a.1)?;

        write_num::<O, _, E::Fq>(w, &proof.b.0 .0)?;
        write_num::<O, _, E::Fq>(w, &proof.b.0 .1)?;
        write_num::<O, _, E::Fq>(w, &proof.b.1 .0)?;
        write_num::<O, _, E::Fq>(w, &proof.b.1 .1)?;

        write_num::<O, _, E::Fq>(w, &proof.c.0)?;
        write_num::<O, _, E::Fq>(w, &proof.c.1)?;
    }

    buf.write_all(&bytes)
}