concordium_base/
base.rs

1//! Basis type definitions that are used throughout the crate.
2
3use crate::{
4    common::{
5        base16_decode_string, deserial_string, types::Signature, Buffer, Deserial, Get,
6        ParseResult, Put, ReadBytesExt, SerdeBase16Serialize, SerdeDeserialize, SerdeSerialize,
7        Serial, Serialize,
8    },
9    curve_arithmetic::Curve,
10    id::{
11        constants::ArCurve,
12        types::{GlobalContext, VerifyKey},
13    },
14    pedersen_commitment::{Randomness, Value},
15    random_oracle::RandomOracle,
16};
17use concordium_contracts_common::AccountAddress;
18pub use concordium_contracts_common::{
19    AccountThreshold, Address, ContractAddress, ContractIndex, ContractSubIndex, ExchangeRate,
20    ZeroSignatureThreshold,
21};
22use derive_more::{Add, Display, From, FromStr, Into, Sub, Sum};
23use ed25519_dalek::Signer;
24use rand::{CryptoRng, Rng};
25use std::{
26    convert::{TryFrom, TryInto},
27    fmt,
28    hash::Hash,
29    str::FromStr,
30};
31use thiserror::Error;
32
33/// An equivalence class of account addresses. Two account addresses are
34/// equivalent if they are aliases of each other.
35///
36/// Account aliases share the first 29 bytes of the address, so the
37/// [`PartialEq`]/[`PartialOrd`] for this type adheres to that.
38#[repr(transparent)] // this is essential for the AsRef implementation
39#[derive(Eq, Debug, Clone, Copy)]
40pub struct AccountAddressEq(pub(crate) AccountAddress);
41
42impl From<AccountAddressEq> for AccountAddress {
43    fn from(aae: AccountAddressEq) -> Self {
44        aae.0
45    }
46}
47
48impl From<AccountAddress> for AccountAddressEq {
49    fn from(address: AccountAddress) -> Self {
50        Self(address)
51    }
52}
53
54impl PartialEq for AccountAddressEq {
55    fn eq(&self, other: &Self) -> bool {
56        let bytes_1 = &self.0 .0;
57        let bytes_2 = &other.0 .0;
58        bytes_1[0..29] == bytes_2[0..29]
59    }
60}
61
62impl PartialOrd for AccountAddressEq {
63    #[inline]
64    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
65        Some(self.cmp(other))
66    }
67}
68
69impl Ord for AccountAddressEq {
70    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
71        let bytes_1 = &self.0 .0;
72        let bytes_2 = &other.0 .0;
73        bytes_1[0..29].cmp(&bytes_2[0..29])
74    }
75}
76
77impl Hash for AccountAddressEq {
78    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
79        self.0 .0[0..29].hash(state)
80    }
81}
82
83// NB: We cannot implement `Borrow` since the equality instance for
84// AccountAddressEq is, deliberately, different, from the one for account
85// addresses.
86impl AsRef<AccountAddressEq> for AccountAddress {
87    fn as_ref(&self) -> &AccountAddressEq {
88        unsafe { std::mem::transmute(self) }
89    }
90}
91
92// NB: We cannot implement `Borrow` since the equality instance for
93// AccountAddressEq is, deliberately, different, from the one for account
94// addresses.
95impl AsRef<AccountAddress> for AccountAddressEq {
96    fn as_ref(&self) -> &AccountAddress {
97        &self.0
98    }
99}
100
101/// Duration of a slot in milliseconds.
102#[repr(transparent)]
103#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
104#[serde(transparent)]
105#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
106pub struct SlotDuration {
107    pub millis: u64,
108}
109
110/// The slot duration is not representable as a [`Duration`](chrono::Duration).
111/// It is too large.
112#[derive(Debug, thiserror::Error)]
113#[error("Slot duration is not representable as chrono::Duration.")]
114pub struct SlotDurationConversionError;
115
116impl TryFrom<SlotDuration> for chrono::Duration {
117    type Error = SlotDurationConversionError;
118
119    fn try_from(s: SlotDuration) -> Result<Self, Self::Error> {
120        let Ok(millis) = s.millis.try_into() else {
121            return Err(SlotDurationConversionError);
122        };
123        Self::try_milliseconds(millis).ok_or(SlotDurationConversionError)
124    }
125}
126
127/// Duration in seconds.
128#[repr(transparent)]
129#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
130#[serde(transparent)]
131#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
132pub struct DurationSeconds {
133    pub seconds: u64,
134}
135
136/// The duration in seconds is not representable as a
137/// [`Duration`](chrono::Duration). It is too large.
138#[derive(Debug, thiserror::Error)]
139#[error("Duration in seconds is not representable as chrono::Duration.")]
140pub struct DurationSecondsConversionError;
141
142impl TryFrom<DurationSeconds> for chrono::Duration {
143    type Error = SlotDurationConversionError;
144
145    fn try_from(s: DurationSeconds) -> Result<Self, Self::Error> {
146        let Ok(millis) = s.seconds.try_into() else {
147            return Err(SlotDurationConversionError);
148        };
149        Self::try_seconds(millis).ok_or(SlotDurationConversionError)
150    }
151}
152
153/// Internal short id of the baker.
154#[repr(transparent)]
155#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
156#[serde(transparent)]
157#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
158pub struct BakerId {
159    pub id: AccountIndex,
160}
161
162/// Internal short id of the delegator.
163#[repr(transparent)]
164#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
165#[serde(transparent)]
166#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
167pub struct DelegatorId {
168    pub id: AccountIndex,
169}
170
171/// A unicode representation of a Url.
172/// The Utf8 encoding of the Url must be at most
173/// [`MAX_URL_TEXT_LENGTH`](crate::constants::MAX_URL_TEXT_LENGTH) bytes.
174///
175/// The default instance produces the empty URL.
176#[repr(transparent)]
177#[derive(
178    SerdeSerialize,
179    SerdeDeserialize,
180    Serial,
181    Clone,
182    Eq,
183    PartialEq,
184    Ord,
185    PartialOrd,
186    Debug,
187    Display,
188    Into,
189    Default,
190)]
191#[serde(try_from = "String", into = "String")]
192pub struct UrlText {
193    #[string_size_length = 2]
194    url: String,
195}
196
197impl Deserial for UrlText {
198    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
199        let len: u16 = source.get()?;
200        anyhow::ensure!(
201            usize::from(len) <= crate::constants::MAX_URL_TEXT_LENGTH,
202            "URL length exceeds maximum allowed."
203        );
204        let url = deserial_string(source, len.into())?;
205        Ok(Self { url })
206    }
207}
208
209impl TryFrom<String> for UrlText {
210    type Error = anyhow::Error;
211
212    fn try_from(value: String) -> Result<Self, Self::Error> {
213        anyhow::ensure!(
214            value.as_bytes().len() <= crate::constants::MAX_URL_TEXT_LENGTH,
215            "URL length exceeds maximum allowed."
216        );
217        Ok(Self { url: value })
218    }
219}
220
221/// The status of whether a baking pool allows delegators to join.
222#[derive(SerdeSerialize, SerdeDeserialize, PartialEq, Eq, Debug, Clone, Copy)]
223#[serde(rename_all = "camelCase")]
224#[repr(u8)]
225pub enum OpenStatus {
226    /// New delegators may join the pool.
227    OpenForAll = 0,
228    /// New delegators may not join, but existing delegators are kept.
229    ClosedForNew = 1,
230    /// No delegators are allowed.
231    ClosedForAll = 2,
232}
233
234impl Serial for OpenStatus {
235    fn serial<B: Buffer>(&self, out: &mut B) {
236        (*self as u8).serial(out)
237    }
238}
239
240impl Deserial for OpenStatus {
241    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
242        let tag: u8 = source.get()?;
243        match tag {
244            0 => Ok(Self::OpenForAll),
245            1 => Ok(Self::ClosedForNew),
246            2 => Ok(Self::ClosedForAll),
247            _ => anyhow::bail!("Unrecognized OpenStatus tag {}", tag),
248        }
249    }
250}
251
252#[derive(SerdeSerialize, SerdeDeserialize, PartialEq, Eq, Debug, Clone)]
253#[serde(rename_all = "camelCase", tag = "delegateType")]
254/// Target of delegation.
255pub enum DelegationTarget {
256    #[serde(rename = "Passive")]
257    /// Delegate passively, i.e., to no specific baker.
258    Passive,
259    #[serde(rename = "Baker")]
260    /// Delegate to a specific baker.
261    Baker {
262        #[serde(rename = "bakerId")]
263        baker_id: BakerId,
264    },
265}
266
267impl From<BakerId> for DelegationTarget {
268    fn from(baker_id: BakerId) -> Self {
269        Self::Baker { baker_id }
270    }
271}
272
273impl Serial for DelegationTarget {
274    fn serial<B: Buffer>(&self, out: &mut B) {
275        match self {
276            DelegationTarget::Passive => 0u8.serial(out),
277            DelegationTarget::Baker { baker_id } => {
278                1u8.serial(out);
279                baker_id.serial(out)
280            }
281        }
282    }
283}
284
285impl Deserial for DelegationTarget {
286    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
287        let tag: u8 = source.get()?;
288        match tag {
289            0 => Ok(Self::Passive),
290            1 => {
291                let baker_id = source.get()?;
292                Ok(Self::Baker { baker_id })
293            }
294            _ => anyhow::bail!("Unrecognized delegation target tag: {}", tag),
295        }
296    }
297}
298
299/// Slot number
300#[repr(transparent)]
301#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
302#[serde(transparent)]
303#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
304pub struct Slot {
305    pub slot: u64,
306}
307
308/// Epoch number
309#[repr(transparent)]
310#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
311#[serde(transparent)]
312#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
313pub struct Epoch {
314    pub epoch: u64,
315}
316
317/// Round number. Applies to protocol 6 and onward.
318#[repr(transparent)]
319#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
320#[serde(transparent)]
321#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
322pub struct Round {
323    pub round: u64,
324}
325
326#[repr(transparent)]
327#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
328#[serde(transparent)]
329#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
330/// A sequence number ordering transactions from a specific account. The initial
331/// sequence number is `1`, and a transaction with sequence number `m` must be
332/// followed by a transaction with sequence number `m+1`.
333pub struct Nonce {
334    pub nonce: u64,
335}
336
337impl Nonce {
338    /// Get the next nonce.
339    pub fn next(self) -> Self {
340        Self {
341            nonce: self.nonce + 1,
342        }
343    }
344
345    /// Increase the nonce to the next nonce.
346    pub fn next_mut(&mut self) {
347        self.nonce += 1;
348    }
349}
350
351#[repr(transparent)]
352#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
353#[serde(transparent)]
354#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
355/// Equivalent of a transaction nonce but for update instructions. Update
356/// sequence numbers are per update type. The minimum sequence number is 1.
357pub struct UpdateSequenceNumber {
358    pub number: u64,
359}
360
361impl UpdateSequenceNumber {
362    /// Get the next sequence number. This is marked as must_use to prevent
363    /// mistakes in combination with next_mut.
364    #[must_use]
365    pub fn next(self) -> Self {
366        Self {
367            number: self.number + 1,
368        }
369    }
370
371    /// Increase the sequence number.
372    pub fn next_mut(&mut self) {
373        self.number += 1;
374    }
375}
376
377impl Default for UpdateSequenceNumber {
378    fn default() -> Self {
379        Self { number: 1 }
380    }
381}
382
383#[repr(transparent)]
384#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
385#[serde(transparent)]
386#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
387/// Limit on the number of credential deployments in a block. Since credential
388/// deployments create accounts, this is in effect a limit on the number of
389/// accounts that can be created in a block.
390pub struct CredentialsPerBlockLimit {
391    pub limit: u16,
392}
393
394/// Height of a block. Last genesis block is at height 0, a child of a block at
395/// height n is at height n+1. This height counts from the last protocol update.
396#[repr(transparent)]
397#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
398#[serde(transparent)]
399#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
400pub struct BlockHeight {
401    pub height: u64,
402}
403
404/// Type indicating the index of a (re)genesis block.
405/// The initial genesis block has index `0` and each subsequent regenesis
406/// has an incrementally higher index.
407#[repr(transparent)]
408#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
409#[serde(transparent)]
410#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
411pub struct GenesisIndex {
412    pub height: u32,
413}
414
415/// An enumeration of the supported versions of the consensus protocol.
416/// Binary and JSON serializations are as Word64 corresponding to the protocol
417/// number.
418#[derive(
419    SerdeSerialize, SerdeDeserialize, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Display,
420)]
421#[serde(into = "u64", try_from = "u64")]
422pub enum ProtocolVersion {
423    #[display(fmt = "P1")]
424    /// The initial protocol version at mainnet launch.
425    P1,
426    #[display(fmt = "P2")]
427    /// Protocol `P2` introduces support for transfers with memos.
428    P2,
429    #[display(fmt = "P3")]
430    /// Protocol `P3` introduces support for account aliases. Each account can
431    /// now be referred to by `2^24` different addresses.
432    P3,
433    #[display(fmt = "P4")]
434    /// Protocol `P4` is a major upgrade that adds support for delegation,
435    /// baking pools, and V1 smart contracts.
436    P4,
437    #[display(fmt = "P5")]
438    /// Protocol `P5` is a minor upgrade that adds support for smart contract
439    /// upgradability, smart contract queries, relaxes some limitations and
440    /// improves the structure of internal node datastructures related to
441    /// accounts.
442    P5,
443    #[display(fmt = "P6")]
444    /// Protocol `P6` uses a new ConcordiumBFT consensus protocol. It also fixes
445    /// state rollback behaviour for version 1 smart contracts, adds support for
446    /// Wasm instructions, and adds host functions for supporting sponsored
447    /// transactions.
448    P6,
449    #[display(fmt = "P7")]
450    /// Protocol `P7` modifies hashing to better support light clients, and
451    /// implements tokenomics changes.
452    P7,
453    #[display(fmt = "P8")]
454    /// Protocol `P8` introduces support for suspended validators.
455    P8,
456    #[display(fmt = "P9")]
457    /// Protocol `P9` introduces support for protocol level tokens (PLT).
458    P9,
459}
460
461#[derive(Debug, Error, Display)]
462/// A structure to represent conversion errors when converting integers to
463/// protocol versions.
464pub struct UnknownProtocolVersion {
465    /// The version that was attempted to be converted, but is not supported.
466    version: u64,
467}
468
469impl TryFrom<u64> for ProtocolVersion {
470    type Error = UnknownProtocolVersion;
471
472    fn try_from(value: u64) -> Result<Self, Self::Error> {
473        match value {
474            1 => Ok(ProtocolVersion::P1),
475            2 => Ok(ProtocolVersion::P2),
476            3 => Ok(ProtocolVersion::P3),
477            4 => Ok(ProtocolVersion::P4),
478            5 => Ok(ProtocolVersion::P5),
479            6 => Ok(ProtocolVersion::P6),
480            7 => Ok(ProtocolVersion::P7),
481            8 => Ok(ProtocolVersion::P8),
482            9 => Ok(ProtocolVersion::P9),
483            version => Err(UnknownProtocolVersion { version }),
484        }
485    }
486}
487
488impl From<ProtocolVersion> for u64 {
489    fn from(pv: ProtocolVersion) -> Self {
490        match pv {
491            ProtocolVersion::P1 => 1,
492            ProtocolVersion::P2 => 2,
493            ProtocolVersion::P3 => 3,
494            ProtocolVersion::P4 => 4,
495            ProtocolVersion::P5 => 5,
496            ProtocolVersion::P6 => 6,
497            ProtocolVersion::P7 => 7,
498            ProtocolVersion::P8 => 8,
499            ProtocolVersion::P9 => 9,
500        }
501    }
502}
503
504impl Serial for ProtocolVersion {
505    fn serial<B: Buffer>(&self, out: &mut B) {
506        let n: u64 = (*self).into();
507        out.put(&n);
508    }
509}
510
511impl Deserial for ProtocolVersion {
512    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
513        let n: u64 = source.get()?;
514        let pv = ProtocolVersion::try_from(n)?;
515        Ok(pv)
516    }
517}
518
519/// Height of a block since chain genesis.
520#[repr(transparent)]
521#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
522#[serde(transparent)]
523#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
524pub struct AbsoluteBlockHeight {
525    pub height: u64,
526}
527
528impl AbsoluteBlockHeight {
529    /// Get the next height.
530    #[must_use]
531    pub fn next(self) -> Self {
532        AbsoluteBlockHeight {
533            height: 1 + self.height,
534        }
535    }
536}
537
538#[repr(transparent)]
539#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
540#[serde(transparent)]
541#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
542/// Index of the account in the account table. These are assigned sequentially
543/// in the order of creation of accounts. The first account has index 0.
544pub struct AccountIndex {
545    pub index: u64,
546}
547
548/// Energy measure.
549#[repr(transparent)]
550#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
551#[serde(transparent)]
552#[derive(
553    Copy,
554    Clone,
555    Eq,
556    PartialEq,
557    Ord,
558    PartialOrd,
559    Debug,
560    Default,
561    FromStr,
562    Display,
563    From,
564    Into,
565    Add,
566    Sub,
567    Sum,
568)]
569pub struct Energy {
570    pub energy: u64,
571}
572
573impl Energy {
574    /// Checked `Energy` subtraction.
575    ///
576    /// Computes `self - rhs` and returns `None` if an underflow occurred.
577    pub fn checked_sub(self, rhs: Energy) -> Option<Energy> {
578        self.energy.checked_sub(rhs.energy).map(From::from)
579    }
580
581    /// "Tick" energy: subtract the provided amount.
582    ///
583    /// Returns an error if the energy goes below `0`.
584    pub fn tick_energy(&mut self, amount: Energy) -> Result<(), InsufficientEnergy> {
585        if let Some(nrg) = self.energy.checked_sub(amount.energy) {
586            self.energy = nrg;
587            Ok(())
588        } else {
589            Err(InsufficientEnergy)
590        }
591    }
592}
593
594#[derive(Debug, PartialEq, Eq, Error)]
595#[error("Out of energy")]
596/// An error raised by [`tick_energy`](Energy::tick_energy) when subtracting the
597/// required amount of energy would lead to a negative value.
598pub struct InsufficientEnergy;
599
600/// Position of the transaction in a block.
601#[repr(transparent)]
602#[derive(SerdeSerialize, SerdeDeserialize, Debug, Serialize, Clone, Copy)]
603#[serde(transparent)]
604pub struct TransactionIndex {
605    pub index: u64,
606}
607
608pub type AggregateSigPairing = crate::id::constants::IpPairing;
609
610#[repr(transparent)]
611#[derive(SerdeBase16Serialize, Serialize)]
612/// A secret key used by bakers and finalizers to sign finalization records.
613pub struct BakerAggregationSignKey {
614    pub(crate) sign_key: crate::aggregate_sig::SecretKey<AggregateSigPairing>,
615}
616
617impl BakerAggregationSignKey {
618    /// Generate a fresh key using the provided random number generatro.
619    pub fn generate<T: Rng>(csprng: &mut T) -> Self {
620        Self {
621            sign_key: crate::aggregate_sig::SecretKey::generate(csprng),
622        }
623    }
624
625    /// Prove knowledge of the baker aggregation signing key with respect to the
626    /// challenge given via the random oracle.
627    pub fn prove<T: Rng>(
628        &self,
629        csprng: &mut T,
630        random_oracle: &mut RandomOracle,
631    ) -> crate::aggregate_sig::Proof<AggregateSigPairing> {
632        self.sign_key.prove(csprng, random_oracle)
633    }
634}
635
636#[repr(transparent)]
637#[derive(SerdeBase16Serialize, Serialize, Clone, Debug, PartialEq)]
638/// Public key corresponding to [`BakerAggregationVerifyKey`].
639pub struct BakerAggregationVerifyKey {
640    pub(crate) verify_key: crate::aggregate_sig::PublicKey<AggregateSigPairing>,
641}
642
643impl From<&BakerAggregationSignKey> for BakerAggregationVerifyKey {
644    fn from(secret: &BakerAggregationSignKey) -> Self {
645        Self {
646            verify_key: crate::aggregate_sig::PublicKey::from_secret(&secret.sign_key),
647        }
648    }
649}
650
651#[repr(transparent)]
652#[derive(SerdeBase16Serialize, Serialize)]
653/// A secret key used by a baker to sign blocks.
654pub struct BakerSignatureSignKey {
655    pub(crate) sign_key: ed25519_dalek::SecretKey,
656}
657
658impl BakerSignatureSignKey {
659    /// Generate a fresh key using the provided random number generator.
660    pub fn generate<T: CryptoRng + Rng>(csprng: &mut T) -> Self {
661        Self {
662            sign_key: csprng.gen(),
663        }
664    }
665}
666
667#[repr(transparent)]
668#[derive(SerdeBase16Serialize, Serialize, Clone, Debug, PartialEq, Eq)]
669/// A public key that corresponds to [`BakerSignatureVerifyKey`].
670pub struct BakerSignatureVerifyKey {
671    pub(crate) verify_key: ed25519_dalek::VerifyingKey,
672}
673
674impl From<&BakerSignatureSignKey> for BakerSignatureVerifyKey {
675    fn from(secret: &BakerSignatureSignKey) -> Self {
676        Self {
677            verify_key: ed25519_dalek::SigningKey::from(&secret.sign_key).verifying_key(),
678        }
679    }
680}
681
682#[repr(transparent)]
683#[derive(SerdeBase16Serialize, Serialize)]
684/// A secret key used by a baker to prove that they won the lottery to produce a
685/// block.
686pub struct BakerElectionSignKey {
687    pub(crate) sign_key: crate::ecvrf::SecretKey,
688}
689
690impl BakerElectionSignKey {
691    pub fn generate<T: CryptoRng + Rng>(csprng: &mut T) -> Self {
692        Self {
693            sign_key: crate::ecvrf::SecretKey::generate(csprng),
694        }
695    }
696}
697
698#[repr(transparent)]
699#[derive(SerdeBase16Serialize, Serialize, Clone, Debug, PartialEq, Eq)]
700/// A public key that corresponds to [`BakerElectionSignKey`].
701pub struct BakerElectionVerifyKey {
702    pub(crate) verify_key: crate::ecvrf::PublicKey,
703}
704
705impl From<&BakerElectionSignKey> for BakerElectionVerifyKey {
706    fn from(secret: &BakerElectionSignKey) -> Self {
707        Self {
708            verify_key: crate::ecvrf::PublicKey::from(&secret.sign_key),
709        }
710    }
711}
712
713/// Baker keys containing both public and secret keys.
714/// This is used to construct `BakerKeysPayload` for adding and updating baker
715/// keys. It is also used to build the `BakerCredentials` required to have a
716/// concordium node running as a baker.
717///
718/// Note: This type contains unencrypted secret keys and should be treated
719/// carefully.
720#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
721pub struct BakerKeyPairs {
722    #[serde(rename = "signatureSignKey")]
723    pub signature_sign: BakerSignatureSignKey,
724    #[serde(rename = "signatureVerifyKey")]
725    pub signature_verify: BakerSignatureVerifyKey,
726    #[serde(rename = "electionPrivateKey")]
727    pub election_sign: BakerElectionSignKey,
728    #[serde(rename = "electionVerifyKey")]
729    pub election_verify: BakerElectionVerifyKey,
730    #[serde(rename = "aggregationSignKey")]
731    pub aggregation_sign: BakerAggregationSignKey,
732    #[serde(rename = "aggregationVerifyKey")]
733    pub aggregation_verify: BakerAggregationVerifyKey,
734}
735
736impl BakerKeyPairs {
737    /// Generate key pairs needed for becoming a baker.
738    pub fn generate<T: Rng + CryptoRng>(csprng: &mut T) -> Self {
739        let signature_sign = BakerSignatureSignKey::generate(csprng);
740        let signature_verify = BakerSignatureVerifyKey::from(&signature_sign);
741        let election_sign = BakerElectionSignKey::generate(csprng);
742        let election_verify = BakerElectionVerifyKey::from(&election_sign);
743        let aggregation_sign = BakerAggregationSignKey::generate(csprng);
744        let aggregation_verify = BakerAggregationVerifyKey::from(&aggregation_sign);
745        BakerKeyPairs {
746            signature_sign,
747            signature_verify,
748            election_sign,
749            election_verify,
750            aggregation_sign,
751            aggregation_verify,
752        }
753    }
754}
755
756/// Baker credentials type, which can be serialized to JSON and used by a
757/// concordium-node for baking.
758///
759/// Note: This type contains unencrypted secret keys and should be treated
760/// carefully.
761#[derive(SerdeSerialize, SerdeDeserialize)]
762#[serde(rename_all = "camelCase")]
763pub struct BakerCredentials {
764    #[serde(alias = "validatorId")]
765    pub baker_id: BakerId,
766    #[serde(flatten)]
767    pub keys: BakerKeyPairs,
768}
769
770impl BakerCredentials {
771    pub fn new(baker_id: BakerId, keys: BakerKeyPairs) -> Self {
772        BakerCredentials { baker_id, keys }
773    }
774}
775
776#[derive(
777    SerdeBase16Serialize,
778    Serialize,
779    Debug,
780    Clone,
781    Copy,
782    derive_more::AsRef,
783    derive_more::Into,
784    PartialEq,
785    Eq,
786)]
787/// A registration ID of a credential. This ID is generated from the user's PRF
788/// key and a sequential counter. [`CredentialRegistrationID`]'s generated from
789/// the same PRF key, but different counter values cannot easily be linked
790/// together.
791pub struct CredentialRegistrationID(crate::id::constants::ArCurve);
792
793impl FromStr for CredentialRegistrationID {
794    type Err = anyhow::Error;
795
796    fn from_str(s: &str) -> Result<Self, Self::Err> {
797        base16_decode_string(s)
798    }
799}
800
801impl CredentialRegistrationID {
802    pub fn new(g: crate::id::constants::ArCurve) -> Self {
803        Self(g)
804    }
805
806    /// Construct the cred id from the exponent derived from the PRF key, in
807    /// the context of chain cryptographic parameters `crypto_params`.
808    pub fn from_exponent(
809        crypto_params: &GlobalContext<ArCurve>,
810        cexp: <crate::id::constants::ArCurve as Curve>::Scalar,
811    ) -> Self {
812        let cred_id = crypto_params
813            .on_chain_commitment_key
814            .hide(&Value::<ArCurve>::new(cexp), &Randomness::zero())
815            .0;
816        Self::new(cred_id)
817    }
818}
819
820impl fmt::Display for CredentialRegistrationID {
821    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
822        let s = hex::encode(crate::common::to_bytes(self));
823        s.fmt(f)
824    }
825}
826
827#[repr(transparent)]
828#[derive(Debug, SerdeSerialize, SerdeDeserialize, Serialize, Clone, Into, From, PartialEq, Eq)]
829#[serde(transparent)]
830/// A single public key that can sign updates.
831pub struct UpdatePublicKey {
832    pub public: VerifyKey,
833}
834
835/// A ed25519 keypair. This is available in the `ed25519::dalek` crate, but the
836/// JSON serialization there is not compatible with what we use, so we redefine
837/// it there.
838#[derive(Debug, SerdeSerialize, SerdeDeserialize, derive_more::AsRef, Clone)]
839#[serde(
840    try_from = "update_key_pair_json::UpdateKeyPair",
841    into = "update_key_pair_json::UpdateKeyPair"
842)]
843pub struct UpdateKeyPair {
844    inner: ed25519_dalek::SigningKey,
845}
846
847mod update_key_pair_json {
848    use crate::id::types::SchemeId;
849
850    use super::*;
851    /// A ed25519 keypair. This is available in the `ed25519::dalek` crate, but
852    /// the JSON serialization there is not compatible with what we use, so
853    /// we redefine it there.
854    #[derive(Debug, SerdeSerialize, SerdeDeserialize)]
855    pub struct UpdateKeyPair {
856        #[serde(
857            rename = "signKey",
858            serialize_with = "crate::common::base16_encode_array",
859            deserialize_with = "crate::common::base16_decode_array"
860        )]
861        pub secret: ed25519_dalek::SecretKey,
862        #[serde(
863            rename = "verifyKey",
864            serialize_with = "crate::common::base16_encode",
865            deserialize_with = "crate::common::base16_decode"
866        )]
867        pub public: ed25519_dalek::VerifyingKey,
868        pub schema: Option<SchemeId>,
869    }
870
871    impl TryFrom<UpdateKeyPair> for super::UpdateKeyPair {
872        type Error = ed25519_dalek::SignatureError;
873
874        fn try_from(value: UpdateKeyPair) -> Result<Self, Self::Error> {
875            let inner = ed25519_dalek::SigningKey::from_bytes(&value.secret);
876            if inner.verifying_key() != value.public {
877                Err(ed25519_dalek::SignatureError::from_source(
878                    "Public key does not match secret key.",
879                ))
880            } else {
881                Ok(Self { inner })
882            }
883        }
884    }
885
886    impl From<super::UpdateKeyPair> for UpdateKeyPair {
887        fn from(value: super::UpdateKeyPair) -> Self {
888            Self {
889                secret: value.inner.to_bytes(),
890                public: value.inner.verifying_key(),
891                schema: Some(SchemeId::Ed25519),
892            }
893        }
894    }
895}
896
897impl UpdateKeyPair {
898    /// Generate a fresh key pair using the provided random number generator.
899    pub fn generate<R: rand::CryptoRng + rand::Rng>(rng: &mut R) -> Self {
900        let inner = ed25519_dalek::SigningKey::generate(rng);
901        Self { inner }
902    }
903
904    /// Sign the message with the keypair.
905    pub fn sign(&self, msg: &[u8]) -> Signature {
906        self.inner.sign(msg).into()
907    }
908}
909
910impl From<&UpdateKeyPair> for UpdatePublicKey {
911    fn from(kp: &UpdateKeyPair) -> Self {
912        UpdatePublicKey {
913            public: kp.inner.verifying_key().into(),
914        }
915    }
916}
917
918#[derive(
919    Debug, Clone, Copy, SerdeSerialize, SerdeDeserialize, Serialize, Into, Display, Eq, PartialEq,
920)]
921#[serde(transparent)]
922/// A lower bound on the number of signatures needed to sign a valid update
923/// message of a particular type. This is never 0.
924pub struct UpdateKeysThreshold {
925    pub(crate) threshold: std::num::NonZeroU16,
926}
927
928impl From<UpdateKeysThreshold> for u16 {
929    #[inline]
930    fn from(u: UpdateKeysThreshold) -> Self {
931        u.threshold.get()
932    }
933}
934
935impl TryFrom<u16> for UpdateKeysThreshold {
936    type Error = ZeroSignatureThreshold;
937
938    fn try_from(value: u16) -> Result<Self, Self::Error> {
939        std::num::NonZeroU16::new(value).map_or(Err(ZeroSignatureThreshold), |threshold| {
940            Ok(UpdateKeysThreshold { threshold })
941        })
942    }
943}
944
945#[repr(transparent)]
946#[derive(
947    Debug,
948    Clone,
949    Copy,
950    SerdeSerialize,
951    SerdeDeserialize,
952    Serialize,
953    PartialEq,
954    Eq,
955    PartialOrd,
956    Ord,
957    From,
958)]
959#[serde(transparent)]
960/// An identifier of a key that can sign update instructions. A signature of an
961/// update instruction is a collection of signatures. An [`UpdateKeysIndex`]
962/// identifies keys that correspond to the signatures.
963pub struct UpdateKeysIndex {
964    pub index: u16,
965}
966
967impl std::fmt::Display for UpdateKeysIndex {
968    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
969        self.index.fmt(f)
970    }
971}
972
973#[repr(transparent)]
974#[derive(
975    Debug, Clone, Copy, SerdeSerialize, SerdeDeserialize, Serialize, FromStr, PartialEq, Eq,
976)]
977#[serde(transparent)]
978/// Representation of the election difficulty as parts per `100_000`. The
979/// election difficulty is never more than `1`.
980pub struct ElectionDifficulty {
981    pub(crate) parts_per_hundred_thousands: PartsPerHundredThousands,
982}
983
984impl ElectionDifficulty {
985    /// Construct a new election difficulty given the integer number of parts
986    /// per `100_000`. Return [`None`] if the number of parts exceeds
987    /// `100_000`.
988    pub fn new(parts: u32) -> Option<Self> {
989        let parts_per_hundred_thousands = PartsPerHundredThousands::new(parts)?;
990        Some(Self {
991            parts_per_hundred_thousands,
992        })
993    }
994
995    /// Construct a new election without checking it is valid.
996    pub fn new_unchecked(parts: u32) -> Self {
997        Self {
998            parts_per_hundred_thousands: PartsPerHundredThousands::new_unchecked(parts),
999        }
1000    }
1001}
1002
1003impl From<ElectionDifficulty> for rust_decimal::Decimal {
1004    fn from(ed: ElectionDifficulty) -> Self {
1005        ed.parts_per_hundred_thousands.into()
1006    }
1007}
1008
1009#[repr(transparent)]
1010#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Into)]
1011/// A fraction between 0 and 1 with a precision of 1/100_000.
1012/// The `Into<u32>` implementation returns the number of parts per `100_000`.
1013pub struct PartsPerHundredThousands {
1014    pub(crate) parts: u32,
1015}
1016
1017impl PartsPerHundredThousands {
1018    /// Construct a new fraction given the integer number of parts per
1019    /// `100_000`. Return [`None`] if the number of parts exceeds `100_000`.
1020    pub fn new(parts: u32) -> Option<Self> {
1021        if parts <= 100_000 {
1022            Some(Self { parts })
1023        } else {
1024            None
1025        }
1026    }
1027
1028    /// Construct a new fraction, but does not check that the resulting fraction
1029    /// is valid.
1030    pub fn new_unchecked(parts: u32) -> Self {
1031        Self { parts }
1032    }
1033}
1034
1035impl From<PartsPerHundredThousands> for rust_decimal::Decimal {
1036    fn from(pp: PartsPerHundredThousands) -> Self {
1037        rust_decimal::Decimal::new(pp.parts.into(), 5)
1038    }
1039}
1040
1041impl Serial for PartsPerHundredThousands {
1042    fn serial<B: Buffer>(&self, out: &mut B) {
1043        self.parts.serial(out)
1044    }
1045}
1046
1047impl Deserial for PartsPerHundredThousands {
1048    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
1049        let parts: u32 = source.get()?;
1050        Self::new(parts)
1051            .ok_or_else(|| anyhow::anyhow!("No more than 100_000 parts per hundred thousand."))
1052    }
1053}
1054
1055/// Display the value as a fraction.
1056impl fmt::Display for PartsPerHundredThousands {
1057    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1058        let x = rust_decimal::Decimal::try_new(self.parts.into(), 5).map_err(|_| fmt::Error)?;
1059        x.fmt(f)
1060    }
1061}
1062
1063#[derive(SerdeSerialize, SerdeDeserialize, PartialEq, Eq, Serialize, Debug, Clone, Copy)]
1064pub struct CommissionRates {
1065    /// Fraction of finalization rewards charged by the pool owner.
1066    #[serde(rename = "finalizationCommission")]
1067    pub finalization: AmountFraction,
1068    /// Fraction of baking rewards charged by the pool owner.
1069    #[serde(rename = "bakingCommission")]
1070    pub baking: AmountFraction,
1071    /// Fraction of transaction rewards charged by the pool owner.
1072    #[serde(rename = "transactionCommission")]
1073    pub transaction: AmountFraction,
1074}
1075
1076#[derive(Serialize, SerdeSerialize, SerdeDeserialize, Debug, Clone)]
1077/// Ranges of allowed commission values that pools may choose from.
1078pub struct CommissionRanges {
1079    /// The range of allowed finalization commissions.
1080    #[serde(rename = "finalizationCommissionRange")]
1081    pub finalization: InclusiveRange<AmountFraction>,
1082    /// The range of allowed baker commissions.
1083    #[serde(rename = "bakingCommissionRange")]
1084    pub baking: InclusiveRange<AmountFraction>,
1085    /// The range of allowed transaction commissions.
1086    #[serde(rename = "transactionCommissionRange")]
1087    pub transaction: InclusiveRange<AmountFraction>,
1088}
1089
1090#[derive(Debug, Copy, Clone, SerdeSerialize, SerdeDeserialize, Eq, PartialEq)]
1091pub struct InclusiveRange<T> {
1092    pub min: T,
1093    pub max: T,
1094}
1095
1096impl<T: Serial> Serial for InclusiveRange<T> {
1097    fn serial<B: Buffer>(&self, out: &mut B) {
1098        self.min.serial(out);
1099        self.max.serial(out)
1100    }
1101}
1102
1103impl<T: Deserial + Ord> Deserial for InclusiveRange<T> {
1104    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
1105        let min = source.get()?;
1106        let max = source.get()?;
1107        anyhow::ensure!(min <= max, "Invalid range.");
1108        Ok(Self { min, max })
1109    }
1110}
1111
1112impl<T: Ord> InclusiveRange<T> {
1113    pub fn contains(&self, x: &T) -> bool {
1114        &self.min <= x && x <= &self.max
1115    }
1116}
1117
1118#[derive(SerdeSerialize, SerdeDeserialize, Serial, Debug, Clone, Copy, Eq, PartialEq)]
1119#[serde(try_from = "leverage_factor_json::LeverageFactorRaw")]
1120/// The amount of leverage that a baker can get from delegation. A leverage
1121/// factor of 1 means that a baker does not gain anything from delegation.
1122pub struct LeverageFactor {
1123    #[serde(deserialize_with = "crate::internal::deserialize_non_default::deserialize")]
1124    pub numerator: u64,
1125    #[serde(deserialize_with = "crate::internal::deserialize_non_default::deserialize")]
1126    pub denominator: u64,
1127}
1128
1129impl LeverageFactor {
1130    /// Construct an integral leverage factor that is assumed to be at least 1.
1131    pub fn new_integral(factor: u64) -> Self {
1132        Self {
1133            numerator: factor,
1134            denominator: 1,
1135        }
1136    }
1137
1138    /// Construct a new leverage factor from a numerator and denominator,
1139    /// checking that it is well-formed.
1140    pub fn new(numerator: u64, denominator: u64) -> Option<Self> {
1141        if numerator >= denominator
1142            && denominator != 0
1143            && num::integer::gcd(numerator, denominator) == 1
1144        {
1145            Some(Self {
1146                numerator,
1147                denominator,
1148            })
1149        } else {
1150            None
1151        }
1152    }
1153}
1154
1155/// An internal helper to deserialize a leverage factor and ensure that it is
1156/// in reduced form.
1157mod leverage_factor_json {
1158    #[derive(super::SerdeDeserialize)]
1159    pub struct LeverageFactorRaw {
1160        pub numerator: u64,
1161        pub denominator: u64,
1162    }
1163
1164    impl std::convert::TryFrom<LeverageFactorRaw> for super::LeverageFactor {
1165        type Error = anyhow::Error;
1166
1167        fn try_from(value: LeverageFactorRaw) -> Result<Self, Self::Error> {
1168            let numerator = value.numerator;
1169            let denominator = value.denominator;
1170            super::LeverageFactor::new(numerator, denominator)
1171                .ok_or_else(|| anyhow::anyhow!("Invalid leverage factor."))
1172        }
1173    }
1174}
1175
1176impl Deserial for LeverageFactor {
1177    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
1178        let numerator = source.get()?;
1179        let denominator = source.get()?;
1180        Self::new(numerator, denominator).ok_or_else(|| anyhow::anyhow!("Invalid leverage factor."))
1181    }
1182}
1183
1184#[derive(SerdeSerialize, SerdeDeserialize, Serial, Debug, Clone)]
1185#[serde(rename_all = "camelCase")]
1186/// Mint distribution that applies to protocol versions 1-3.
1187pub struct MintDistributionV0 {
1188    /// The increase in CCD amount per slot.
1189    pub mint_per_slot: MintRate,
1190    /// Fraction of newly minted CCD allocated to baker rewards.
1191    pub baking_reward: AmountFraction,
1192    /// Fraction of newly minted CCD allocated to finalization rewards.
1193    pub finalization_reward: AmountFraction,
1194}
1195
1196#[derive(SerdeSerialize, SerdeDeserialize, Serial, Debug, Clone)]
1197#[serde(rename_all = "camelCase")]
1198/// Mint distribution parameters that apply to protocol version 4 and up.
1199pub struct MintDistributionV1 {
1200    /// Fraction of newly minted CCD allocated to baker rewards.
1201    pub baking_reward: AmountFraction,
1202    /// Fraction of newly minted CCD allocated to finalization rewards.
1203    pub finalization_reward: AmountFraction,
1204}
1205
1206impl Deserial for MintDistributionV0 {
1207    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
1208        let mint_per_slot = source.get()?;
1209        let baking_reward: AmountFraction = source.get()?;
1210        let finalization_reward: AmountFraction = source.get()?;
1211        anyhow::ensure!(
1212            (baking_reward + finalization_reward).is_some(),
1213            "Reward fractions exceed 100%."
1214        );
1215        Ok(Self {
1216            mint_per_slot,
1217            baking_reward,
1218            finalization_reward,
1219        })
1220    }
1221}
1222
1223impl Deserial for MintDistributionV1 {
1224    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
1225        let baking_reward: AmountFraction = source.get()?;
1226        let finalization_reward: AmountFraction = source.get()?;
1227        anyhow::ensure!(
1228            (baking_reward + finalization_reward).is_some(),
1229            "Reward fractions exceed 100%."
1230        );
1231        Ok(Self {
1232            baking_reward,
1233            finalization_reward,
1234        })
1235    }
1236}
1237
1238#[derive(Debug, Serialize, Clone, Copy, Eq, PartialEq)]
1239/// Rate of creation of new CCDs. For example, A value of `0.05` would mean an
1240/// increase of 5 percent per unit of time. This value does not specify the time
1241/// unit, and this differs based on the protocol version.
1242///
1243/// The representation is base-10 floating point number representation.
1244/// The value is `mantissa * 10^(-exponent)`.
1245///
1246/// Note that the `Eq` instance is representational, so it is possible for
1247/// two `MintRate`s that represent the same number not be be equal. (For
1248/// example, 1 * 10^(-1) and 10 * 10^(-2).)
1249pub struct MintRate {
1250    pub mantissa: u32,
1251    pub exponent: u8,
1252}
1253
1254#[derive(
1255    Default,
1256    Debug,
1257    Display,
1258    Clone,
1259    Copy,
1260    SerdeSerialize,
1261    SerdeDeserialize,
1262    Serialize,
1263    PartialEq,
1264    Eq,
1265    PartialOrd,
1266    Ord,
1267    Into,
1268    FromStr,
1269)]
1270#[serde(transparent)]
1271/// A fraction of an amount with a precision of `1/100_000`.
1272/// The [`FromStr`] instance will parse a decimal fraction with up to `5`
1273/// decimals.
1274pub struct AmountFraction {
1275    pub(crate) parts_per_hundred_thousands: PartsPerHundredThousands,
1276}
1277
1278impl AmountFraction {
1279    /// Construct a new fraction given the integer number of parts per
1280    /// `100_000`. Return [`None`] if the number of parts exceeds `100_000`.
1281    pub fn new(parts: u32) -> Option<Self> {
1282        let parts_per_hundred_thousands = PartsPerHundredThousands::new(parts)?;
1283        Some(Self {
1284            parts_per_hundred_thousands,
1285        })
1286    }
1287
1288    /// Construct a new fraction, but does not check that the resulting fraction
1289    /// is valid.
1290    pub fn new_unchecked(parts: u32) -> Self {
1291        Self {
1292            parts_per_hundred_thousands: PartsPerHundredThousands::new_unchecked(parts),
1293        }
1294    }
1295}
1296
1297#[repr(transparent)]
1298#[derive(
1299    Debug, Clone, Copy, SerdeSerialize, SerdeDeserialize, Serialize, FromStr, Eq, PartialEq,
1300)]
1301#[serde(transparent)]
1302/// A bound on the relative share of the total staked capital that a baker can
1303/// have as its stake. This is required to be greater than 0.
1304pub struct CapitalBound {
1305    #[serde(deserialize_with = "crate::internal::deserialize_non_default::deserialize")]
1306    pub bound: AmountFraction,
1307}
1308
1309#[repr(transparent)]
1310#[derive(SerdeSerialize, SerdeDeserialize, Serialize)]
1311#[serde(transparent)]
1312#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, FromStr, Display, From, Into)]
1313/// Sequential index of finalization.
1314pub struct FinalizationIndex {
1315    pub index: u64,
1316}
1317
1318/// Add two parts, checking that the result is still less than 100_000.
1319impl std::ops::Add for PartsPerHundredThousands {
1320    type Output = Option<Self>;
1321
1322    fn add(self, rhs: Self) -> Self::Output {
1323        let parts = self.parts.checked_add(rhs.parts)?;
1324        if parts <= 100_000 {
1325            Some(PartsPerHundredThousands { parts })
1326        } else {
1327            None
1328        }
1329    }
1330}
1331
1332/// Add two reward fractions checking that they sum up to no more than 1.
1333impl std::ops::Add for AmountFraction {
1334    type Output = Option<Self>;
1335
1336    fn add(self, rhs: Self) -> Self::Output {
1337        let parts_per_hundred_thousands =
1338            (self.parts_per_hundred_thousands + rhs.parts_per_hundred_thousands)?;
1339        Some(AmountFraction {
1340            parts_per_hundred_thousands,
1341        })
1342    }
1343}
1344
1345impl SerdeSerialize for PartsPerHundredThousands {
1346    fn serialize<S: serde::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
1347        let decimal = rust_decimal::Decimal::try_new(self.parts.into(), 5)
1348            .map_err(serde::ser::Error::custom)?;
1349        SerdeSerialize::serialize(&decimal, ser)
1350    }
1351}
1352
1353#[derive(Clone, PartialEq, Debug, Error)]
1354/// An error that may be raised by converting from a
1355/// [`Decimal`](rust_decimal::Decimal) to a [`PartsPerHundredThousands`].
1356pub enum ConvertPartsPerHundredThousandsError {
1357    #[error("Parts per thousand should not have more than 5 decimals.")]
1358    TooManyDecimals,
1359    #[error("Parts per thousand should not be negative.")]
1360    Negative,
1361    #[error("Parts per thousand out of bounds.")]
1362    OutOfBounds,
1363    #[error("Scale out of bounds.")]
1364    ScaleError {
1365        #[from]
1366        inner: rust_decimal::Error,
1367    },
1368}
1369
1370impl TryFrom<rust_decimal::Decimal> for PartsPerHundredThousands {
1371    type Error = ConvertPartsPerHundredThousandsError;
1372
1373    fn try_from(value: rust_decimal::Decimal) -> Result<Self, Self::Error> {
1374        let mut f = value;
1375        f.normalize_assign();
1376        if f.scale() > 5 {
1377            return Err(ConvertPartsPerHundredThousandsError::TooManyDecimals);
1378        }
1379        if !f.is_sign_positive() && !f.is_zero() {
1380            return Err(ConvertPartsPerHundredThousandsError::Negative);
1381        }
1382        f.rescale(5);
1383        if f.mantissa() > 100_000 {
1384            return Err(ConvertPartsPerHundredThousandsError::OutOfBounds);
1385        }
1386        Ok(PartsPerHundredThousands {
1387            parts: f.mantissa() as u32,
1388        })
1389    }
1390}
1391
1392impl FromStr for PartsPerHundredThousands {
1393    type Err = ConvertPartsPerHundredThousandsError;
1394
1395    fn from_str(s: &str) -> Result<Self, Self::Err> {
1396        let decimal: rust_decimal::Decimal = s.parse()?;
1397        Self::try_from(decimal)
1398    }
1399}
1400
1401impl<'de> SerdeDeserialize<'de> for PartsPerHundredThousands {
1402    fn deserialize<D: serde::Deserializer<'de>>(des: D) -> Result<Self, D::Error> {
1403        let f: rust_decimal::Decimal =
1404            SerdeDeserialize::deserialize(des).map_err(serde::de::Error::custom)?;
1405        let parts = PartsPerHundredThousands::try_from(f).map_err(serde::de::Error::custom)?;
1406        Ok(parts)
1407    }
1408}
1409
1410impl SerdeSerialize for MintRate {
1411    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1412    where
1413        S: serde::Serializer,
1414    {
1415        let x = rust_decimal::Decimal::try_new(self.mantissa.into(), self.exponent.into())
1416            .map_err(serde::ser::Error::custom)?;
1417        SerdeSerialize::serialize(&x, serializer)
1418    }
1419}
1420
1421impl FromStr for MintRate {
1422    type Err = anyhow::Error;
1423
1424    fn from_str(s: &str) -> Result<Self, Self::Err> {
1425        let f: rust_decimal::Decimal = s.parse()?;
1426        f.try_into()
1427    }
1428}
1429
1430impl TryFrom<rust_decimal::Decimal> for MintRate {
1431    type Error = anyhow::Error;
1432
1433    fn try_from(mut value: rust_decimal::Decimal) -> Result<Self, Self::Error> {
1434        // FIXME: exponents will only be 28 at most for this type, so it is not entirely
1435        // compatible with the Haskell code.
1436        value.normalize_assign();
1437        if let Ok(exponent) = u8::try_from(value.scale()) {
1438            if let Ok(mantissa) = u32::try_from(value.mantissa()) {
1439                Ok(MintRate { mantissa, exponent })
1440            } else {
1441                anyhow::bail!("Unsupported mantissa range for MintRate.",);
1442            }
1443        } else {
1444            anyhow::bail!("Unsupported exponent range for MintRate.");
1445        }
1446    }
1447}
1448
1449impl<'de> SerdeDeserialize<'de> for MintRate {
1450    fn deserialize<D>(des: D) -> Result<Self, D::Error>
1451    where
1452        D: serde::Deserializer<'de>,
1453    {
1454        let f: rust_decimal::Decimal = SerdeDeserialize::deserialize(des)?;
1455        MintRate::try_from(f).map_err(serde::de::Error::custom)
1456    }
1457}
1458
1459#[cfg(test)]
1460mod tests {
1461    use super::*;
1462    #[test]
1463    fn test_parts_0() {
1464        assert_eq!(
1465            Ok(PartsPerHundredThousands::new_unchecked(12345)),
1466            "0.12345".parse(),
1467            "Case 1."
1468        );
1469        assert_eq!(
1470            Ok(PartsPerHundredThousands::new_unchecked(12345)),
1471            "0.123450".parse(),
1472            "Case 2."
1473        );
1474        assert_eq!(
1475            Ok(PartsPerHundredThousands::new_unchecked(12300)),
1476            "0.123".parse(),
1477            "Case 3."
1478        );
1479        assert_eq!(
1480            Ok(PartsPerHundredThousands::new_unchecked(12300)),
1481            "0.123000".parse(),
1482            "Case 4."
1483        );
1484        assert!("0.123456".parse::<PartsPerHundredThousands>().is_err());
1485    }
1486
1487    #[test]
1488    fn test_parts_json() {
1489        assert_eq!(
1490            PartsPerHundredThousands::new_unchecked(12345),
1491            serde_json::from_str("0.12345").unwrap(),
1492            "Case 1."
1493        );
1494        assert_eq!(
1495            PartsPerHundredThousands::new_unchecked(12345),
1496            serde_json::from_str("0.123450").unwrap(),
1497            "Case 2."
1498        );
1499        assert_eq!(
1500            PartsPerHundredThousands::new_unchecked(12300),
1501            serde_json::from_str("0.123").unwrap(),
1502            "Case 3."
1503        );
1504        assert_eq!(
1505            PartsPerHundredThousands::new_unchecked(12300),
1506            serde_json::from_str("0.123000").unwrap(),
1507            "Case 4."
1508        );
1509        assert!(serde_json::from_str::<PartsPerHundredThousands>("0.123456").is_err());
1510    }
1511}