use crate::{
common::{
deserial_string, types::Signature, Buffer, Deserial, Get, ParseResult, Put, ReadBytesExt,
SerdeBase16Serialize, SerdeDeserialize, SerdeSerialize, Serial, Serialize,
},
curve_arithmetic::Curve,
id::{
constants::ArCurve,
types::{GlobalContext, VerifyKey},
},
pedersen_commitment::{Randomness, Value},
random_oracle::RandomOracle,
};
use concordium_contracts_common::AccountAddress;
pub use concordium_contracts_common::{
Address, ContractAddress, ContractIndex, ContractSubIndex, ExchangeRate,
};
use derive_more::{Add, Display, From, FromStr, Into, Sub};
use rand::{CryptoRng, Rng};
use std::{
convert::{TryFrom, TryInto},
fmt,
hash::Hash,
str::FromStr,
};
use thiserror::Error;
#[repr(transparent)] #[derive(Eq, Debug, Clone, Copy)]
pub struct AccountAddressEq(pub(crate) AccountAddress);
impl From<AccountAddressEq> for AccountAddress {
fn from(aae: AccountAddressEq) -> Self { aae.0 }
}
impl From<AccountAddress> for AccountAddressEq {
fn from(address: AccountAddress) -> Self { Self(address) }
}
impl PartialEq for AccountAddressEq {
fn eq(&self, other: &Self) -> bool {
let bytes_1 = &self.0 .0;
let bytes_2 = &other.0 .0;
bytes_1[0..29] == bytes_2[0..29]
}
}
impl PartialOrd for AccountAddressEq {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { Some(self.cmp(other)) }
}
impl Ord for AccountAddressEq {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let bytes_1 = &self.0 .0;
let bytes_2 = &other.0 .0;
bytes_1[0..29].cmp(&bytes_2[0..29])
}
}
impl Hash for AccountAddressEq {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.0 .0[0..29].hash(state) }
}
impl AsRef<AccountAddressEq> for AccountAddress {
fn as_ref(&self) -> &AccountAddressEq { unsafe { std::mem::transmute(self) } }
}
impl AsRef<AccountAddress> for AccountAddressEq {
fn as_ref(&self) -> &AccountAddress { &self.0 }
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct SlotDuration {
pub millis: u64,
}
impl From<SlotDuration> for chrono::Duration {
fn from(s: SlotDuration) -> Self {
Self::milliseconds(s.millis as i64)
}
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct DurationSeconds {
pub seconds: u64,
}
impl From<DurationSeconds> for chrono::Duration {
fn from(s: DurationSeconds) -> Self {
Self::seconds(s.seconds as i64)
}
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct BakerId {
pub id: AccountIndex,
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct DelegatorId {
pub id: AccountIndex,
}
#[repr(transparent)]
#[derive(
SerdeSerialize,
SerdeDeserialize,
Serial,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
Debug,
Display,
Into,
Default,
)]
#[serde(try_from = "String", into = "String")]
pub struct UrlText {
#[string_size_length = 2]
url: String,
}
impl Deserial for UrlText {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let len: u16 = source.get()?;
anyhow::ensure!(
usize::from(len) <= crate::constants::MAX_URL_TEXT_LENGTH,
"URL length exceeds maximum allowed."
);
let url = deserial_string(source, len.into())?;
Ok(Self { url })
}
}
impl TryFrom<String> for UrlText {
type Error = anyhow::Error;
fn try_from(value: String) -> Result<Self, Self::Error> {
anyhow::ensure!(
value.as_bytes().len() <= crate::constants::MAX_URL_TEXT_LENGTH,
"URL length exceeds maximum allowed."
);
Ok(Self { url: value })
}
}
#[derive(SerdeSerialize, SerdeDeserialize, PartialEq, Eq, Debug, Clone, Copy)]
#[serde(rename_all = "camelCase")]
#[repr(u8)]
pub enum OpenStatus {
OpenForAll = 0,
ClosedForNew = 1,
ClosedForAll = 2,
}
impl Serial for OpenStatus {
fn serial<B: Buffer>(&self, out: &mut B) { (*self as u8).serial(out) }
}
impl Deserial for OpenStatus {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let tag: u8 = source.get()?;
match tag {
0 => Ok(Self::OpenForAll),
1 => Ok(Self::ClosedForNew),
2 => Ok(Self::ClosedForAll),
_ => anyhow::bail!("Unrecognized OpenStatus tag {}", tag),
}
}
}
#[derive(SerdeSerialize, SerdeDeserialize, PartialEq, Eq, Debug, Clone)]
#[serde(rename_all = "camelCase", tag = "delegateType")]
pub enum DelegationTarget {
#[serde(rename = "Passive")]
Passive,
#[serde(rename = "Baker")]
Baker {
#[serde(rename = "bakerId")]
baker_id: BakerId,
},
}
impl From<BakerId> for DelegationTarget {
fn from(baker_id: BakerId) -> Self { Self::Baker { baker_id } }
}
impl Serial for DelegationTarget {
fn serial<B: Buffer>(&self, out: &mut B) {
match self {
DelegationTarget::Passive => 0u8.serial(out),
DelegationTarget::Baker { baker_id } => {
1u8.serial(out);
baker_id.serial(out)
}
}
}
}
impl Deserial for DelegationTarget {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let tag: u8 = source.get()?;
match tag {
0 => Ok(Self::Passive),
1 => {
let baker_id = source.get()?;
Ok(Self::Baker { baker_id })
}
_ => anyhow::bail!("Unrecognized delegation target tag: {}", tag),
}
}
}
#[derive(SerdeSerialize, SerdeDeserialize, PartialEq, Eq, Serial, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct BakerPoolInfo {
pub open_status: OpenStatus,
pub metadata_url: UrlText,
pub commission_rates: CommissionRates,
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct Slot {
pub slot: u64,
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct Epoch {
pub epoch: u64,
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct Nonce {
pub nonce: u64,
}
impl Nonce {
pub fn next(self) -> Self {
Self {
nonce: self.nonce + 1,
}
}
pub fn next_mut(&mut self) { self.nonce += 1; }
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct UpdateSequenceNumber {
pub number: u64,
}
impl UpdateSequenceNumber {
#[must_use]
pub fn next(self) -> Self {
Self {
number: self.number + 1,
}
}
pub fn next_mut(&mut self) { self.number += 1; }
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Into, Serial)]
pub struct AccountThreshold {
#[serde(deserialize_with = "crate::internal::deserialize_non_default::deserialize")]
threshold: u8,
}
impl Deserial for AccountThreshold {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let threshold: u8 = source.get()?;
anyhow::ensure!(threshold != 0, "Account threshold cannot be 0.");
Ok(AccountThreshold { threshold })
}
}
impl TryFrom<u8> for AccountThreshold {
type Error = ZeroSignatureThreshold;
fn try_from(value: u8) -> Result<Self, Self::Error> {
if value == 0 {
Err(ZeroSignatureThreshold)
} else {
Ok(AccountThreshold { threshold: value })
}
}
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct CredentialsPerBlockLimit {
pub limit: u16,
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct BlockHeight {
pub height: u64,
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct GenesisIndex {
pub height: u32,
}
#[derive(
SerdeSerialize, SerdeDeserialize, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Display,
)]
#[serde(into = "u64", try_from = "u64")]
pub enum ProtocolVersion {
#[display(fmt = "P1")]
P1,
#[display(fmt = "P2")]
P2,
#[display(fmt = "P3")]
P3,
#[display(fmt = "P4")]
P4,
#[display(fmt = "P5")]
P5,
#[display(fmt = "P6")]
P6,
}
#[derive(Debug, Error, Display)]
pub struct UnknownProtocolVersion {
version: u64,
}
impl TryFrom<u64> for ProtocolVersion {
type Error = UnknownProtocolVersion;
fn try_from(value: u64) -> Result<Self, Self::Error> {
match value {
1 => Ok(ProtocolVersion::P1),
2 => Ok(ProtocolVersion::P2),
3 => Ok(ProtocolVersion::P3),
4 => Ok(ProtocolVersion::P4),
5 => Ok(ProtocolVersion::P5),
6 => Ok(ProtocolVersion::P6),
version => Err(UnknownProtocolVersion { version }),
}
}
}
impl From<ProtocolVersion> for u64 {
fn from(pv: ProtocolVersion) -> Self {
match pv {
ProtocolVersion::P1 => 1,
ProtocolVersion::P2 => 2,
ProtocolVersion::P3 => 3,
ProtocolVersion::P4 => 4,
ProtocolVersion::P5 => 5,
ProtocolVersion::P6 => 6,
}
}
}
impl Serial for ProtocolVersion {
fn serial<B: Buffer>(&self, out: &mut B) {
let n: u64 = (*self).into();
out.put(&n);
}
}
impl Deserial for ProtocolVersion {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let n: u64 = source.get()?;
let pv = ProtocolVersion::try_from(n)?;
Ok(pv)
}
}
pub struct ChainParameterVersion0;
pub struct ChainParameterVersion1;
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct AbsoluteBlockHeight {
pub height: u64,
}
impl AbsoluteBlockHeight {
#[must_use]
pub fn next(self) -> Self {
AbsoluteBlockHeight {
height: 1 + self.height,
}
}
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct AccountIndex {
pub index: u64,
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(
Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into, Add, Sub,
)]
pub struct Energy {
pub energy: u64,
}
impl Energy {
pub fn checked_sub(self, rhs: Energy) -> Option<Energy> {
self.energy.checked_sub(rhs.energy).map(From::from)
}
pub fn tick_energy(&mut self, amount: Energy) -> Result<(), InsufficientEnergy> {
if let Some(nrg) = self.energy.checked_sub(amount.energy) {
self.energy = nrg;
Ok(())
} else {
Err(InsufficientEnergy)
}
}
}
#[derive(Debug, PartialEq, Eq, Error)]
#[error("Out of energy")]
pub struct InsufficientEnergy;
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Debug, Serialize, Clone, Copy)]
#[serde(transparent)]
pub struct TransactionIndex {
pub index: u64,
}
pub type AggregateSigPairing = crate::id::constants::IpPairing;
#[repr(transparent)]
#[derive(SerdeBase16Serialize, Serialize)]
pub struct BakerAggregationSignKey {
pub(crate) sign_key: crate::aggregate_sig::SecretKey<AggregateSigPairing>,
}
impl BakerAggregationSignKey {
pub fn generate<T: Rng>(csprng: &mut T) -> Self {
Self {
sign_key: crate::aggregate_sig::SecretKey::generate(csprng),
}
}
pub fn prove<T: Rng>(
&self,
csprng: &mut T,
random_oracle: &mut RandomOracle,
) -> crate::aggregate_sig::Proof<AggregateSigPairing> {
self.sign_key.prove(csprng, random_oracle)
}
}
#[repr(transparent)]
#[derive(SerdeBase16Serialize, Serialize, Clone, Debug, PartialEq)]
pub struct BakerAggregationVerifyKey {
pub(crate) verify_key: crate::aggregate_sig::PublicKey<AggregateSigPairing>,
}
impl From<&BakerAggregationSignKey> for BakerAggregationVerifyKey {
fn from(secret: &BakerAggregationSignKey) -> Self {
Self {
verify_key: crate::aggregate_sig::PublicKey::from_secret(&secret.sign_key),
}
}
}
#[repr(transparent)]
#[derive(SerdeBase16Serialize, Serialize)]
pub struct BakerSignatureSignKey {
pub(crate) sign_key: ed25519_dalek::SecretKey,
}
impl BakerSignatureSignKey {
pub fn generate<T: CryptoRng + Rng>(csprng: &mut T) -> Self {
Self {
sign_key: ed25519_dalek::SecretKey::generate(csprng),
}
}
}
#[repr(transparent)]
#[derive(SerdeBase16Serialize, Serialize, Clone, Debug, PartialEq, Eq)]
pub struct BakerSignatureVerifyKey {
pub(crate) verify_key: ed25519_dalek::PublicKey,
}
impl From<&BakerSignatureSignKey> for BakerSignatureVerifyKey {
fn from(secret: &BakerSignatureSignKey) -> Self {
Self {
verify_key: ed25519_dalek::PublicKey::from(&secret.sign_key),
}
}
}
#[repr(transparent)]
#[derive(SerdeBase16Serialize, Serialize)]
pub struct BakerElectionSignKey {
pub(crate) sign_key: crate::ecvrf::SecretKey,
}
impl BakerElectionSignKey {
pub fn generate<T: CryptoRng + Rng>(csprng: &mut T) -> Self {
Self {
sign_key: crate::ecvrf::SecretKey::generate(csprng),
}
}
}
#[repr(transparent)]
#[derive(SerdeBase16Serialize, Serialize, Clone, Debug, PartialEq, Eq)]
pub struct BakerElectionVerifyKey {
pub(crate) verify_key: crate::ecvrf::PublicKey,
}
impl From<&BakerElectionSignKey> for BakerElectionVerifyKey {
fn from(secret: &BakerElectionSignKey) -> Self {
Self {
verify_key: crate::ecvrf::PublicKey::from(&secret.sign_key),
}
}
}
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
pub struct BakerKeyPairs {
#[serde(rename = "signatureSignKey")]
pub signature_sign: BakerSignatureSignKey,
#[serde(rename = "signatureVerifyKey")]
pub signature_verify: BakerSignatureVerifyKey,
#[serde(rename = "electionPrivateKey")]
pub election_sign: BakerElectionSignKey,
#[serde(rename = "electionVerifyKey")]
pub election_verify: BakerElectionVerifyKey,
#[serde(rename = "aggregationSignKey")]
pub aggregation_sign: BakerAggregationSignKey,
#[serde(rename = "aggregationVerifyKey")]
pub aggregation_verify: BakerAggregationVerifyKey,
}
impl BakerKeyPairs {
pub fn generate<T: Rng + CryptoRng>(csprng: &mut T) -> Self {
let signature_sign = BakerSignatureSignKey::generate(csprng);
let signature_verify = BakerSignatureVerifyKey::from(&signature_sign);
let election_sign = BakerElectionSignKey::generate(csprng);
let election_verify = BakerElectionVerifyKey::from(&election_sign);
let aggregation_sign = BakerAggregationSignKey::generate(csprng);
let aggregation_verify = BakerAggregationVerifyKey::from(&aggregation_sign);
BakerKeyPairs {
signature_sign,
signature_verify,
election_sign,
election_verify,
aggregation_sign,
aggregation_verify,
}
}
}
#[derive(SerdeSerialize, SerdeDeserialize)]
#[serde(rename_all = "camelCase")]
pub struct BakerCredentials {
pub baker_id: BakerId,
#[serde(flatten)]
pub keys: BakerKeyPairs,
}
impl BakerCredentials {
pub fn new(baker_id: BakerId, keys: BakerKeyPairs) -> Self {
BakerCredentials { baker_id, keys }
}
}
#[derive(
SerdeBase16Serialize, Serialize, Debug, Clone, Copy, derive_more::AsRef, derive_more::Into,
)]
pub struct CredentialRegistrationID(crate::id::constants::ArCurve);
impl CredentialRegistrationID {
pub fn new(g: crate::id::constants::ArCurve) -> Self { Self(g) }
pub fn from_exponent(
crypto_params: &GlobalContext<ArCurve>,
cexp: <crate::id::constants::ArCurve as Curve>::Scalar,
) -> Self {
let cred_id = crypto_params
.on_chain_commitment_key
.hide(&Value::<ArCurve>::new(cexp), &Randomness::zero())
.0;
Self::new(cred_id)
}
}
impl fmt::Display for CredentialRegistrationID {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = hex::encode(crate::common::to_bytes(self));
s.fmt(f)
}
}
#[repr(transparent)]
#[derive(Debug, SerdeSerialize, SerdeDeserialize, Serialize, Clone, Into, From, PartialEq, Eq)]
#[serde(transparent)]
pub struct UpdatePublicKey {
pub public: VerifyKey,
}
#[derive(Debug, SerdeSerialize, SerdeDeserialize)]
pub struct UpdateKeyPair {
#[serde(
rename = "signKey",
serialize_with = "crate::common::base16_encode",
deserialize_with = "crate::common::base16_decode"
)]
pub secret: ed25519_dalek::SecretKey,
#[serde(flatten)]
pub public: UpdatePublicKey,
}
impl UpdateKeyPair {
pub fn generate<R: rand::CryptoRng + rand::Rng>(rng: &mut R) -> Self {
let kp = ed25519_dalek::Keypair::generate(rng);
Self {
secret: kp.secret,
public: UpdatePublicKey {
public: VerifyKey::Ed25519VerifyKey(kp.public),
},
}
}
pub fn sign(&self, msg: &[u8]) -> Signature {
let expanded = ed25519_dalek::ExpandedSecretKey::from(&self.secret);
match self.public.public {
VerifyKey::Ed25519VerifyKey(vf) => {
let sig = expanded.sign(msg, &vf);
Signature {
sig: sig.to_bytes().to_vec(),
}
}
}
}
}
impl From<&UpdateKeyPair> for UpdatePublicKey {
fn from(kp: &UpdateKeyPair) -> Self { kp.public.clone() }
}
#[derive(Debug, Clone, Copy, SerdeSerialize, SerdeDeserialize, Serialize, Into, Display)]
#[serde(transparent)]
pub struct UpdateKeysThreshold {
pub(crate) threshold: std::num::NonZeroU16,
}
impl From<UpdateKeysThreshold> for u16 {
#[inline]
fn from(u: UpdateKeysThreshold) -> Self { u.threshold.get() }
}
#[derive(Debug, Error)]
#[error("Signature threshold cannot be 0.")]
pub struct ZeroSignatureThreshold;
impl TryFrom<u16> for UpdateKeysThreshold {
type Error = ZeroSignatureThreshold;
fn try_from(value: u16) -> Result<Self, Self::Error> {
std::num::NonZeroU16::new(value).map_or(Err(ZeroSignatureThreshold), |threshold| {
Ok(UpdateKeysThreshold { threshold })
})
}
}
#[repr(transparent)]
#[derive(
Debug,
Clone,
Copy,
SerdeSerialize,
SerdeDeserialize,
Serialize,
PartialEq,
Eq,
PartialOrd,
Ord,
From,
)]
#[serde(transparent)]
pub struct UpdateKeysIndex {
pub index: u16,
}
impl std::fmt::Display for UpdateKeysIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.index.fmt(f) }
}
#[repr(transparent)]
#[derive(
Debug, Clone, Copy, SerdeSerialize, SerdeDeserialize, Serialize, FromStr, PartialEq, Eq,
)]
#[serde(transparent)]
pub struct ElectionDifficulty {
pub(crate) parts_per_hundred_thousands: PartsPerHundredThousands,
}
impl ElectionDifficulty {
pub fn new(parts: u32) -> Option<Self> {
let parts_per_hundred_thousands = PartsPerHundredThousands::new(parts)?;
Some(Self {
parts_per_hundred_thousands,
})
}
pub fn new_unchecked(parts: u32) -> Self {
Self {
parts_per_hundred_thousands: PartsPerHundredThousands::new_unchecked(parts),
}
}
}
impl From<ElectionDifficulty> for rust_decimal::Decimal {
fn from(ed: ElectionDifficulty) -> Self { ed.parts_per_hundred_thousands.into() }
}
#[repr(transparent)]
#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Into)]
pub struct PartsPerHundredThousands {
pub(crate) parts: u32,
}
impl PartsPerHundredThousands {
pub fn new(parts: u32) -> Option<Self> {
if parts <= 100_000 {
Some(Self { parts })
} else {
None
}
}
pub fn new_unchecked(parts: u32) -> Self { Self { parts } }
}
impl From<PartsPerHundredThousands> for rust_decimal::Decimal {
fn from(pp: PartsPerHundredThousands) -> Self { rust_decimal::Decimal::new(pp.parts.into(), 5) }
}
impl Serial for PartsPerHundredThousands {
fn serial<B: Buffer>(&self, out: &mut B) { self.parts.serial(out) }
}
impl Deserial for PartsPerHundredThousands {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let parts: u32 = source.get()?;
Self::new(parts)
.ok_or_else(|| anyhow::anyhow!("No more than 100_000 parts per hundred thousand."))
}
}
impl fmt::Display for PartsPerHundredThousands {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let x = rust_decimal::Decimal::try_new(self.parts.into(), 5).map_err(|_| fmt::Error)?;
x.fmt(f)
}
}
#[derive(SerdeSerialize, SerdeDeserialize, PartialEq, Eq, Serialize, Debug, Clone, Copy)]
pub struct CommissionRates {
#[serde(rename = "finalizationCommission")]
pub finalization: AmountFraction,
#[serde(rename = "bakingCommission")]
pub baking: AmountFraction,
#[serde(rename = "transactionCommission")]
pub transaction: AmountFraction,
}
#[derive(Serialize, SerdeSerialize, SerdeDeserialize, Debug, Clone)]
pub struct CommissionRanges {
#[serde(rename = "finalizationCommissionRange")]
pub finalization: InclusiveRange<AmountFraction>,
#[serde(rename = "bakingCommissionRange")]
pub baking: InclusiveRange<AmountFraction>,
#[serde(rename = "transactionCommissionRange")]
pub transaction: InclusiveRange<AmountFraction>,
}
#[derive(Debug, Copy, Clone, SerdeSerialize, SerdeDeserialize)]
pub struct InclusiveRange<T> {
pub min: T,
pub max: T,
}
impl<T: Serial> Serial for InclusiveRange<T> {
fn serial<B: Buffer>(&self, out: &mut B) {
self.min.serial(out);
self.max.serial(out)
}
}
impl<T: Deserial + Ord> Deserial for InclusiveRange<T> {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let min = source.get()?;
let max = source.get()?;
anyhow::ensure!(min <= max, "Invalid range.");
Ok(Self { min, max })
}
}
impl<T: Ord> InclusiveRange<T> {
pub fn contains(&self, x: &T) -> bool { &self.min <= x && x <= &self.max }
}
#[derive(SerdeSerialize, SerdeDeserialize, Serial, Debug, Clone, Copy)]
#[serde(try_from = "leverage_factor_json::LeverageFactorRaw")]
pub struct LeverageFactor {
#[serde(deserialize_with = "crate::internal::deserialize_non_default::deserialize")]
pub numerator: u64,
#[serde(deserialize_with = "crate::internal::deserialize_non_default::deserialize")]
pub denominator: u64,
}
impl LeverageFactor {
pub fn new_integral(factor: u64) -> Self {
Self {
numerator: factor,
denominator: 1,
}
}
pub fn new(numerator: u64, denominator: u64) -> Option<Self> {
if numerator >= denominator
&& denominator != 0
&& num::integer::gcd(numerator, denominator) == 1
{
Some(Self {
numerator,
denominator,
})
} else {
None
}
}
}
mod leverage_factor_json {
#[derive(super::SerdeDeserialize)]
pub struct LeverageFactorRaw {
pub numerator: u64,
pub denominator: u64,
}
impl std::convert::TryFrom<LeverageFactorRaw> for super::LeverageFactor {
type Error = anyhow::Error;
fn try_from(value: LeverageFactorRaw) -> Result<Self, Self::Error> {
let numerator = value.numerator;
let denominator = value.denominator;
super::LeverageFactor::new(numerator, denominator)
.ok_or_else(|| anyhow::anyhow!("Invalid leverage factor."))
}
}
}
impl Deserial for LeverageFactor {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let numerator = source.get()?;
let denominator = source.get()?;
Self::new(numerator, denominator).ok_or_else(|| anyhow::anyhow!("Invalid leverage factor."))
}
}
#[derive(SerdeSerialize, SerdeDeserialize, Serial, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct MintDistributionV0 {
pub mint_per_slot: MintRate,
pub baking_reward: AmountFraction,
pub finalization_reward: AmountFraction,
}
#[derive(SerdeSerialize, SerdeDeserialize, Serial, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct MintDistributionV1 {
pub baking_reward: AmountFraction,
pub finalization_reward: AmountFraction,
}
impl Deserial for MintDistributionV0 {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let mint_per_slot = source.get()?;
let baking_reward: AmountFraction = source.get()?;
let finalization_reward: AmountFraction = source.get()?;
anyhow::ensure!(
(baking_reward + finalization_reward).is_some(),
"Reward fractions exceed 100%."
);
Ok(Self {
mint_per_slot,
baking_reward,
finalization_reward,
})
}
}
impl Deserial for MintDistributionV1 {
fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
let baking_reward: AmountFraction = source.get()?;
let finalization_reward: AmountFraction = source.get()?;
anyhow::ensure!(
(baking_reward + finalization_reward).is_some(),
"Reward fractions exceed 100%."
);
Ok(Self {
baking_reward,
finalization_reward,
})
}
}
pub trait MintDistributionFamily {
type Output;
}
impl MintDistributionFamily for ChainParameterVersion0 {
type Output = MintDistributionV0;
}
impl MintDistributionFamily for ChainParameterVersion1 {
type Output = MintDistributionV1;
}
pub type MintDistribution<CPV> = <CPV as MintDistributionFamily>::Output;
#[derive(Debug, Serialize, Clone, Copy)]
pub struct MintRate {
pub mantissa: u32,
pub exponent: u8,
}
#[derive(
Default,
Debug,
Display,
Clone,
Copy,
SerdeSerialize,
SerdeDeserialize,
Serialize,
PartialEq,
Eq,
PartialOrd,
Ord,
Into,
FromStr,
)]
#[serde(transparent)]
pub struct AmountFraction {
pub(crate) parts_per_hundred_thousands: PartsPerHundredThousands,
}
impl AmountFraction {
pub fn new(parts: u32) -> Option<Self> {
let parts_per_hundred_thousands = PartsPerHundredThousands::new(parts)?;
Some(Self {
parts_per_hundred_thousands,
})
}
pub fn new_unchecked(parts: u32) -> Self {
Self {
parts_per_hundred_thousands: PartsPerHundredThousands::new_unchecked(parts),
}
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, SerdeSerialize, SerdeDeserialize, Serialize, FromStr)]
#[serde(transparent)]
pub struct CapitalBound {
#[serde(deserialize_with = "crate::internal::deserialize_non_default::deserialize")]
pub bound: AmountFraction,
}
#[repr(transparent)]
#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
#[serde(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
pub struct FinalizationIndex {
pub index: u64,
}
impl std::ops::Add for PartsPerHundredThousands {
type Output = Option<Self>;
fn add(self, rhs: Self) -> Self::Output {
let parts = self.parts.checked_add(rhs.parts)?;
if parts <= 100_000 {
Some(PartsPerHundredThousands { parts })
} else {
None
}
}
}
impl std::ops::Add for AmountFraction {
type Output = Option<Self>;
fn add(self, rhs: Self) -> Self::Output {
let parts_per_hundred_thousands =
(self.parts_per_hundred_thousands + rhs.parts_per_hundred_thousands)?;
Some(AmountFraction {
parts_per_hundred_thousands,
})
}
}
impl SerdeSerialize for PartsPerHundredThousands {
fn serialize<S: serde::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
let decimal = rust_decimal::Decimal::try_new(self.parts.into(), 5)
.map_err(serde::ser::Error::custom)?;
SerdeSerialize::serialize(&decimal, ser)
}
}
#[derive(Clone, PartialEq, Debug, Error)]
pub enum ConvertPartsPerHundredThousandsError {
#[error("Parts per thousand should not have more than 5 decimals.")]
TooManyDecimals,
#[error("Parts per thousand should not be negative.")]
Negative,
#[error("Parts per thousand out of bounds.")]
OutOfBounds,
#[error("Scale out of bounds.")]
ScaleError {
#[from]
inner: rust_decimal::Error,
},
}
impl TryFrom<rust_decimal::Decimal> for PartsPerHundredThousands {
type Error = ConvertPartsPerHundredThousandsError;
fn try_from(value: rust_decimal::Decimal) -> Result<Self, Self::Error> {
let mut f = value;
f.normalize_assign();
if f.scale() > 5 {
return Err(ConvertPartsPerHundredThousandsError::TooManyDecimals);
}
if !f.is_sign_positive() && !f.is_zero() {
return Err(ConvertPartsPerHundredThousandsError::Negative);
}
f.rescale(5);
if f.mantissa() > 100_000 {
return Err(ConvertPartsPerHundredThousandsError::OutOfBounds);
}
Ok(PartsPerHundredThousands {
parts: f.mantissa() as u32,
})
}
}
impl FromStr for PartsPerHundredThousands {
type Err = ConvertPartsPerHundredThousandsError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let decimal: rust_decimal::Decimal = s.parse()?;
Self::try_from(decimal)
}
}
impl<'de> SerdeDeserialize<'de> for PartsPerHundredThousands {
fn deserialize<D: serde::Deserializer<'de>>(des: D) -> Result<Self, D::Error> {
let f: rust_decimal::Decimal =
SerdeDeserialize::deserialize(des).map_err(serde::de::Error::custom)?;
let parts = PartsPerHundredThousands::try_from(f).map_err(serde::de::Error::custom)?;
Ok(parts)
}
}
impl SerdeSerialize for MintRate {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer, {
let x = rust_decimal::Decimal::try_new(self.mantissa.into(), self.exponent.into())
.map_err(serde::ser::Error::custom)?;
SerdeSerialize::serialize(&x, serializer)
}
}
impl FromStr for MintRate {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let f: rust_decimal::Decimal = s.parse()?;
f.try_into()
}
}
impl TryFrom<rust_decimal::Decimal> for MintRate {
type Error = anyhow::Error;
fn try_from(mut value: rust_decimal::Decimal) -> Result<Self, Self::Error> {
value.normalize_assign();
if let Ok(exponent) = u8::try_from(value.scale()) {
if let Ok(mantissa) = u32::try_from(value.mantissa()) {
Ok(MintRate { mantissa, exponent })
} else {
anyhow::bail!("Unsupported mantissa range for MintRate.",);
}
} else {
anyhow::bail!("Unsupported exponent range for MintRate.");
}
}
}
impl<'de> SerdeDeserialize<'de> for MintRate {
fn deserialize<D>(des: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>, {
let f: rust_decimal::Decimal = SerdeDeserialize::deserialize(des)?;
MintRate::try_from(f).map_err(serde::de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parts_0() {
assert_eq!(
Ok(PartsPerHundredThousands::new_unchecked(12345)),
"0.12345".parse(),
"Case 1."
);
assert_eq!(
Ok(PartsPerHundredThousands::new_unchecked(12345)),
"0.123450".parse(),
"Case 2."
);
assert_eq!(
Ok(PartsPerHundredThousands::new_unchecked(12300)),
"0.123".parse(),
"Case 3."
);
assert_eq!(
Ok(PartsPerHundredThousands::new_unchecked(12300)),
"0.123000".parse(),
"Case 4."
);
assert!("0.123456".parse::<PartsPerHundredThousands>().is_err());
}
#[test]
fn test_parts_json() {
assert_eq!(
PartsPerHundredThousands::new_unchecked(12345),
serde_json::from_str("0.12345").unwrap(),
"Case 1."
);
assert_eq!(
PartsPerHundredThousands::new_unchecked(12345),
serde_json::from_str("0.123450").unwrap(),
"Case 2."
);
assert_eq!(
PartsPerHundredThousands::new_unchecked(12300),
serde_json::from_str("0.123").unwrap(),
"Case 3."
);
assert_eq!(
PartsPerHundredThousands::new_unchecked(12300),
serde_json::from_str("0.123000").unwrap(),
"Case 4."
);
assert!(serde_json::from_str::<PartsPerHundredThousands>("0.123456").is_err());
}
}