use super::keys::{PublicKey, Signature, SignatureShare};
use super::money::Money;
use crdts::Dot;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use threshold_crypto::PublicKeySet;
/// Actor id
pub type AccountId = PublicKey;
/// Transfer ID.
pub type TransferId = Dot<AccountId>;
/// A transfer of money between two keys.
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct Transfer {
/// Transfer ID, containing source key.
pub id: TransferId,
/// The destination to transfer to.
pub to: AccountId,
/// The amount to transfer.
pub amount: Money,
}
impl Transfer {
/// Get the transfer id
pub fn id(&self) -> TransferId {
self.id
}
/// Get the amount of this transfer
pub fn amount(&self) -> Money {
self.amount
}
/// Get the sender of this transfer
pub fn from(&self) -> AccountId {
self.id.actor
}
/// Get the recipient of this transfer
pub fn to(&self) -> PublicKey {
self.to
}
}
/// The aggregated Replica signatures of the Actor debit cmd.
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct DebitAgreementProof {
/// The cmd generated by sender Actor.
pub signed_transfer: SignedTransfer,
/// Quorum of Replica sigs over the transfer cmd.
pub debiting_replicas_sig: Signature,
/// PublicKeySet of the replica when it validated the transfer.
pub replica_key: ReplicaPublicKeySet,
}
impl DebitAgreementProof {
/// Get the transfer id
pub fn id(&self) -> TransferId {
self.signed_transfer.id()
}
/// Get the amount of this transfer
pub fn amount(&self) -> Money {
self.signed_transfer.amount()
}
/// Get the sender of this transfer
pub fn from(&self) -> PublicKey {
self.signed_transfer.from()
}
/// Get the recipient of this transfer
pub fn to(&self) -> PublicKey {
self.signed_transfer.to()
}
/// Get the PublicKeySet of the replica that validated this transfer
pub fn replica_keys(&self) -> ReplicaPublicKeySet {
self.replica_key.clone()
}
}
/// An Actor cmd.
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct SignedTransfer {
/// The transfer.
pub transfer: Transfer,
/// Actor signature over the transfer.
pub actor_signature: Signature,
}
impl SignedTransfer {
/// Get the transfer id
pub fn id(&self) -> TransferId {
self.transfer.id
}
/// Get the amount of this transfer
pub fn amount(&self) -> Money {
self.transfer.amount
}
/// Get the sender of this transfer
pub fn from(&self) -> PublicKey {
self.transfer.id.actor
}
/// Get the recipient of this transfer
pub fn to(&self) -> PublicKey {
self.transfer.to
}
}
// ------------------------------------------------------------
// Replica
// ------------------------------------------------------------
/// Events raised by the Replica.
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub enum ReplicaEvent {
/// The event raised when
/// ValidateTransfer cmd has been successful.
TransferValidated(TransferValidated),
/// The event raised when
/// RegisterTransfer cmd has been successful.
TransferRegistered(TransferRegistered),
/// The event raised when
/// PropagateTransfer cmd has been successful.
TransferPropagated(TransferPropagated),
// /// The event raised when
// /// peers changed so that we have a new PublicKeySet.
// PeersChanged(PeersChanged),
/// The event raised when
/// we learn of a new group PK set.
KnownGroupAdded(KnownGroupAdded),
}
/// The debiting Replica event raised when
/// ValidateTransfer cmd has been successful.
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct TransferValidated {
/// The cmd generated by Actor.
pub signed_transfer: SignedTransfer,
/// Replica signature over the transfer cmd.
pub replica_signature: SignatureShare,
/// The PK Set of the Replicas
pub replicas: PublicKeySet,
// NB: I'm a bit ambivalent to this implicit communication of public key change.
// I generally prefer an explicit cmd + event for such a significant part of the logic.
// Including it here minimizes msg types and traffic, and seamlessly - apparently -
// updates Actors on any public key change, which they can accumulate in order to
// apply the change to local state.
// But it inflicts on, and complicates the logic for validating a transfer..
// Cost / benefit to be discussed..
}
impl TransferValidated {
/// Get the transfer id
pub fn id(&self) -> TransferId {
self.signed_transfer.id()
}
/// Get the amount of this transfer
pub fn amount(&self) -> Money {
self.signed_transfer.amount()
}
/// Get the recipient of this transfer
pub fn from(&self) -> PublicKey {
self.signed_transfer.from()
}
/// Get the recipient of this transfer
pub fn to(&self) -> PublicKey {
self.signed_transfer.to()
}
}
/// The debiting Replica event raised when
/// RegisterTransfer cmd has been successful.
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct TransferRegistered {
/// The debit proof.
pub debit_proof: DebitAgreementProof,
}
impl TransferRegistered {
/// Get the transfer id
pub fn id(&self) -> TransferId {
self.debit_proof.id()
}
/// Get the amount of this transfer
pub fn amount(&self) -> Money {
self.debit_proof.amount()
}
/// Get the recipient of this transfer
pub fn from(&self) -> PublicKey {
self.debit_proof.from()
}
/// Get the recipient of this transfer
pub fn to(&self) -> PublicKey {
self.debit_proof.to()
}
}
/// The crediting Replica event raised when
/// PropagateTransfer cmd has been successful.
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct TransferPropagated {
/// The debiting Replicas' proof.
pub debit_proof: DebitAgreementProof,
/// The pub key of the debiting Replicas.
pub debiting_replicas: PublicKey,
/// The crediting Replica signature.
pub crediting_replica_sig: SignatureShare,
}
impl TransferPropagated {
/// Get the transfer id
pub fn id(&self) -> TransferId {
self.debit_proof.id()
}
/// Get the amount of this transfer
pub fn amount(&self) -> Money {
self.debit_proof.amount()
}
/// Get the recipient of this transfer
pub fn from(&self) -> PublicKey {
self.debit_proof.from()
}
/// Get the recipient of this transfer
pub fn to(&self) -> PublicKey {
self.debit_proof.to()
}
}
/// Public Key Set for a group of transfer replicas.
pub type ReplicaPublicKeySet = PublicKeySet;
/// The Replica event raised when
/// we learn of a new group PK set.
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct KnownGroupAdded {
/// The PublicKeySet of the group.
pub group: PublicKeySet,
}
// /// (Draft) An Actor cmd to roll back a failed transfer.
// #[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize, Debug)]
// pub struct CancelTransfer {
// /// The transfer id.
// pub transfer_id: TransferId,
// /// Actor signature over the transfer id.
// pub actor_signature: Signature,
// }
/// Notification of a Transfer sent to a recipient.
#[derive(Hash, Eq, PartialEq, PartialOrd, Clone, Serialize, Deserialize, Debug)]
pub struct TransferNotification(pub DebitAgreementProof);