1use 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#[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)]
58pub 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 let len: u16 = source.get()?;
199 let mut bytes = vec![0u8; len.into()]; source.read_exact(&mut bytes)?;
201 Ok(OwnedParameter::new_unchecked(bytes))
202 }
203}
204
205#[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#[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 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 pub fn new_unchecked(numerator: u64, denominator: u64) -> Self {
250 Self {
251 numerator,
252 denominator,
253 }
254 }
255
256 pub fn numerator(&self) -> u64 { self.numerator }
258
259 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#[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)]
307pub 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 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#[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 pub fn num_signatures(&self) -> u32 {
376 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#[derive(
422 SerdeDeserialize, SerdeSerialize, PartialEq, Eq, Debug, Serialize, Clone, Copy, PartialOrd, Ord,
423)]
424#[serde(transparent)]
425pub struct TransactionTime {
426 pub seconds: u64,
428}
429
430impl TransactionTime {
431 pub fn from_seconds(seconds: u64) -> Self { Self { seconds } }
433
434 pub fn seconds_after(seconds: u32) -> Self {
436 Self::from_seconds(chrono::offset::Utc::now().timestamp() as u64 + u64::from(seconds))
437 }
438
439 pub fn minutes_after(minutes: u32) -> Self { Self::seconds_after(minutes * 60) }
441
442 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#[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 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}