use core::borrow::{Borrow, BorrowMut};
use core::iter::once;
use ark_ec::Group;
use ark_ff::Zero;
use super::single::SignedMessage;
use super::verifiers::verify_with_distinct_messages;
use super::*;
fn slice_eq_bytewise<T: PartialEq<T>>(x: &[T], y: &[T]) -> bool {
if x.len() != y.len() {
return false;
}
if ::core::ptr::eq(x, y) {
return true;
}
x == y
}
pub trait SignerTable<E: EngineBLS> {
fn agreement(&self, other: &Self) -> bool;
type Signers: Borrow<[u8]> + BorrowMut<[u8]> + Clone + Sized;
fn new_signers(&self) -> Self::Signers;
fn lookup(&self, index: usize) -> Option<PublicKey<E>>;
fn find(&self, publickey: &PublicKey<E>) -> Option<usize>;
}
fn chunk_lookups<E, ST>(signer_table: &ST, offset: usize) -> u8
where
E: EngineBLS,
ST: SignerTable<E>,
{
(0..8).into_iter().fold(0u8, |b, j| {
let i = 8 * offset + j;
let pk = signer_table.lookup(i).filter(|pk| {
let bb = Some(i) == signer_table.find(&pk);
debug_assert!(
bb,
"Incorrect SignerTable implementation with duplicate publickeys"
);
bb
});
b | pk.map_or(0u8, |_| 1u8 << j)
})
}
impl<E, V> SignerTable<E> for V
where
E: EngineBLS,
V: ::core::ops::Deref<Target = [PublicKey<E>]>,
{
fn agreement(&self, other: &Self) -> bool {
slice_eq_bytewise(self.deref(), other.deref())
}
type Signers = Box<[u8]>;
fn new_signers(&self) -> Self::Signers {
vec![0u8; (self.deref().len() + 7) / 8].into_boxed_slice()
}
fn lookup(&self, index: usize) -> Option<PublicKey<E>> {
self.deref().get(index).cloned()
}
fn find(&self, publickey: &PublicKey<E>) -> Option<usize> {
self.deref().iter().position(|pk| *pk == *publickey)
}
}
#[derive(Debug)]
pub enum SignerTableError {
BadSignerTable(&'static str),
MismatchedMessage,
RepeatedSigners,
}
impl ::core::fmt::Display for SignerTableError {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
use self::SignerTableError::*;
match self {
BadSignerTable(s) => write!(f, "{}", s),
MismatchedMessage => write!(
f,
"Cannot aggregate distinct messages with only a bit field."
),
RepeatedSigners => write!(f, "Cannot aggregate due to duplicate signers."),
}
}
}
impl ::std::error::Error for SignerTableError {
fn description(&self) -> &str {
use self::SignerTableError::*;
match self {
BadSignerTable(s) => s,
MismatchedMessage => "Cannot aggregate distinct messages with only a bit field.",
RepeatedSigners => "Cannot aggregate due to duplicate signers",
}
}
}
pub struct BitSignedMessage<E: EngineBLS, POP: SignerTable<E>> {
proofs_of_possession: POP,
signers: <POP as SignerTable<E>>::Signers,
message: Message,
signature: Signature<E>,
}
impl<'a, E, POP> Clone for BitSignedMessage<E, POP>
where
E: EngineBLS,
POP: SignerTable<E> + Clone,
{
fn clone(&self) -> BitSignedMessage<E, POP> {
BitSignedMessage {
proofs_of_possession: self.proofs_of_possession.clone(),
signers: self.signers.clone(),
message: self.message.clone(),
signature: self.signature.clone(),
}
}
}
impl<'a, E, POP> Signed for &'a BitSignedMessage<E, POP>
where
E: EngineBLS,
POP: SignerTable<E>,
{
type E = E;
type M = Message;
type PKG = PublicKey<E>;
type PKnM = ::core::iter::Once<(Message, PublicKey<E>)>;
fn messages_and_publickeys(self) -> Self::PKnM {
let mut publickey = E::PublicKeyGroup::zero();
for i in 0..8 * self.signers.borrow().len() {
if self.signers.borrow()[i / 8] & (1 << (i % 8)) != 0 {
let pop_pk = self.proofs_of_possession.lookup(i).unwrap();
if Some(i) != self.proofs_of_possession.find(&pop_pk) {
debug_assert!(
false,
"Incorrect SignerTable implementation with duplicate publickeys"
);
continue;
}
publickey += &pop_pk.0;
}
}
once((self.message.clone(), PublicKey(publickey)))
}
fn signature(&self) -> Signature<E> {
self.signature
}
fn verify(self) -> bool {
verify_with_distinct_messages(self, true)
}
}
impl<E, POP> BitSignedMessage<E, POP>
where
E: EngineBLS,
POP: SignerTable<E>,
{
pub fn new(proofs_of_possession: POP, message: &Message) -> BitSignedMessage<E, POP> {
let signers = proofs_of_possession.new_signers();
let signature = Signature(E::SignatureGroup::zero());
BitSignedMessage {
proofs_of_possession,
signers,
message: message.clone(),
signature,
}
}
fn add_points(
&mut self,
publickey: PublicKey<E>,
signature: Signature<E>,
) -> Result<(), SignerTableError> {
let i =
self.proofs_of_possession
.find(&publickey)
.ok_or(SignerTableError::BadSignerTable(
"Mismatched proof-of-possession",
))?;
if self.proofs_of_possession.lookup(i) != Some(publickey) {
return Err(SignerTableError::BadSignerTable(
"Invalid SignerTable implementation with missmatched lookups",
));
}
let b = 1 << (i % 8);
let s = &mut self.signers.borrow_mut()[i / 8];
if *s & b != 0 {
return Err(SignerTableError::RepeatedSigners);
}
*s |= b;
self.signature.0 += &signature.0;
Ok(())
}
pub fn add(&mut self, signed: &SignedMessage<E>) -> Result<(), SignerTableError> {
if self.message != signed.message {
return Err(SignerTableError::MismatchedMessage);
}
self.add_points(signed.publickey, signed.signature)
}
pub fn merge(&mut self, other: &BitSignedMessage<E, POP>) -> Result<(), SignerTableError> {
if self.message != other.message {
return Err(SignerTableError::MismatchedMessage);
}
if !self
.proofs_of_possession
.agreement(&other.proofs_of_possession)
{
return Err(SignerTableError::BadSignerTable(
"Mismatched proof-of-possession",
));
}
for (offset, (x, y)) in self
.signers
.borrow()
.iter()
.zip(other.signers.borrow())
.enumerate()
{
if *x & *y != 0 {
return Err(SignerTableError::RepeatedSigners);
}
if *y & !chunk_lookups(&self.proofs_of_possession, offset) != 0 {
return Err(SignerTableError::BadSignerTable("Absent signer"));
}
}
for (x, y) in self
.signers
.borrow_mut()
.iter_mut()
.zip(other.signers.borrow())
{
*x |= y;
}
self.signature.0 += &other.signature.0;
Ok(())
}
}
pub struct CountSignedMessage<E: EngineBLS, POP: SignerTable<E>> {
proofs_of_possession: POP,
signers: Vec<<POP as SignerTable<E>>::Signers>,
message: Message,
signature: Signature<E>,
pub max_duplicates: usize,
}
impl<'a, E, POP> Clone for CountSignedMessage<E, POP>
where
E: EngineBLS,
POP: SignerTable<E> + Clone,
{
fn clone(&self) -> CountSignedMessage<E, POP> {
CountSignedMessage {
proofs_of_possession: self.proofs_of_possession.clone(),
signers: self.signers.clone(),
message: self.message.clone(),
signature: self.signature.clone(),
max_duplicates: self.max_duplicates,
}
}
}
impl<'a, E, POP> Signed for &'a CountSignedMessage<E, POP>
where
E: EngineBLS,
POP: SignerTable<E>,
{
type E = E;
type M = Message;
type PKG = PublicKey<E>;
type PKnM = ::core::iter::Once<(Message, PublicKey<E>)>;
fn messages_and_publickeys(self) -> Self::PKnM {
let mut publickey = E::PublicKeyGroup::zero();
for signers in self.signers.iter().rev().map(|signers| signers.borrow()) {
publickey.double_in_place();
for i in 0..8 * signers.len() {
if signers[i / 8] & (1 << (i % 8)) != 0 {
let pop_pk = self.proofs_of_possession.lookup(i).unwrap();
if Some(i) != self.proofs_of_possession.find(&pop_pk) {
debug_assert!(
false,
"Incorrect SignerTable implementation with duplicate publickeys"
);
continue;
}
publickey += &pop_pk.0;
}
}
}
once((self.message.clone(), PublicKey(publickey)))
}
fn signature(&self) -> Signature<E> {
self.signature
}
fn verify(self) -> bool {
verify_with_distinct_messages(self, true)
}
}
impl<E, POP> CountSignedMessage<E, POP>
where
E: EngineBLS,
POP: SignerTable<E>,
{
pub fn new(proofs_of_possession: POP, message: Message) -> CountSignedMessage<E, POP> {
let signers = vec![proofs_of_possession.new_signers(); 1];
let signature = Signature(E::SignatureGroup::zero());
let max_duplicates = 16;
CountSignedMessage {
proofs_of_possession,
signers,
message,
signature,
max_duplicates,
}
}
fn reserve_depth(&mut self, count: usize) {
let l = 0usize.leading_zeros() - count.leading_zeros();
if l as usize <= self.signers.len() {
return;
}
let l = l as usize - self.signers.len();
self.signers.reserve(l);
for _i in 0..l {
self.signers.push(self.proofs_of_possession.new_signers());
}
}
fn test_count(&self, count: usize) -> Result<(), SignerTableError> {
if count >= self.max_duplicates || count >= usize::max_value() {
return Err(SignerTableError::RepeatedSigners);
}
Ok(())
}
fn get_count(&self, index: usize) -> usize {
let mut count = 0;
for signers in self.signers.iter().rev().map(|signers| signers.borrow()) {
count *= 2;
if signers[index / 8] & (1 << (index % 8)) != 0 {
count += 1;
}
}
count
}
fn set_count(&mut self, index: usize, mut count: usize) {
self.reserve_depth(count);
for signers in self.signers.iter_mut().map(|signers| signers.borrow_mut()) {
if count & 1usize != 0 {
signers[index / 8] |= 1 << (index % 8);
} else {
signers[index / 8] &= !(1 << (index % 8));
}
count /= 2;
}
}
fn add_points(
&mut self,
publickey: PublicKey<E>,
signature: Signature<E>,
) -> Result<(), SignerTableError> {
let i =
self.proofs_of_possession
.find(&publickey)
.ok_or(SignerTableError::BadSignerTable(
"Mismatched proof-of-possession",
))?;
if self.proofs_of_possession.lookup(i) != Some(publickey) {
return Err(SignerTableError::BadSignerTable(
"Invalid SignerTable implementation with missmatched lookups",
));
}
let count = self.get_count(i) + 1;
self.test_count(count)?;
self.set_count(i, count);
self.signature.0 += &signature.0;
Ok(())
}
pub fn add(&mut self, signed: &SignedMessage<E>) -> Result<(), SignerTableError> {
if self.message != signed.message {
return Err(SignerTableError::MismatchedMessage);
}
self.add_points(signed.publickey, signed.signature)
}
pub fn add_bitsig(&mut self, other: &BitSignedMessage<E, POP>) -> Result<(), SignerTableError> {
if self.message != other.message {
return Err(SignerTableError::MismatchedMessage);
}
if !self
.proofs_of_possession
.agreement(&other.proofs_of_possession)
{
return Err(SignerTableError::BadSignerTable(
"Mismatched proof-of-possession",
));
}
let os = other.signers.borrow();
for offset in 0..self.signers[0].borrow().len() {
if self
.signers
.iter()
.fold(os[offset], |b, s| b | s.borrow()[offset])
& !chunk_lookups(&self.proofs_of_possession, offset)
!= 0u8
{
return Err(SignerTableError::BadSignerTable("Absent signer"));
}
for j in 0..8 {
let mut count = self.get_count(8 * offset + j);
if os[offset] & (1 << j) != 0 {
count += 1;
}
self.test_count(count)?;
}
}
for index in 0..8 * self.signers[0].borrow().len() {
let count = self.get_count(index);
if os[index / 8] & (1 << (index % 8)) != 0 {
self.set_count(index, count + 1);
}
}
self.signature.0 += &other.signature.0;
Ok(())
}
pub fn merge(&mut self, other: &CountSignedMessage<E, POP>) -> Result<(), SignerTableError> {
if self.message != other.message {
return Err(SignerTableError::MismatchedMessage);
}
if !self
.proofs_of_possession
.agreement(&other.proofs_of_possession)
{
return Err(SignerTableError::BadSignerTable(
"Mismatched proof-of-possession",
));
}
for offset in 0..self.signers[0].borrow().len() {
if self
.signers
.iter()
.chain(&other.signers)
.fold(0u8, |b, s| b | s.borrow()[offset])
& !chunk_lookups(&self.proofs_of_possession, offset)
!= 0u8
{
return Err(SignerTableError::BadSignerTable("Absent signer"));
}
for j in 0..8 {
let index = 8 * offset + j;
self.test_count(self.get_count(index).saturating_add(other.get_count(index)))?;
}
}
for index in 0..8 * self.signers[0].borrow().len() {
self.set_count(index, self.get_count(index) + other.get_count(index));
}
self.signature.0 += &other.signature.0;
Ok(())
}
}
#[cfg(all(test, feature = "std"))]
mod tests {
use rand::thread_rng;
use super::*;
#[test]
fn proofs_of_possession() {
let msg1 = Message::new(b"ctx", b"some message");
let msg2 = Message::new(b"ctx", b"another message");
let k = |_| Keypair::<ZBLS>::generate(thread_rng());
let mut keypairs = (0..4).into_iter().map(k).collect::<Vec<_>>();
let pop = keypairs.iter().map(|k| k.public).collect::<Vec<_>>();
let dup = keypairs[3].clone();
keypairs.push(dup);
let sigs1 = keypairs
.iter_mut()
.map(|k| k.signed_message(&msg1))
.collect::<Vec<_>>();
let mut bitsig1 = BitSignedMessage::<ZBLS, _>::new(pop.clone(), &msg1);
assert!(bitsig1.verify()); for (i, sig) in sigs1.iter().enumerate().take(2) {
assert!(bitsig1.add(sig).is_ok() == (i < 4));
assert!(bitsig1.verify()); }
let mut bitsig1a = BitSignedMessage::<ZBLS, _>::new(pop.clone(), &msg1);
for (i, sig) in sigs1.iter().enumerate().skip(2) {
assert!(bitsig1a.add(sig).is_ok() == (i < 4));
assert!(bitsig1a.verify()); }
assert!(bitsig1.merge(&bitsig1a).is_ok());
assert!(bitsig1.merge(&bitsig1a).is_err());
assert!(verifiers::verify_unoptimized(&bitsig1));
assert!(verifiers::verify_simple(&bitsig1));
assert!(verifiers::verify_with_distinct_messages(&bitsig1, false));
let sigs2 = keypairs
.iter_mut()
.map(|k| k.signed_message(&msg2))
.collect::<Vec<_>>();
let mut bitsig2 = BitSignedMessage::<ZBLS, _>::new(pop.clone(), &msg2);
for sig in sigs2.iter().take(3) {
assert!(bitsig2.add(sig).is_ok());
}
assert!(bitsig1.merge(&bitsig2).is_err());
let mut multimsg =
multi_pop_aggregator::MultiMessageSignatureAggregatorAssumingPoP::<ZBLS>::new();
multimsg.aggregate(&bitsig1);
multimsg.aggregate(&bitsig2);
assert!(multimsg.verify()); assert!(verifiers::verify_unoptimized(&multimsg));
assert!(verifiers::verify_simple(&multimsg));
assert!(verifiers::verify_with_distinct_messages(&multimsg, false));
let oops = Keypair::<ZBLS>::generate(thread_rng()).signed_message(&msg2);
assert!(bitsig1.add_points(oops.publickey, oops.signature).is_err());
let mut countsig = CountSignedMessage::<ZBLS, _>::new(pop.clone(), msg1);
assert!(countsig.signers.len() == 1);
assert!(countsig.verify()); assert!(countsig.add_bitsig(&bitsig1).is_ok());
assert!(bitsig1.signature == countsig.signature);
assert!(countsig.signers.len() == 1);
assert!(
bitsig1.messages_and_publickeys().next() == countsig.messages_and_publickeys().next()
);
assert!(countsig.verify());
for (i, sig) in sigs1.iter().enumerate().take(3) {
assert!(countsig.add(sig).is_ok() == (i < 4));
assert!(countsig.verify(), "countsig failed at sig {}", i); }
assert!(countsig.add_bitsig(&bitsig1a).is_ok());
assert!(countsig.add_bitsig(&bitsig1a).is_ok());
assert!(countsig.add_bitsig(&bitsig2).is_err());
let countpop2 = countsig.clone();
assert!(countsig.merge(&countpop2).is_ok());
assert!(verifiers::verify_unoptimized(&countsig));
assert!(verifiers::verify_simple(&countsig));
assert!(verifiers::verify_with_distinct_messages(&countsig, false));
countsig.max_duplicates = 4;
assert!(countsig.merge(&countpop2).is_err());
}
}