use super::{
keys::{PublicKey, Signature, SignatureShare},
token::Token,
utils, Error, Result,
};
use crdts::Dot;
use serde::{Deserialize, Serialize};
use std::fmt::{self, Debug, Display, Formatter};
use threshold_crypto::PublicKeySet;
use tiny_keccak::{Hasher, Sha3};
pub type DebitId = Dot<PublicKey>;
pub type CreditId = [u8; 256 / 8];
pub type Msg = String;
#[derive(Eq, PartialEq, Clone, Serialize, Deserialize)]
pub struct WalletInfo {
pub replicas: PublicKeySet,
pub history: ActorHistory,
}
impl Debug for WalletInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"WalletInfo {{ replicas: PkSet {{ public_key: {:?} }}, history: {:?} }}",
self.replicas.public_key(),
self.history
)
}
}
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct Transfer {
pub amount: Token,
pub to: PublicKey,
pub debit_id: DebitId,
pub msg: Msg,
}
impl Transfer {
pub fn debit(&self) -> Debit {
Debit {
id: self.debit_id,
amount: self.amount,
}
}
pub fn credit(&self) -> Result<Credit> {
Ok(Credit {
id: self.debit().credit_id()?,
amount: self.amount,
recipient: self.to,
msg: self.msg.to_string(),
})
}
}
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct Debit {
pub id: DebitId,
pub amount: Token,
}
impl Debit {
pub fn id(&self) -> DebitId {
self.id
}
pub fn amount(&self) -> Token {
self.amount
}
pub fn sender(&self) -> PublicKey {
self.id.actor
}
pub fn credit_id(&self) -> Result<CreditId> {
let id_bytes = &utils::serialise(&self.id)?;
let mut hasher = Sha3::v256();
let mut output = [0; 32];
hasher.update(&id_bytes);
hasher.finalize(&mut output);
Ok(output)
}
}
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub struct Credit {
pub id: CreditId,
pub amount: Token,
pub recipient: PublicKey,
pub msg: Msg,
}
impl Credit {
pub fn id(&self) -> &CreditId {
&self.id
}
pub fn amount(&self) -> Token {
self.amount
}
pub fn recipient(&self) -> PublicKey {
self.recipient
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct ActorHistory {
pub credits: Vec<CreditAgreementProof>,
pub debits: Vec<TransferAgreementProof>,
}
impl ActorHistory {
pub fn empty() -> Self {
Self {
credits: vec![],
debits: vec![],
}
}
pub fn is_empty(&self) -> bool {
self.credits.is_empty() && self.debits.is_empty()
}
pub fn len(&self) -> usize {
self.credits.len() + self.debits.len()
}
}
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct CreditAgreementProof {
pub signed_credit: SignedCredit,
pub debiting_replicas_sig: Signature,
pub debiting_replicas_keys: ReplicaPublicKeySet,
}
impl Debug for CreditAgreementProof {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "CreditAgreementProof::")?;
write!(formatter, "Credit({})", self.signed_credit.amount())?;
write!(formatter, "ActorSignature::")?;
Debug::fmt(&self.signed_credit.actor_signature, formatter)?;
write!(formatter, "ReplicaSignature::")?;
Debug::fmt(&self.debiting_replicas_sig, formatter)
}
}
impl Display for CreditAgreementProof {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
Debug::fmt(self, formatter)
}
}
impl CreditAgreementProof {
pub fn id(&self) -> &CreditId {
self.signed_credit.id()
}
pub fn amount(&self) -> Token {
self.signed_credit.amount()
}
pub fn recipient(&self) -> PublicKey {
self.signed_credit.recipient()
}
pub fn replica_keys(&self) -> ReplicaPublicKeySet {
self.debiting_replicas_keys.clone()
}
}
#[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct TransferAgreementProof {
pub signed_debit: SignedDebit,
pub signed_credit: SignedCredit,
pub debit_sig: Signature,
pub credit_sig: Signature,
pub debiting_replicas_keys: ReplicaPublicKeySet,
}
impl TransferAgreementProof {
pub fn id(&self) -> DebitId {
self.signed_debit.id()
}
pub fn amount(&self) -> Token {
self.signed_debit.amount()
}
pub fn sender(&self) -> PublicKey {
self.signed_debit.sender()
}
pub fn recipient(&self) -> PublicKey {
self.signed_credit.recipient()
}
pub fn replica_keys(&self) -> ReplicaPublicKeySet {
self.debiting_replicas_keys.clone()
}
pub fn credit_proof(&self) -> CreditAgreementProof {
CreditAgreementProof {
signed_credit: self.signed_credit.clone(),
debiting_replicas_sig: self.credit_sig.clone(),
debiting_replicas_keys: self.replica_keys(),
}
}
}
impl Debug for TransferAgreementProof {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"TransferAgreementProof {{ signed_debit: {:?}, signed_credit: {:?}, debit_sig: {:?}, credit_sig: {:?}, debiting_replicas_keys: PkSet {{ public_key: {:?} }} }}",
self.signed_debit,
self.signed_credit,
self.debit_sig,
self.credit_sig,
self.debiting_replicas_keys.public_key()
)
}
}
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct SignedTransfer {
pub debit: SignedDebit,
pub credit: SignedCredit,
}
impl SignedTransfer {
pub fn id(&self) -> DebitId {
self.debit.id()
}
pub fn amount(&self) -> Token {
self.debit.amount()
}
pub fn sender(&self) -> PublicKey {
self.debit.id().actor
}
pub fn credit_id(&self) -> Result<CreditId> {
self.debit.credit_id()
}
}
#[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct SignedDebit {
pub debit: Debit,
pub actor_signature: Signature,
}
impl SignedDebit {
pub fn id(&self) -> DebitId {
self.debit.id()
}
pub fn amount(&self) -> Token {
self.debit.amount()
}
pub fn sender(&self) -> PublicKey {
self.debit.sender()
}
pub fn credit_id(&self) -> Result<CreditId> {
self.debit.credit_id()
}
pub fn as_share(&self) -> Result<SignedDebitShare> {
if let Signature::BlsShare(share) = self.actor_signature.clone() {
Ok(SignedDebitShare {
debit: self.debit.clone(),
actor_signature: share,
})
} else {
Err(Error::InvalidSignature)
}
}
}
#[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct SignedCredit {
pub credit: Credit,
pub actor_signature: Signature,
}
impl SignedCredit {
pub fn id(&self) -> &CreditId {
self.credit.id()
}
pub fn amount(&self) -> Token {
self.credit.amount
}
pub fn recipient(&self) -> PublicKey {
self.credit.recipient()
}
pub fn as_share(&self) -> Result<SignedCreditShare> {
if let Signature::BlsShare(share) = self.actor_signature.clone() {
Ok(SignedCreditShare {
credit: self.credit.clone(),
actor_signature: share,
})
} else {
Err(Error::InvalidSignature)
}
}
}
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct SignedTransferShare {
debit: SignedDebitShare,
credit: SignedCreditShare,
actors: PublicKeySet,
}
impl SignedTransferShare {
pub fn new(
debit: SignedDebitShare,
credit: SignedCreditShare,
actors: PublicKeySet,
) -> Result<Self> {
if debit.amount() != credit.amount() {
return Err(Error::InvalidOperation);
}
if debit.credit_id()? != *credit.id() {
return Err(Error::InvalidOperation);
}
let debit_sig_index = debit.actor_signature.index;
let credit_sig_index = credit.actor_signature.index;
if debit_sig_index != credit_sig_index {
return Err(Error::InvalidOperation);
}
Ok(Self {
debit,
credit,
actors,
})
}
pub fn id(&self) -> DebitId {
self.debit.id()
}
pub fn amount(&self) -> Token {
self.debit.amount()
}
pub fn sender(&self) -> PublicKey {
self.debit.id().actor
}
pub fn credit_id(&self) -> Result<CreditId> {
self.debit.credit_id()
}
pub fn debit(&self) -> &SignedDebitShare {
&self.debit
}
pub fn credit(&self) -> &SignedCreditShare {
&self.credit
}
pub fn share_index(&self) -> usize {
self.debit.actor_signature.index
}
pub fn actors(&self) -> &PublicKeySet {
&self.actors
}
}
impl Debug for SignedTransferShare {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"SignedTransferShare {{ debit: {:?}, credit: {:?}, actors: PkSet {{ public_key: {:?} }} }}",
self.debit,
self.credit,
self.actors.public_key()
)
}
}
#[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct SignedDebitShare {
pub debit: Debit,
pub actor_signature: SignatureShare,
}
impl SignedDebitShare {
pub fn id(&self) -> DebitId {
self.debit.id()
}
pub fn amount(&self) -> Token {
self.debit.amount()
}
pub fn sender(&self) -> PublicKey {
self.debit.sender()
}
pub fn credit_id(&self) -> Result<CreditId> {
self.debit.credit_id()
}
pub fn share_index(&self) -> usize {
self.actor_signature.index
}
}
#[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct SignedCreditShare {
pub credit: Credit,
pub actor_signature: SignatureShare,
}
impl SignedCreditShare {
pub fn id(&self) -> &CreditId {
self.credit.id()
}
pub fn amount(&self) -> Token {
self.credit.amount
}
pub fn recipient(&self) -> PublicKey {
self.credit.recipient()
}
pub fn share_index(&self) -> usize {
self.actor_signature.index
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub enum ReplicaEvent {
TransferValidationProposed(TransferValidationProposed),
TransferValidated(TransferValidated),
TransferRegistered(TransferRegistered),
TransferPropagated(TransferPropagated),
}
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct TransferValidationProposed {
pub signed_debit: SignedDebitShare,
pub signed_credit: SignedCreditShare,
pub agreed_transfer: Option<SignedTransfer>,
}
impl TransferValidationProposed {
pub fn id(&self) -> DebitId {
self.signed_debit.id()
}
pub fn amount(&self) -> Token {
self.signed_debit.amount()
}
pub fn sender(&self) -> PublicKey {
self.signed_debit.sender()
}
pub fn recipient(&self) -> PublicKey {
self.signed_credit.recipient()
}
}
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct TransferValidated {
pub signed_debit: SignedDebit,
pub signed_credit: SignedCredit,
pub replica_debit_sig: SignatureShare,
pub replica_credit_sig: SignatureShare,
pub replicas: PublicKeySet,
}
impl Debug for TransferValidated {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"TransferValidated {{ signed_debit: {:?}, signed_credit: {:?}, replica_debit_sig: {:?}, replica_credit_sig: {:?}, replicas: PkSet {{ public_key: {:?} }} }}",
self.signed_debit,
self.signed_credit,
self.replica_debit_sig,
self.replica_credit_sig,
self.replicas.public_key()
)
}
}
impl TransferValidated {
pub fn id(&self) -> DebitId {
self.signed_debit.id()
}
pub fn amount(&self) -> Token {
self.signed_debit.amount()
}
pub fn sender(&self) -> PublicKey {
self.signed_debit.sender()
}
pub fn recipient(&self) -> PublicKey {
self.signed_credit.recipient()
}
}
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct TransferRegistered {
pub transfer_proof: TransferAgreementProof,
}
impl TransferRegistered {
pub fn id(&self) -> DebitId {
self.transfer_proof.id()
}
pub fn amount(&self) -> Token {
self.transfer_proof.amount()
}
pub fn sender(&self) -> PublicKey {
self.transfer_proof.sender()
}
pub fn recipient(&self) -> PublicKey {
self.transfer_proof.recipient()
}
}
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct TransferPropagated {
pub credit_proof: CreditAgreementProof,
}
impl TransferPropagated {
pub fn id(&self) -> &CreditId {
self.credit_proof.id()
}
pub fn amount(&self) -> Token {
self.credit_proof.amount()
}
pub fn recipient(&self) -> PublicKey {
self.credit_proof.recipient()
}
}
pub type ReplicaPublicKeySet = PublicKeySet;
#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct KnownGroupAdded {
pub group: PublicKeySet,
}
impl Debug for KnownGroupAdded {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"KnownGroupAdded {{ group: PkSet {{ public_key: {:?} }} }}",
self.group.public_key()
)
}
}
#[derive(Eq, PartialEq, Clone, Serialize, Deserialize, Debug)]
pub struct CreditNotification(pub CreditAgreementProof);