use super::{Error, Outcome, Result, TernaryResult};
use crate::genesis;
use sn_data_types::{
CreditAgreementProof, PublicKey, SignatureShare, SignedCredit, SignedDebit, SignedTransfer,
};
use threshold_crypto::{PublicKeySet, PublicKeyShare, SecretKeyShare};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReplicaSigning {
id: PublicKeyShare,
secret_key: SecretKeyShare,
key_index: usize,
peer_replicas: PublicKeySet,
}
impl ReplicaSigning {
pub fn new(secret_key: SecretKeyShare, key_index: usize, peer_replicas: PublicKeySet) -> Self {
let id = secret_key.public_key_share();
Self {
secret_key,
id,
key_index,
peer_replicas,
}
}
pub fn replicas_pk_set(&self) -> PublicKeySet {
self.peer_replicas.clone()
}
pub fn try_genesis(&self, balance: u64) -> Result<CreditAgreementProof> {
genesis::get_genesis(
balance,
PublicKey::Bls(self.peer_replicas.public_key()),
self.peer_replicas.clone(),
self.secret_key.clone(),
)
}
pub fn sign_transfer(
&self,
signed_transfer: &SignedTransfer,
) -> Outcome<(SignatureShare, SignatureShare)> {
let replica_debit_sig = self.sign_validated_debit(&signed_transfer.debit)?;
let replica_credit_sig = self.sign_validated_credit(&signed_transfer.credit)?;
if let Some(rds) = replica_debit_sig {
if let Some(rcs) = replica_credit_sig {
return Outcome::success((rds, rcs));
}
}
Outcome::rejected(Error::InvalidSignature)
}
pub fn sign_validated_debit(&self, debit: &SignedDebit) -> Outcome<SignatureShare> {
match bincode::serialize(debit) {
Err(_) => Err(Error::Serialisation("Could not serialise debit".into())),
Ok(data) => Outcome::success(SignatureShare {
index: self.key_index,
share: self.secret_key.sign(data),
}),
}
}
pub fn sign_validated_credit(&self, credit: &SignedCredit) -> Outcome<SignatureShare> {
match bincode::serialize(credit) {
Err(_) => Err(Error::Serialisation("Could not serialise credit".into())),
Ok(data) => Outcome::success(SignatureShare {
index: self.key_index,
share: self.secret_key.sign(data),
}),
}
}
pub fn sign_credit_proof(&self, proof: &CreditAgreementProof) -> Outcome<SignatureShare> {
match bincode::serialize(proof) {
Err(_) => Err(Error::Serialisation("Could not serialise proof".into())),
Ok(data) => Outcome::success(SignatureShare {
index: self.key_index,
share: self.secret_key.sign(data),
}),
}
}
}