concordium_base/common/
types.rs

1//! Common types needed in concordium.
2
3use super::{
4    deserial_string, serial_string, Buffer, Deserial, Get, ParseResult, SerdeDeserialize,
5    SerdeSerialize, Serial,
6};
7use crate::common::Serialize;
8use byteorder::{BigEndian, ReadBytesExt};
9use concordium_contracts_common::{
10    self as concordium_std, ContractAddress, ContractName, OwnedContractName, OwnedParameter,
11    OwnedReceiveName, Parameter, ReceiveName,
12};
13pub use concordium_contracts_common::{
14    AccountAddress, Address, Amount, Timestamp, ACCOUNT_ADDRESS_SIZE,
15};
16use derive_more::{Display, From, FromStr, Into};
17use ed25519_dalek::Signer;
18use std::{collections::BTreeMap, num::ParseIntError, str::FromStr};
19/// Index of an account key that is to be used.
20#[derive(
21    Debug,
22    PartialEq,
23    Eq,
24    PartialOrd,
25    Ord,
26    Clone,
27    Copy,
28    Hash,
29    Serialize,
30    Display,
31    From,
32    Into,
33    concordium_std::Serialize,
34)]
35#[repr(transparent)]
36#[derive(SerdeSerialize)]
37#[serde(transparent)]
38pub struct KeyIndex(pub u8);
39
40#[derive(
41    SerdeSerialize,
42    SerdeDeserialize,
43    Serialize,
44    Copy,
45    Clone,
46    Eq,
47    PartialEq,
48    Ord,
49    PartialOrd,
50    Debug,
51    FromStr,
52    Display,
53    From,
54    Into,
55    concordium_std::Serialize,
56)]
57#[serde(transparent)]
58/// Index of the credential that is to be used.
59pub struct CredentialIndex {
60    pub index: u8,
61}
62
63impl Serial for Amount {
64    fn serial<B: super::Buffer>(&self, out: &mut B) { self.micro_ccd().serial(out) }
65}
66
67impl Deserial for Amount {
68    fn deserial<R: byteorder::ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
69        let micro_ccd = source.get()?;
70        Ok(Amount::from_micro_ccd(micro_ccd))
71    }
72}
73
74impl Serial for Address {
75    fn serial<B: Buffer>(&self, out: &mut B) {
76        match self {
77            Address::Account(acc) => {
78                0u8.serial(out);
79                acc.serial(out)
80            }
81            Address::Contract(ca) => {
82                1u8.serial(out);
83                ca.serial(out)
84            }
85        }
86    }
87}
88
89impl Deserial for Address {
90    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
91        match u8::deserial(source)? {
92            0u8 => Ok(Self::Account(source.get()?)),
93            1u8 => Ok(Self::Contract(source.get()?)),
94            _ => anyhow::bail!("Unsupported address type."),
95        }
96    }
97}
98
99impl Serial for AccountAddress {
100    #[inline]
101    fn serial<B: Buffer>(&self, x: &mut B) {
102        x.write_all(&self.0)
103            .expect("Writing to buffer should succeed.")
104    }
105}
106
107impl Deserial for AccountAddress {
108    #[inline]
109    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
110        let mut buf = [0u8; ACCOUNT_ADDRESS_SIZE];
111        source.read_exact(&mut buf)?;
112        Ok(AccountAddress(buf))
113    }
114}
115
116impl Serial for ContractAddress {
117    #[inline]
118    fn serial<B: Buffer>(&self, x: &mut B) {
119        x.write_u64::<BigEndian>(self.index)
120            .expect("Writing to buffer should succeed.");
121        x.write_u64::<BigEndian>(self.subindex)
122            .expect("Writing to buffer should succeed.");
123    }
124}
125
126impl Deserial for ContractAddress {
127    #[inline]
128    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
129        let index = source.read_u64::<BigEndian>()?;
130        let subindex = source.read_u64::<BigEndian>()?;
131        Ok(ContractAddress::new(index, subindex))
132    }
133}
134
135impl Serial for ReceiveName<'_> {
136    #[inline]
137    fn serial<B: Buffer>(&self, out: &mut B) {
138        let string = self.get_chain_name();
139        (string.len() as u16).serial(out);
140        serial_string(string, out)
141    }
142}
143
144impl Serial for OwnedReceiveName {
145    #[inline]
146    fn serial<B: Buffer>(&self, x: &mut B) { self.as_receive_name().serial(x) }
147}
148
149impl Deserial for OwnedReceiveName {
150    #[inline]
151    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
152        let len: u16 = source.get()?;
153        let name = deserial_string(source, len.into())?;
154        Ok(OwnedReceiveName::new(name)?)
155    }
156}
157
158impl Serial for ContractName<'_> {
159    #[inline]
160    fn serial<B: Buffer>(&self, out: &mut B) {
161        let string = self.get_chain_name();
162        (string.len() as u16).serial(out);
163        serial_string(string, out)
164    }
165}
166
167impl Serial for OwnedContractName {
168    #[inline]
169    fn serial<B: Buffer>(&self, x: &mut B) { self.as_contract_name().serial(x) }
170}
171
172impl Deserial for OwnedContractName {
173    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
174        let len: u16 = source.get()?;
175        let name = deserial_string(source, len.into())?;
176        Ok(OwnedContractName::new(name)?)
177    }
178}
179
180impl Serial for Parameter<'_> {
181    fn serial<B: Buffer>(&self, out: &mut B) {
182        let bytes = self.as_ref();
183        (bytes.len() as u16).serial(out);
184        out.write_all(bytes)
185            .expect("Writing to buffer should succeed.")
186    }
187}
188
189impl Serial for OwnedParameter {
190    #[inline]
191    fn serial<B: Buffer>(&self, out: &mut B) { self.as_parameter().serial(out) }
192}
193
194impl Deserial for OwnedParameter {
195    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
196        // Since `MAX_PARAMETER_LEN == u16::MAX`, we don't need to check it explicitly.
197        // The constant exists in concordium_contracts_common::constants.
198        let len: u16 = source.get()?;
199        let mut bytes = vec![0u8; len.into()]; // Safe to preallocate since len fits `u16`.
200        source.read_exact(&mut bytes)?;
201        Ok(OwnedParameter::new_unchecked(bytes))
202    }
203}
204
205/// A ratio between two `u64` integers.
206///
207/// It should be safe to assume the denominator is not zero and that numerator
208/// and denominator are coprime.
209///
210/// This type is introduced (over using `num::rational::Ratio<u64>`) to add the
211/// above requirements and to provide implementations for `serde::Serialize` and
212/// `serde::Deserialize`.
213#[derive(Debug, SerdeDeserialize, SerdeSerialize, Serial, Clone, Copy)]
214#[serde(try_from = "rust_decimal::Decimal", into = "rust_decimal::Decimal")]
215pub struct Ratio {
216    numerator:   u64,
217    denominator: u64,
218}
219
220/// Error during creating a new ratio.
221#[derive(Debug, Clone, thiserror::Error)]
222pub enum NewRatioError {
223    #[error("Denominator cannot be 0.")]
224    ZeroDenominator,
225    #[error("Numerator and denominator must be coprime.")]
226    NotCoprime,
227}
228
229impl Ratio {
230    /// Construct a new ratio. Returns an error if denominator is non-zero or
231    /// numerator and denominator are not coprime.
232    pub fn new(numerator: u64, denominator: u64) -> Result<Self, NewRatioError> {
233        if denominator == 0 {
234            return Err(NewRatioError::ZeroDenominator);
235        }
236        if num::Integer::gcd(&numerator, &denominator) != 1 {
237            return Err(NewRatioError::NotCoprime);
238        }
239        Ok(Self {
240            numerator,
241            denominator,
242        })
243    }
244
245    /// Construct a new ratio without checking anything.
246    ///
247    /// It is up to the caller to ensure the denominator is not zero and that
248    /// numerator and denominator are coprime.
249    pub fn new_unchecked(numerator: u64, denominator: u64) -> Self {
250        Self {
251            numerator,
252            denominator,
253        }
254    }
255
256    /// Get the numerator of the ratio.
257    pub fn numerator(&self) -> u64 { self.numerator }
258
259    /// Get the denominator of the ratio.
260    pub fn denominator(&self) -> u64 { self.denominator }
261}
262
263impl Deserial for Ratio {
264    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
265        let numerator: u64 = source.get()?;
266        let denominator: u64 = source.get()?;
267        Ok(Self::new(numerator, denominator)?)
268    }
269}
270
271impl From<Ratio> for rust_decimal::Decimal {
272    fn from(ratio: Ratio) -> rust_decimal::Decimal {
273        rust_decimal::Decimal::from(ratio.numerator)
274            / rust_decimal::Decimal::from(ratio.denominator)
275    }
276}
277
278/// Error from converting a decimal to a [`Ratio`].
279#[derive(Debug, Clone, thiserror::Error)]
280#[error("Unrepresentable number.")]
281pub struct RatioFromDecimalError;
282
283impl TryFrom<rust_decimal::Decimal> for Ratio {
284    type Error = RatioFromDecimalError;
285
286    fn try_from(mut value: rust_decimal::Decimal) -> Result<Self, Self::Error> {
287        value.normalize_assign();
288        let mantissa = value.mantissa();
289        let scale = value.scale();
290        let denominator = 10u64.checked_pow(scale).ok_or(RatioFromDecimalError)?;
291        let numerator: u64 = mantissa.try_into().map_err(|_| RatioFromDecimalError)?;
292        let g = num::Integer::gcd(&numerator, &denominator);
293        let numerator = numerator / g;
294        let denominator = denominator / g;
295        Ok(Self {
296            numerator,
297            denominator,
298        })
299    }
300}
301
302impl From<Ratio> for num::rational::Ratio<u64> {
303    fn from(ratio: Ratio) -> Self { Self::new_raw(ratio.numerator, ratio.denominator) }
304}
305
306#[derive(Clone, PartialEq, Eq, Debug)]
307/// A single signature. Using the same binary and JSON serialization as the
308/// Haskell counterpart. In particular this means encoding the length as 2
309/// bytes, and thus the largest size is 65535 bytes.
310pub struct Signature {
311    pub sig: Vec<u8>,
312}
313
314impl From<ed25519_dalek::Signature> for Signature {
315    fn from(value: ed25519_dalek::Signature) -> Self {
316        Self {
317            sig: value.to_vec(),
318        }
319    }
320}
321
322impl Serial for Signature {
323    fn serial<B: Buffer>(&self, out: &mut B) {
324        (self.sig.len() as u16).serial(out);
325        out.write_all(&self.sig)
326            .expect("Writing to buffer should succeed.");
327    }
328}
329
330impl Deserial for Signature {
331    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
332        let len: u16 = source.get()?;
333        // allocating is safe because len is a u16
334        let mut sig = vec![0; len as usize];
335        source.read_exact(&mut sig)?;
336        Ok(Signature { sig })
337    }
338}
339
340impl SerdeSerialize for Signature {
341    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
342    where
343        S: serde::Serializer, {
344        serializer.serialize_str(&hex::encode(&self.sig))
345    }
346}
347
348impl<'de> SerdeDeserialize<'de> for Signature {
349    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
350    where
351        D: serde::Deserializer<'de>, {
352        let s = String::deserialize(deserializer)?;
353        let sig = hex::decode(s).map_err(|e| serde::de::Error::custom(format!("{}", e)))?;
354        if sig.len() <= 65535 {
355            Ok(Signature { sig })
356        } else {
357            Err(serde::de::Error::custom("Signature length out of bounds."))
358        }
359    }
360}
361
362impl AsRef<[u8]> for Signature {
363    fn as_ref(&self) -> &[u8] { &self.sig }
364}
365
366/// Transaction signature structure, to match the one on the Haskell side.
367#[derive(SerdeDeserialize, SerdeSerialize, Clone, PartialEq, Eq, Debug, derive_more::AsRef)]
368#[serde(transparent)]
369pub struct TransactionSignature {
370    pub signatures: BTreeMap<CredentialIndex, BTreeMap<KeyIndex, Signature>>,
371}
372
373impl TransactionSignature {
374    /// The total number of signatures.
375    pub fn num_signatures(&self) -> u32 {
376        // Since there are at most 256 credential indices, and at most 256 key indices
377        // using `as` is safe.
378        let x: usize = self.signatures.values().map(|sigs| sigs.len()).sum();
379        x as u32
380    }
381}
382
383impl Serial for TransactionSignature {
384    fn serial<B: Buffer>(&self, out: &mut B) {
385        let l = self.signatures.len() as u8;
386        l.serial(out);
387        for (idx, map) in self.signatures.iter() {
388            idx.serial(out);
389            (map.len() as u8).serial(out);
390            super::serial_map_no_length(map, out);
391        }
392    }
393}
394
395impl Deserial for TransactionSignature {
396    fn deserial<R: ReadBytesExt>(source: &mut R) -> ParseResult<Self> {
397        let num_creds: u8 = source.get()?;
398        anyhow::ensure!(num_creds > 0, "Number of signatures must not be 0.");
399        let mut out = BTreeMap::new();
400        let mut last = None;
401        for _ in 0..num_creds {
402            let idx = source.get()?;
403            anyhow::ensure!(
404                last < Some(idx),
405                "Credential indices must be strictly increasing."
406            );
407            last = Some(idx);
408            let inner_len: u8 = source.get()?;
409            anyhow::ensure!(
410                inner_len > 0,
411                "Each credential must have at least one signature."
412            );
413            let inner_map = super::deserial_map_no_length(source, inner_len.into())?;
414            out.insert(idx, inner_map);
415        }
416        Ok(TransactionSignature { signatures: out })
417    }
418}
419
420/// Datatype used to indicate transaction expiry.
421#[derive(
422    SerdeDeserialize, SerdeSerialize, PartialEq, Eq, Debug, Serialize, Clone, Copy, PartialOrd, Ord,
423)]
424#[serde(transparent)]
425pub struct TransactionTime {
426    /// Seconds since the unix epoch.
427    pub seconds: u64,
428}
429
430impl TransactionTime {
431    /// Construct a timestamp from seconds since the unix epoch.
432    pub fn from_seconds(seconds: u64) -> Self { Self { seconds } }
433
434    /// Construct a timestamp that is the given amount of seconds in the future.
435    pub fn seconds_after(seconds: u32) -> Self {
436        Self::from_seconds(chrono::offset::Utc::now().timestamp() as u64 + u64::from(seconds))
437    }
438
439    /// Construct a timestamp that is the given amount of minutes in the future.
440    pub fn minutes_after(minutes: u32) -> Self { Self::seconds_after(minutes * 60) }
441
442    /// Construct a timestamp that is the given amount of hours in the future.
443    pub fn hours_after(hours: u32) -> Self { Self::minutes_after(hours * 60) }
444}
445
446impl From<u64> for TransactionTime {
447    fn from(seconds: u64) -> Self { Self { seconds } }
448}
449
450impl FromStr for TransactionTime {
451    type Err = ParseIntError;
452
453    fn from_str(s: &str) -> Result<Self, Self::Err> {
454        let seconds = u64::from_str(s)?;
455        Ok(Self { seconds })
456    }
457}
458
459/// A ed25519 keypair. This is available in the `ed25519::dalek` crate, but the
460/// JSON serialization there is not compatible with what we use, so we redefine
461/// it there.
462#[derive(
463    Debug,
464    SerdeSerialize,
465    SerdeDeserialize,
466    derive_more::AsRef,
467    derive_more::From,
468    derive_more::Into,
469    Clone,
470)]
471#[serde(try_from = "key_pair_json::KeyPair", into = "key_pair_json::KeyPair")]
472pub struct KeyPair {
473    inner: ed25519_dalek::SigningKey,
474}
475
476impl KeyPair {
477    pub fn public(&self) -> ed25519_dalek::VerifyingKey { self.inner.verifying_key() }
478}
479
480mod key_pair_json {
481    #[derive(Debug, super::SerdeSerialize, super::SerdeDeserialize)]
482    pub struct KeyPair {
483        #[serde(
484            rename = "signKey",
485            serialize_with = "crate::common::base16_encode_array",
486            deserialize_with = "crate::common::base16_decode_array"
487        )]
488        pub secret: ed25519_dalek::SecretKey,
489        #[serde(
490            rename = "verifyKey",
491            serialize_with = "crate::common::base16_encode",
492            deserialize_with = "crate::common::base16_decode"
493        )]
494        pub public: ed25519_dalek::VerifyingKey,
495    }
496
497    impl TryFrom<KeyPair> for super::KeyPair {
498        type Error = ed25519_dalek::SignatureError;
499
500        fn try_from(value: KeyPair) -> Result<Self, Self::Error> {
501            let inner = ed25519_dalek::SigningKey::from_bytes(&value.secret);
502            if inner.verifying_key() != value.public {
503                Err(Self::Error::from_source("Public/secret key mismatch."))
504            } else {
505                Ok(Self { inner })
506            }
507        }
508    }
509
510    impl From<super::KeyPair> for KeyPair {
511        fn from(value: super::KeyPair) -> Self {
512            Self {
513                secret: value.inner.to_bytes(),
514                public: value.inner.verifying_key(),
515            }
516        }
517    }
518}
519
520impl KeyPair {
521    pub fn generate<R: rand::CryptoRng + rand::Rng>(rng: &mut R) -> Self {
522        Self::from(ed25519_dalek::SigningKey::generate(rng))
523    }
524}
525
526impl KeyPair {
527    /// Sign the given message with the keypair.
528    pub fn sign(&self, msg: &[u8]) -> ed25519_dalek::Signature { self.inner.sign(msg) }
529}
530
531#[cfg(test)]
532mod tests {
533    use super::*;
534    use rand::{
535        distributions::{Distribution, Uniform},
536        Rng,
537    };
538
539    #[test]
540    fn transaction_signature_serialization() {
541        let mut rng = rand::thread_rng();
542        for _ in 0..100 {
543            let num_creds = rng.gen_range(1..30);
544            let mut signatures = BTreeMap::new();
545            for _ in 0..num_creds {
546                let num_keys = rng.gen_range(1..20);
547                let mut cred_sigs = BTreeMap::new();
548                for _ in 0..num_keys {
549                    let num_elems = rng.gen_range(0..200);
550                    let sig = Signature {
551                        sig: Uniform::new_inclusive(0, 255u8)
552                            .sample_iter(rng.clone())
553                            .take(num_elems)
554                            .collect(),
555                    };
556                    cred_sigs.insert(KeyIndex(rng.gen()), sig);
557                }
558                signatures.insert(CredentialIndex { index: rng.gen() }, cred_sigs);
559            }
560            let signatures = TransactionSignature { signatures };
561            let js = serde_json::to_string(&signatures).expect("Serialization should succeed.");
562            match serde_json::from_str::<TransactionSignature>(&js) {
563                Ok(s) => assert_eq!(s, signatures, "Deserialized incorrect value."),
564                Err(e) => panic!("{}", e),
565            }
566
567            let binary_result = crate::common::serialize_deserialize(&signatures)
568                .expect("Binary signature serialization is not invertible.");
569            assert_eq!(
570                binary_result, signatures,
571                "Binary signature parses incorrectly."
572            );
573        }
574    }
575
576    #[test]
577    fn amount_json_serialization() {
578        let mut rng = rand::thread_rng();
579        for _ in 0..1000 {
580            let amount = Amount::from_micro_ccd(rng.gen::<u64>());
581            let s = serde_json::to_string(&amount).expect("Could not serialize");
582            assert_eq!(
583                amount,
584                serde_json::from_str(&s).unwrap(),
585                "Could not deserialize amount."
586            );
587        }
588
589        let amount = Amount::from_micro_ccd(12345);
590        let s = serde_json::to_string(&amount).expect("Could not serialize");
591        assert_eq!(s, r#""12345""#, "Could not deserialize amount.");
592
593        assert!(
594            serde_json::from_str::<Amount>(r#""""#).is_err(),
595            "Parsed empty string, but should not."
596        );
597        assert!(
598            serde_json::from_str::<Amount>(r#""12f""#).is_err(),
599            "Parsed string with corrupt data at end, but should not."
600        );
601        assert!(
602            serde_json::from_str::<Amount>(r#""12345612312315415123123""#).is_err(),
603            "Parsed overflowing amount, but should not."
604        );
605    }
606}