use std::{sync::Arc};
use parity_scale_codec::{Decode, Encode};
use sp_core::crypto::KeyTypeId;
use sp_keystore::{Error as KeystoreError, Keystore};
use sp_runtime::RuntimeAppPublic;
use crate::{
abft::{NodeCount, NodeIndex, SignatureSet},
phron_primitives::{AuthorityId, AuthoritySignature, KEY_TYPE},
};
#[allow(dead_code)]
#[derive(Debug)]
pub enum Error {
KeyMissing(AuthorityId),
Keystore(KeystoreError),
Conversion,
}
#[derive(PartialEq, Eq, Clone, Debug, Hash, Decode, Encode)]
pub struct Signature(AuthoritySignature);
impl From<AuthoritySignature> for Signature {
fn from(authority_signature: AuthoritySignature) -> Signature {
Signature(authority_signature)
}
}
#[derive(Clone)]
pub struct AuthorityPen {
key_type_id: KeyTypeId,
authority_id: AuthorityId,
keystore: Arc<dyn Keystore>,
}
impl AuthorityPen {
pub fn new_with_key_type(
authority_id: AuthorityId,
keystore: Arc<dyn Keystore>,
key_type: KeyTypeId,
) -> Result<Self, Error> {
let _: AuthoritySignature = keystore
.ed25519_sign(key_type, &authority_id.clone().into(), b"test")
.map_err(Error::Keystore)?
.ok_or_else(|| Error::KeyMissing(authority_id.clone()))?
.into();
Ok(AuthorityPen {
key_type_id: key_type,
authority_id,
keystore,
})
}
pub fn new(authority_id: AuthorityId, keystore: Arc<dyn Keystore>) -> Result<Self, Error> {
Self::new_with_key_type(authority_id, keystore, KEY_TYPE)
}
pub fn sign(&self, msg: &[u8]) -> Signature {
Signature(
self.keystore
.ed25519_sign(self.key_type_id, &self.authority_id.clone().into(), msg)
.expect("the keystore works")
.expect("we have the required key")
.into(),
)
}
pub fn authority_id(&self) -> AuthorityId {
self.authority_id.clone()
}
}
pub fn verify(authority: &AuthorityId, message: &[u8], signature: &Signature) -> bool {
authority.verify(&message, &signature.0)
}
#[derive(PartialEq, Clone, Debug)]
pub struct AuthorityVerifier {
authorities: Vec<AuthorityId>,
}
impl AuthorityVerifier {
pub fn new(authorities: Vec<AuthorityId>) -> Self {
AuthorityVerifier { authorities }
}
pub fn verify(&self, msg: &[u8], sgn: &Signature, index: NodeIndex) -> bool {
match self.authorities.get(index.0) {
Some(authority) => verify(authority, msg, sgn),
None => false,
}
}
pub fn node_count(&self) -> NodeCount {
self.authorities.len().into()
}
fn threshold(&self) -> usize {
2 * self.node_count().0 / 3 + 1
}
pub fn is_complete(&self, msg: &[u8], partial: &SignatureSet<Signature>) -> bool {
let signature_count = partial.iter().count();
if signature_count < self.threshold() {
return false;
}
partial.iter().all(|(i, sgn)| self.verify(msg, sgn, i))
}
}
#[derive(PartialEq, Eq, Clone, Debug, Decode, Encode)]
pub struct SignatureV1 {
pub _id: NodeIndex,
pub sgn: AuthoritySignature,
}
impl From<SignatureV1> for Signature {
fn from(sig_v1: SignatureV1) -> Signature {
Signature(sig_v1.sgn)
}
}
#[cfg(test)]
mod tests {
use sp_keystore::{testing::MemoryKeystore as Keystore, Keystore as _};
use super::*;
use crate::abft::NodeIndex;
fn generate_keys(names: &[String]) -> (Vec<AuthorityPen>, AuthorityVerifier) {
let key_store = Arc::new(Keystore::new());
let mut authority_ids = Vec::with_capacity(names.len());
for name in names {
let pk = key_store
.ed25519_generate_new(KEY_TYPE, Some(name))
.unwrap();
authority_ids.push(AuthorityId::from(pk));
}
let mut pens = Vec::with_capacity(names.len());
for authority_id in authority_ids.clone() {
pens.push(
AuthorityPen::new(authority_id, key_store.clone())
.expect("The keys should sign successfully"),
);
}
assert_eq!(key_store.keys(KEY_TYPE).unwrap().len(), names.len());
(pens, AuthorityVerifier::new(authority_ids))
}
fn prepare_test() -> (Vec<AuthorityPen>, AuthorityVerifier) {
let authority_names: Vec<_> = ["//Alice", "//Bob", "//Charlie"]
.iter()
.map(|s| s.to_string())
.collect();
generate_keys(&authority_names)
}
#[test]
fn produces_and_verifies_correct_signatures() {
let (pens, verifier) = prepare_test();
let msg = b"test";
for (i, pen) in pens.into_iter().enumerate() {
let signature = pen.sign(msg);
assert!(verifier.verify(msg, &signature, NodeIndex(i)));
}
}
#[test]
fn does_not_accept_signatures_from_wrong_sources() {
let (pens, verifier) = prepare_test();
let msg = b"test";
for pen in &pens[1..] {
let signature = pen.sign(msg);
assert!(!verifier.verify(msg, &signature, NodeIndex(0)));
}
}
#[test]
fn does_not_accept_signatures_from_unknown_sources() {
let (pens, verifier) = prepare_test();
let msg = b"test";
for pen in &pens {
let signature = pen.sign(msg);
assert!(!verifier.verify(msg, &signature, NodeIndex(pens.len())));
}
}
#[test]
fn does_not_accept_signatures_for_different_messages() {
let (pens, verifier) = prepare_test();
let msg = b"test";
let not_msg = b"not test";
for (i, pen) in pens.into_iter().enumerate() {
let signature = pen.sign(msg);
assert!(!verifier.verify(not_msg, &signature, NodeIndex(i)));
}
}
}