use generic_ec::{Curve, Scalar};
use paillier_zk::rug::{self, Integer};
use paillier_zk::{
group_element_vs_paillier_encryption_in_range as pi_log,
paillier_affine_operation_in_range as pi_aff, paillier_encryption_in_range as pi_enc,
};
use round_based::rounds_router::simple_store::RoundMsgs;
use round_based::{MsgId, PartyIndex};
use crate::security_level::SecurityLevel;
pub use paillier_zk::fast_paillier::utils::external_rand;
pub fn scalar_to_bignumber<E: Curve>(scalar: impl AsRef<Scalar<E>>) -> Integer {
Integer::from_digits(&scalar.as_ref().to_be_bytes(), rug::integer::Order::Msf)
}
pub struct SecurityParams {
pub pi_aff: pi_aff::SecurityParams,
pub pi_log: pi_log::SecurityParams,
pub pi_enc: pi_enc::SecurityParams,
}
impl SecurityParams {
pub fn new<L: SecurityLevel>() -> Self {
Self {
pi_aff: pi_aff::SecurityParams {
l_x: L::ELL,
l_y: L::ELL_PRIME,
epsilon: L::EPSILON,
q: L::q(),
},
pi_log: pi_log::SecurityParams {
l: L::ELL,
epsilon: L::EPSILON,
q: L::q(),
},
pi_enc: pi_enc::SecurityParams {
l: L::ELL,
epsilon: L::EPSILON,
q: L::q(),
},
}
}
}
pub fn xor_array<A, B>(mut a: A, b: B) -> A
where
A: AsMut<[u8]>,
B: AsRef<[u8]>,
{
a.as_mut()
.iter_mut()
.zip(b.as_ref())
.for_each(|(a_i, b_i)| *a_i ^= *b_i);
a
}
#[derive(Debug)]
#[allow(dead_code)] pub struct AbortBlame {
pub faulty_party: PartyIndex,
pub data_message: MsgId,
pub proof_message: MsgId,
}
impl AbortBlame {
pub fn new(faulty_party: PartyIndex, data_message: MsgId, proof_message: MsgId) -> Self {
Self {
faulty_party,
data_message,
proof_message,
}
}
}
pub fn collect_blame<D, P, F>(
data_messages: &RoundMsgs<D>,
proof_messages: &RoundMsgs<P>,
mut filter: F,
) -> Vec<AbortBlame>
where
F: FnMut(PartyIndex, &D, &P) -> bool,
{
data_messages
.iter_indexed()
.zip(proof_messages.iter_indexed())
.filter_map(|((j, data_msg_id, data), (_, proof_msg_id, proof))| {
if filter(j, data, proof) {
Some(AbortBlame::new(j, data_msg_id, proof_msg_id))
} else {
None
}
})
.collect()
}
pub fn collect_simple_blame<D, F>(messages: &RoundMsgs<D>, mut filter: F) -> Vec<AbortBlame>
where
F: FnMut(&D) -> bool,
{
messages
.iter_indexed()
.filter_map(|(j, msg_id, data)| {
if filter(data) {
Some(AbortBlame::new(j, msg_id, msg_id))
} else {
None
}
})
.collect()
}
pub fn try_collect_blame<E, D, P, F>(
data_messages: &RoundMsgs<D>,
proof_messages: &RoundMsgs<P>,
mut filter: F,
) -> Result<Vec<AbortBlame>, E>
where
F: FnMut(PartyIndex, &D, &P) -> Result<bool, E>,
{
let mut r = Vec::new();
for ((j, data_msg_id, data), (_, proof_msg_id, proof)) in data_messages
.iter_indexed()
.zip(proof_messages.iter_indexed())
{
if filter(j, data, proof)? {
r.push(AbortBlame::new(j, data_msg_id, proof_msg_id));
}
}
Ok(r)
}
pub fn iter_peers(i: u16, n: u16) -> impl Iterator<Item = u16> {
(0..n).filter(move |x| *x != i)
}
pub fn but_nth<T, I: IntoIterator<Item = T>>(n: u16, iter: I) -> impl Iterator<Item = T> {
iter.into_iter()
.enumerate()
.filter(move |(i, _)| *i != usize::from(n))
.map(|(_, x)| x)
}
pub fn sqrt(x: &Integer) -> Integer {
if x.cmp0().is_le() {
Integer::ONE.clone()
} else {
x.sqrt_ref().into()
}
}
pub fn partition_results<I, A, B>(iter: I) -> (Vec<A>, Vec<B>)
where
I: Iterator<Item = Result<A, B>>,
{
let mut oks = Vec::new();
let mut errs = Vec::new();
for i in iter {
match i {
Ok(ok) => oks.push(ok),
Err(err) => errs.push(err),
}
}
(oks, errs)
}
pub fn subset<T: Clone, I: Into<usize> + Copy>(indexes: &[I], list: &[T]) -> Option<Vec<T>> {
indexes
.iter()
.map(|&i| list.get(i.into()).cloned())
.collect()
}
#[cfg(test)]
pub fn generate_blum_prime(rng: &mut impl rand_core::RngCore, bits_size: u32) -> Integer {
loop {
let mut n: Integer = Integer::random_bits(bits_size, &mut external_rand(rng)).into();
n.set_bit(bits_size - 1, true);
n.next_prime_mut();
if n.mod_u(4) == 3 {
break n;
}
}
}
pub mod encoding {
use paillier_zk::rug;
pub struct Integer;
impl udigest::DigestAs<rug::Integer> for Integer {
fn digest_as<B: udigest::Buffer>(
x: &rug::Integer,
encoder: udigest::encoding::EncodeValue<B>,
) {
encoder.encode_leaf_value(x.to_digits(rug::integer::Order::Msf))
}
}
}
#[cfg(test)]
mod test {
use paillier_zk::rug::Complete;
#[test]
fn test_sqrt() {
use super::{sqrt, Integer};
assert_eq!(sqrt(&Integer::from(-5)), Integer::from(1));
assert_eq!(sqrt(&Integer::from(1)), Integer::from(1));
assert_eq!(sqrt(&Integer::from(2)), Integer::from(1));
assert_eq!(sqrt(&Integer::from(3)), Integer::from(1));
assert_eq!(sqrt(&Integer::from(4)), Integer::from(2));
assert_eq!(sqrt(&Integer::from(5)), Integer::from(2));
assert_eq!(sqrt(&Integer::from(6)), Integer::from(2));
assert_eq!(sqrt(&Integer::from(7)), Integer::from(2));
assert_eq!(sqrt(&Integer::from(8)), Integer::from(2));
assert_eq!(sqrt(&Integer::from(9)), Integer::from(3));
assert_eq!(sqrt(&(Integer::from(1) << 1024)), Integer::from(1) << 512);
let modulo = (Integer::ONE << 1024_u32).complete();
let mut rng = rand_dev::DevRng::new();
for _ in 0..100 {
let x = modulo
.random_below_ref(&mut super::external_rand(&mut rng))
.into();
let root = sqrt(&x);
assert!(root.square_ref().complete() <= x);
let root = root + 1u8;
assert!(root.square_ref().complete() > x);
}
}
}