#![allow(clippy::field_reassign_with_default)]
use alloc::vec::Vec;
#[cfg(feature = "datasize")]
use datasize::DataSize;
#[cfg(feature = "json-schema")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
bytesrepr::{self, FromBytes, ToBytes},
CLType, CLTyped, EraId, PublicKey, URef, U512,
};
use super::WithdrawPurse;
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "datasize", derive(DataSize))]
#[cfg_attr(feature = "json-schema", derive(JsonSchema))]
#[serde(deny_unknown_fields)]
pub struct UnbondingPurse {
bonding_purse: URef,
validator_public_key: PublicKey,
unbonder_public_key: PublicKey,
era_of_creation: EraId,
amount: U512,
new_validator: Option<PublicKey>,
}
impl UnbondingPurse {
pub const fn new(
bonding_purse: URef,
validator_public_key: PublicKey,
unbonder_public_key: PublicKey,
era_of_creation: EraId,
amount: U512,
new_validator: Option<PublicKey>,
) -> Self {
Self {
bonding_purse,
validator_public_key,
unbonder_public_key,
era_of_creation,
amount,
new_validator,
}
}
pub fn is_validator(&self) -> bool {
self.validator_public_key == self.unbonder_public_key
}
pub fn bonding_purse(&self) -> &URef {
&self.bonding_purse
}
pub fn validator_public_key(&self) -> &PublicKey {
&self.validator_public_key
}
pub fn unbonder_public_key(&self) -> &PublicKey {
&self.unbonder_public_key
}
pub fn era_of_creation(&self) -> EraId {
self.era_of_creation
}
pub fn amount(&self) -> &U512 {
&self.amount
}
pub fn new_validator(&self) -> &Option<PublicKey> {
&self.new_validator
}
}
impl ToBytes for UnbondingPurse {
fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
let mut result = bytesrepr::allocate_buffer(self)?;
result.extend(&self.bonding_purse.to_bytes()?);
result.extend(&self.validator_public_key.to_bytes()?);
result.extend(&self.unbonder_public_key.to_bytes()?);
result.extend(&self.era_of_creation.to_bytes()?);
result.extend(&self.amount.to_bytes()?);
result.extend(&self.new_validator.to_bytes()?);
Ok(result)
}
fn serialized_length(&self) -> usize {
self.bonding_purse.serialized_length()
+ self.validator_public_key.serialized_length()
+ self.unbonder_public_key.serialized_length()
+ self.era_of_creation.serialized_length()
+ self.amount.serialized_length()
+ self.new_validator.serialized_length()
}
fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
self.bonding_purse.write_bytes(writer)?;
self.validator_public_key.write_bytes(writer)?;
self.unbonder_public_key.write_bytes(writer)?;
self.era_of_creation.write_bytes(writer)?;
self.amount.write_bytes(writer)?;
self.new_validator.write_bytes(writer)?;
Ok(())
}
}
impl FromBytes for UnbondingPurse {
fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
let (bonding_purse, remainder) = FromBytes::from_bytes(bytes)?;
let (validator_public_key, remainder) = FromBytes::from_bytes(remainder)?;
let (unbonder_public_key, remainder) = FromBytes::from_bytes(remainder)?;
let (era_of_creation, remainder) = FromBytes::from_bytes(remainder)?;
let (amount, remainder) = FromBytes::from_bytes(remainder)?;
let (new_validator, remainder) = Option::<PublicKey>::from_bytes(remainder)?;
Ok((
UnbondingPurse {
bonding_purse,
validator_public_key,
unbonder_public_key,
era_of_creation,
amount,
new_validator,
},
remainder,
))
}
}
impl CLTyped for UnbondingPurse {
fn cl_type() -> CLType {
CLType::Any
}
}
impl From<WithdrawPurse> for UnbondingPurse {
fn from(withdraw_purse: WithdrawPurse) -> Self {
UnbondingPurse::new(
withdraw_purse.bonding_purse,
withdraw_purse.validator_public_key,
withdraw_purse.unbonder_public_key,
withdraw_purse.era_of_creation,
withdraw_purse.amount,
None,
)
}
}
#[cfg(test)]
mod tests {
use crate::{
bytesrepr, system::auction::UnbondingPurse, AccessRights, EraId, PublicKey, SecretKey,
URef, U512,
};
const BONDING_PURSE: URef = URef::new([14; 32], AccessRights::READ_ADD_WRITE);
const ERA_OF_WITHDRAWAL: EraId = EraId::MAX;
fn validator_public_key() -> PublicKey {
let secret_key = SecretKey::ed25519_from_bytes([42; SecretKey::ED25519_LENGTH]).unwrap();
PublicKey::from(&secret_key)
}
fn unbonder_public_key() -> PublicKey {
let secret_key = SecretKey::ed25519_from_bytes([43; SecretKey::ED25519_LENGTH]).unwrap();
PublicKey::from(&secret_key)
}
fn amount() -> U512 {
U512::max_value() - 1
}
#[test]
fn serialization_roundtrip_for_unbonding_purse() {
let unbonding_purse = UnbondingPurse {
bonding_purse: BONDING_PURSE,
validator_public_key: validator_public_key(),
unbonder_public_key: unbonder_public_key(),
era_of_creation: ERA_OF_WITHDRAWAL,
amount: amount(),
new_validator: None,
};
bytesrepr::test_serialization_roundtrip(&unbonding_purse);
}
#[test]
fn should_be_validator_condition_for_unbonding_purse() {
let validator_unbonding_purse = UnbondingPurse::new(
BONDING_PURSE,
validator_public_key(),
validator_public_key(),
ERA_OF_WITHDRAWAL,
amount(),
None,
);
assert!(validator_unbonding_purse.is_validator());
}
#[test]
fn should_be_delegator_condition_for_unbonding_purse() {
let delegator_unbonding_purse = UnbondingPurse::new(
BONDING_PURSE,
validator_public_key(),
unbonder_public_key(),
ERA_OF_WITHDRAWAL,
amount(),
None,
);
assert!(!delegator_unbonding_purse.is_validator());
}
}