linera_base/
data_types.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2// Copyright (c) Zefchain Labs, Inc.
3// SPDX-License-Identifier: Apache-2.0
4
5//! Core data-types used in the Linera protocol.
6
7#[cfg(with_testing)]
8use std::ops;
9use std::{
10    collections::BTreeSet,
11    fmt::{self, Display},
12    fs,
13    hash::Hash,
14    io, iter,
15    num::ParseIntError,
16    ops::{Bound, RangeBounds},
17    path::Path,
18    str::FromStr,
19};
20
21use async_graphql::{InputObject, SimpleObject};
22use custom_debug_derive::Debug;
23use linera_witty::{WitLoad, WitStore, WitType};
24use serde::{Deserialize, Deserializer, Serialize, Serializer};
25use thiserror::Error;
26
27#[cfg(with_metrics)]
28use crate::prometheus_util::MeasureLatency as _;
29use crate::{
30    crypto::{BcsHashable, CryptoError, CryptoHash},
31    doc_scalar, hex_debug, http,
32    identifiers::{
33        ApplicationId, BlobId, BlobType, ChainId, EventId, GenericApplicationId, ModuleId, StreamId,
34    },
35    limited_writer::{LimitedWriter, LimitedWriterError},
36    ownership::ChainOwnership,
37    time::{Duration, SystemTime},
38    vm::VmRuntime,
39};
40
41/// A non-negative amount of tokens.
42///
43/// This is a fixed-point fraction, with [`Amount::DECIMAL_PLACES`] digits after the point.
44/// [`Amount::ONE`] is one whole token, divisible into `10.pow(Amount::DECIMAL_PLACES)` parts.
45#[derive(
46    Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash, Default, Debug, WitType, WitLoad, WitStore,
47)]
48#[cfg_attr(
49    all(with_testing, not(target_arch = "wasm32")),
50    derive(test_strategy::Arbitrary)
51)]
52pub struct Amount(u128);
53
54#[derive(Serialize, Deserialize)]
55#[serde(rename = "Amount")]
56struct AmountString(String);
57
58#[derive(Serialize, Deserialize)]
59#[serde(rename = "Amount")]
60struct AmountU128(u128);
61
62impl Serialize for Amount {
63    fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
64        if serializer.is_human_readable() {
65            AmountString(self.to_string()).serialize(serializer)
66        } else {
67            AmountU128(self.0).serialize(serializer)
68        }
69    }
70}
71
72impl<'de> Deserialize<'de> for Amount {
73    fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
74        if deserializer.is_human_readable() {
75            let AmountString(s) = AmountString::deserialize(deserializer)?;
76            s.parse().map_err(serde::de::Error::custom)
77        } else {
78            Ok(Amount(AmountU128::deserialize(deserializer)?.0))
79        }
80    }
81}
82
83/// A block height to identify blocks in a chain.
84#[derive(
85    Eq,
86    PartialEq,
87    Ord,
88    PartialOrd,
89    Copy,
90    Clone,
91    Hash,
92    Default,
93    Debug,
94    Serialize,
95    Deserialize,
96    WitType,
97    WitLoad,
98    WitStore,
99)]
100#[cfg_attr(with_testing, derive(test_strategy::Arbitrary))]
101pub struct BlockHeight(pub u64);
102
103/// An identifier for successive attempts to decide a value in a consensus protocol.
104#[derive(
105    Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash, Default, Debug, Serialize, Deserialize,
106)]
107pub enum Round {
108    /// The initial fast round.
109    #[default]
110    Fast,
111    /// The N-th multi-leader round.
112    MultiLeader(u32),
113    /// The N-th single-leader round.
114    SingleLeader(u32),
115    /// The N-th round where the validators rotate as leaders.
116    Validator(u32),
117}
118
119/// A duration in microseconds.
120#[derive(
121    Eq,
122    PartialEq,
123    Ord,
124    PartialOrd,
125    Copy,
126    Clone,
127    Hash,
128    Default,
129    Debug,
130    Serialize,
131    Deserialize,
132    WitType,
133    WitLoad,
134    WitStore,
135)]
136pub struct TimeDelta(u64);
137
138impl TimeDelta {
139    /// Returns the given number of microseconds as a [`TimeDelta`].
140    pub const fn from_micros(micros: u64) -> Self {
141        TimeDelta(micros)
142    }
143
144    /// Returns the given number of milliseconds as a [`TimeDelta`].
145    pub const fn from_millis(millis: u64) -> Self {
146        TimeDelta(millis.saturating_mul(1_000))
147    }
148
149    /// Returns the given number of seconds as a [`TimeDelta`].
150    pub const fn from_secs(secs: u64) -> Self {
151        TimeDelta(secs.saturating_mul(1_000_000))
152    }
153
154    /// Returns the given duration, rounded to the nearest microsecond and capped to the maximum
155    /// [`TimeDelta`] value.
156    pub fn from_duration(duration: Duration) -> Self {
157        TimeDelta::from_micros(u64::try_from(duration.as_micros()).unwrap_or(u64::MAX))
158    }
159
160    /// Returns this [`TimeDelta`] as a number of microseconds.
161    pub const fn as_micros(&self) -> u64 {
162        self.0
163    }
164
165    /// Returns this [`TimeDelta`] as a [`Duration`].
166    pub const fn as_duration(&self) -> Duration {
167        Duration::from_micros(self.as_micros())
168    }
169}
170
171/// A timestamp, in microseconds since the Unix epoch.
172#[derive(
173    Eq,
174    PartialEq,
175    Ord,
176    PartialOrd,
177    Copy,
178    Clone,
179    Hash,
180    Default,
181    Debug,
182    Serialize,
183    Deserialize,
184    WitType,
185    WitLoad,
186    WitStore,
187)]
188pub struct Timestamp(u64);
189
190impl Timestamp {
191    /// Returns the current time according to the system clock.
192    pub fn now() -> Timestamp {
193        Timestamp(
194            SystemTime::UNIX_EPOCH
195                .elapsed()
196                .expect("system time should be after Unix epoch")
197                .as_micros()
198                .try_into()
199                .unwrap_or(u64::MAX),
200        )
201    }
202
203    /// Returns the number of microseconds since the Unix epoch.
204    pub const fn micros(&self) -> u64 {
205        self.0
206    }
207
208    /// Returns the [`TimeDelta`] between `other` and `self`, or zero if `other` is not earlier
209    /// than `self`.
210    pub const fn delta_since(&self, other: Timestamp) -> TimeDelta {
211        TimeDelta::from_micros(self.0.saturating_sub(other.0))
212    }
213
214    /// Returns the [`Duration`] between `other` and `self`, or zero if `other` is not
215    /// earlier than `self`.
216    pub const fn duration_since(&self, other: Timestamp) -> Duration {
217        Duration::from_micros(self.0.saturating_sub(other.0))
218    }
219
220    /// Returns the timestamp that is `duration` later than `self`.
221    pub const fn saturating_add(&self, duration: TimeDelta) -> Timestamp {
222        Timestamp(self.0.saturating_add(duration.0))
223    }
224
225    /// Returns the timestamp that is `duration` earlier than `self`.
226    pub const fn saturating_sub(&self, duration: TimeDelta) -> Timestamp {
227        Timestamp(self.0.saturating_sub(duration.0))
228    }
229
230    /// Returns a timestamp `micros` microseconds earlier than `self`, or the lowest possible value
231    /// if it would underflow.
232    pub const fn saturating_sub_micros(&self, micros: u64) -> Timestamp {
233        Timestamp(self.0.saturating_sub(micros))
234    }
235}
236
237impl From<u64> for Timestamp {
238    fn from(t: u64) -> Timestamp {
239        Timestamp(t)
240    }
241}
242
243impl Display for Timestamp {
244    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245        if let Some(date_time) = chrono::DateTime::from_timestamp(
246            (self.0 / 1_000_000) as i64,
247            ((self.0 % 1_000_000) * 1_000) as u32,
248        ) {
249            return date_time.naive_utc().fmt(f);
250        }
251        self.0.fmt(f)
252    }
253}
254
255/// Resources that an application may spend during the execution of transaction or an
256/// application call.
257#[derive(
258    Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, WitLoad, WitStore, WitType,
259)]
260pub struct Resources {
261    /// An amount of Wasm execution fuel.
262    pub wasm_fuel: u64,
263    /// An amount of EVM execution fuel.
264    pub evm_fuel: u64,
265    /// A number of read operations to be executed.
266    pub read_operations: u32,
267    /// A number of write operations to be executed.
268    pub write_operations: u32,
269    /// A number of bytes read from runtime.
270    pub bytes_runtime: u32,
271    /// A number of bytes to read.
272    pub bytes_to_read: u32,
273    /// A number of bytes to write.
274    pub bytes_to_write: u32,
275    /// A number of blobs to read.
276    pub blobs_to_read: u32,
277    /// A number of blobs to publish.
278    pub blobs_to_publish: u32,
279    /// A number of blob bytes to read.
280    pub blob_bytes_to_read: u32,
281    /// A number of blob bytes to publish.
282    pub blob_bytes_to_publish: u32,
283    /// A number of messages to be sent.
284    pub messages: u32,
285    /// The size of the messages to be sent.
286    // TODO(#1531): Account for the type of message to be sent.
287    pub message_size: u32,
288    /// An increase in the amount of storage space.
289    pub storage_size_delta: u32,
290    /// A number of service-as-oracle requests to be performed.
291    pub service_as_oracle_queries: u32,
292    /// A number of HTTP requests to be performed.
293    pub http_requests: u32,
294    // TODO(#1532): Account for the system calls that we plan on calling.
295    // TODO(#1533): Allow declaring calls to other applications instead of having to count them here.
296}
297
298/// A request to send a message.
299#[derive(Clone, Debug, Deserialize, Serialize, WitLoad, WitType)]
300#[cfg_attr(with_testing, derive(Eq, PartialEq, WitStore))]
301#[witty_specialize_with(Message = Vec<u8>)]
302pub struct SendMessageRequest<Message> {
303    /// The destination of the message.
304    pub destination: ChainId,
305    /// Whether the message is authenticated.
306    pub authenticated: bool,
307    /// Whether the message is tracked.
308    pub is_tracked: bool,
309    /// The grant resources forwarded with the message.
310    pub grant: Resources,
311    /// The message itself.
312    pub message: Message,
313}
314
315impl<Message> SendMessageRequest<Message>
316where
317    Message: Serialize,
318{
319    /// Serializes the internal `Message` type into raw bytes.
320    pub fn into_raw(self) -> SendMessageRequest<Vec<u8>> {
321        let message = bcs::to_bytes(&self.message).expect("Failed to serialize message");
322
323        SendMessageRequest {
324            destination: self.destination,
325            authenticated: self.authenticated,
326            is_tracked: self.is_tracked,
327            grant: self.grant,
328            message,
329        }
330    }
331}
332
333/// An error type for arithmetic errors.
334#[derive(Debug, Error)]
335#[allow(missing_docs)]
336pub enum ArithmeticError {
337    #[error("Number overflow")]
338    Overflow,
339    #[error("Number underflow")]
340    Underflow,
341}
342
343macro_rules! impl_wrapped_number {
344    ($name:ident, $wrapped:ident) => {
345        impl $name {
346            /// The zero value.
347            pub const ZERO: Self = Self(0);
348
349            /// The maximum value.
350            pub const MAX: Self = Self($wrapped::MAX);
351
352            /// Checked addition.
353            pub fn try_add(self, other: Self) -> Result<Self, ArithmeticError> {
354                let val = self
355                    .0
356                    .checked_add(other.0)
357                    .ok_or(ArithmeticError::Overflow)?;
358                Ok(Self(val))
359            }
360
361            /// Checked increment.
362            pub fn try_add_one(self) -> Result<Self, ArithmeticError> {
363                let val = self.0.checked_add(1).ok_or(ArithmeticError::Overflow)?;
364                Ok(Self(val))
365            }
366
367            /// Saturating addition.
368            pub const fn saturating_add(self, other: Self) -> Self {
369                let val = self.0.saturating_add(other.0);
370                Self(val)
371            }
372
373            /// Checked subtraction.
374            pub fn try_sub(self, other: Self) -> Result<Self, ArithmeticError> {
375                let val = self
376                    .0
377                    .checked_sub(other.0)
378                    .ok_or(ArithmeticError::Underflow)?;
379                Ok(Self(val))
380            }
381
382            /// Checked decrement.
383            pub fn try_sub_one(self) -> Result<Self, ArithmeticError> {
384                let val = self.0.checked_sub(1).ok_or(ArithmeticError::Underflow)?;
385                Ok(Self(val))
386            }
387
388            /// Saturating subtraction.
389            pub const fn saturating_sub(self, other: Self) -> Self {
390                let val = self.0.saturating_sub(other.0);
391                Self(val)
392            }
393
394            /// Checked in-place addition.
395            pub fn try_add_assign(&mut self, other: Self) -> Result<(), ArithmeticError> {
396                self.0 = self
397                    .0
398                    .checked_add(other.0)
399                    .ok_or(ArithmeticError::Overflow)?;
400                Ok(())
401            }
402
403            /// Checked in-place increment.
404            pub fn try_add_assign_one(&mut self) -> Result<(), ArithmeticError> {
405                self.0 = self.0.checked_add(1).ok_or(ArithmeticError::Overflow)?;
406                Ok(())
407            }
408
409            /// Saturating in-place addition.
410            pub const fn saturating_add_assign(&mut self, other: Self) {
411                self.0 = self.0.saturating_add(other.0);
412            }
413
414            /// Checked in-place subtraction.
415            pub fn try_sub_assign(&mut self, other: Self) -> Result<(), ArithmeticError> {
416                self.0 = self
417                    .0
418                    .checked_sub(other.0)
419                    .ok_or(ArithmeticError::Underflow)?;
420                Ok(())
421            }
422
423            /// Saturating multiplication.
424            pub const fn saturating_mul(&self, other: $wrapped) -> Self {
425                Self(self.0.saturating_mul(other))
426            }
427
428            /// Checked multiplication.
429            pub fn try_mul(self, other: $wrapped) -> Result<Self, ArithmeticError> {
430                let val = self.0.checked_mul(other).ok_or(ArithmeticError::Overflow)?;
431                Ok(Self(val))
432            }
433
434            /// Checked in-place multiplication.
435            pub fn try_mul_assign(&mut self, other: $wrapped) -> Result<(), ArithmeticError> {
436                self.0 = self.0.checked_mul(other).ok_or(ArithmeticError::Overflow)?;
437                Ok(())
438            }
439        }
440
441        impl From<$name> for $wrapped {
442            fn from(value: $name) -> Self {
443                value.0
444            }
445        }
446
447        // Cannot directly create values for a wrapped type, except for testing.
448        #[cfg(with_testing)]
449        impl From<$wrapped> for $name {
450            fn from(value: $wrapped) -> Self {
451                Self(value)
452            }
453        }
454
455        #[cfg(with_testing)]
456        impl ops::Add for $name {
457            type Output = Self;
458
459            fn add(self, other: Self) -> Self {
460                Self(self.0 + other.0)
461            }
462        }
463
464        #[cfg(with_testing)]
465        impl ops::Sub for $name {
466            type Output = Self;
467
468            fn sub(self, other: Self) -> Self {
469                Self(self.0 - other.0)
470            }
471        }
472
473        #[cfg(with_testing)]
474        impl ops::Mul<$wrapped> for $name {
475            type Output = Self;
476
477            fn mul(self, other: $wrapped) -> Self {
478                Self(self.0 * other)
479            }
480        }
481    };
482}
483
484impl TryFrom<BlockHeight> for usize {
485    type Error = ArithmeticError;
486
487    fn try_from(height: BlockHeight) -> Result<usize, ArithmeticError> {
488        usize::try_from(height.0).map_err(|_| ArithmeticError::Overflow)
489    }
490}
491
492/// Allows converting [`BlockHeight`] ranges to inclusive tuples of bounds.
493pub trait BlockHeightRangeBounds {
494    /// Returns the range as a tuple of inclusive bounds.
495    /// If the range is empty, returns `None`.
496    fn to_inclusive(&self) -> Option<(BlockHeight, BlockHeight)>;
497}
498
499impl<T: RangeBounds<BlockHeight>> BlockHeightRangeBounds for T {
500    fn to_inclusive(&self) -> Option<(BlockHeight, BlockHeight)> {
501        let start = match self.start_bound() {
502            Bound::Included(height) => *height,
503            Bound::Excluded(height) => height.try_add_one().ok()?,
504            Bound::Unbounded => BlockHeight(0),
505        };
506        let end = match self.end_bound() {
507            Bound::Included(height) => *height,
508            Bound::Excluded(height) => height.try_sub_one().ok()?,
509            Bound::Unbounded => BlockHeight::MAX,
510        };
511        if start > end {
512            return None;
513        }
514        Some((start, end))
515    }
516}
517
518impl_wrapped_number!(Amount, u128);
519impl_wrapped_number!(BlockHeight, u64);
520impl_wrapped_number!(TimeDelta, u64);
521
522impl Display for Amount {
523    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
524        // Print the wrapped integer, padded with zeros to cover a digit before the decimal point.
525        let places = Amount::DECIMAL_PLACES as usize;
526        let min_digits = places + 1;
527        let decimals = format!("{:0min_digits$}", self.0);
528        let integer_part = &decimals[..(decimals.len() - places)];
529        let fractional_part = decimals[(decimals.len() - places)..].trim_end_matches('0');
530
531        // For now, we never trim non-zero digits so we don't lose any precision.
532        let precision = f.precision().unwrap_or(0).max(fractional_part.len());
533        let sign = if f.sign_plus() && self.0 > 0 { "+" } else { "" };
534        // The amount of padding: desired width minus sign, point and number of digits.
535        let pad_width = f.width().map_or(0, |w| {
536            w.saturating_sub(precision)
537                .saturating_sub(sign.len() + integer_part.len() + 1)
538        });
539        let left_pad = match f.align() {
540            None | Some(fmt::Alignment::Right) => pad_width,
541            Some(fmt::Alignment::Center) => pad_width / 2,
542            Some(fmt::Alignment::Left) => 0,
543        };
544
545        for _ in 0..left_pad {
546            write!(f, "{}", f.fill())?;
547        }
548        write!(f, "{sign}{integer_part}.{fractional_part:0<precision$}")?;
549        for _ in left_pad..pad_width {
550            write!(f, "{}", f.fill())?;
551        }
552        Ok(())
553    }
554}
555
556#[derive(Error, Debug)]
557#[allow(missing_docs)]
558pub enum ParseAmountError {
559    #[error("cannot parse amount")]
560    Parse,
561    #[error("cannot represent amount: number too high")]
562    TooHigh,
563    #[error("cannot represent amount: too many decimal places after the point")]
564    TooManyDigits,
565}
566
567impl FromStr for Amount {
568    type Err = ParseAmountError;
569
570    fn from_str(src: &str) -> Result<Self, Self::Err> {
571        let mut result: u128 = 0;
572        let mut decimals: Option<u8> = None;
573        let mut chars = src.trim().chars().peekable();
574        if chars.peek() == Some(&'+') {
575            chars.next();
576        }
577        for char in chars {
578            match char {
579                '_' => {}
580                '.' if decimals.is_some() => return Err(ParseAmountError::Parse),
581                '.' => decimals = Some(Amount::DECIMAL_PLACES),
582                char => {
583                    let digit = u128::from(char.to_digit(10).ok_or(ParseAmountError::Parse)?);
584                    if let Some(d) = &mut decimals {
585                        *d = d.checked_sub(1).ok_or(ParseAmountError::TooManyDigits)?;
586                    }
587                    result = result
588                        .checked_mul(10)
589                        .and_then(|r| r.checked_add(digit))
590                        .ok_or(ParseAmountError::TooHigh)?;
591                }
592            }
593        }
594        result = result
595            .checked_mul(10u128.pow(decimals.unwrap_or(Amount::DECIMAL_PLACES) as u32))
596            .ok_or(ParseAmountError::TooHigh)?;
597        Ok(Amount(result))
598    }
599}
600
601impl Display for BlockHeight {
602    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
603        self.0.fmt(f)
604    }
605}
606
607impl FromStr for BlockHeight {
608    type Err = ParseIntError;
609
610    fn from_str(src: &str) -> Result<Self, Self::Err> {
611        Ok(Self(u64::from_str(src)?))
612    }
613}
614
615impl Display for Round {
616    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
617        match self {
618            Round::Fast => write!(f, "fast round"),
619            Round::MultiLeader(r) => write!(f, "multi-leader round {}", r),
620            Round::SingleLeader(r) => write!(f, "single-leader round {}", r),
621            Round::Validator(r) => write!(f, "validator round {}", r),
622        }
623    }
624}
625
626impl Round {
627    /// Whether the round is a multi-leader round.
628    pub fn is_multi_leader(&self) -> bool {
629        matches!(self, Round::MultiLeader(_))
630    }
631
632    /// Returns the round number if this is a multi-leader round, `None` otherwise.
633    pub fn multi_leader(&self) -> Option<u32> {
634        match self {
635            Round::MultiLeader(number) => Some(*number),
636            _ => None,
637        }
638    }
639
640    /// Whether the round is the fast round.
641    pub fn is_fast(&self) -> bool {
642        matches!(self, Round::Fast)
643    }
644
645    /// The index of a round amongst the rounds of the same category.
646    pub fn number(&self) -> u32 {
647        match self {
648            Round::Fast => 0,
649            Round::MultiLeader(r) | Round::SingleLeader(r) | Round::Validator(r) => *r,
650        }
651    }
652
653    /// The category of the round as a string.
654    pub fn type_name(&self) -> &'static str {
655        match self {
656            Round::Fast => "fast",
657            Round::MultiLeader(_) => "multi",
658            Round::SingleLeader(_) => "single",
659            Round::Validator(_) => "validator",
660        }
661    }
662}
663
664impl<'a> iter::Sum<&'a Amount> for Amount {
665    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
666        iter.fold(Self::ZERO, |a, b| a.saturating_add(*b))
667    }
668}
669
670impl Amount {
671    /// The base-10 exponent representing how much a token can be divided.
672    pub const DECIMAL_PLACES: u8 = 18;
673
674    /// One token.
675    pub const ONE: Amount = Amount(10u128.pow(Amount::DECIMAL_PLACES as u32));
676
677    /// Returns an `Amount` corresponding to that many tokens, or `Amount::MAX` if saturated.
678    pub const fn from_tokens(tokens: u128) -> Amount {
679        Self::ONE.saturating_mul(tokens)
680    }
681
682    /// Returns an `Amount` corresponding to that many millitokens, or `Amount::MAX` if saturated.
683    pub const fn from_millis(millitokens: u128) -> Amount {
684        Amount(10u128.pow(Amount::DECIMAL_PLACES as u32 - 3)).saturating_mul(millitokens)
685    }
686
687    /// Returns an `Amount` corresponding to that many microtokens, or `Amount::MAX` if saturated.
688    pub const fn from_micros(microtokens: u128) -> Amount {
689        Amount(10u128.pow(Amount::DECIMAL_PLACES as u32 - 6)).saturating_mul(microtokens)
690    }
691
692    /// Returns an `Amount` corresponding to that many nanotokens, or `Amount::MAX` if saturated.
693    pub const fn from_nanos(nanotokens: u128) -> Amount {
694        Amount(10u128.pow(Amount::DECIMAL_PLACES as u32 - 9)).saturating_mul(nanotokens)
695    }
696
697    /// Returns an `Amount` corresponding to that many attotokens.
698    pub const fn from_attos(attotokens: u128) -> Amount {
699        Amount(attotokens)
700    }
701
702    /// Helper function to obtain the 64 most significant bits of the balance.
703    pub const fn upper_half(self) -> u64 {
704        (self.0 >> 64) as u64
705    }
706
707    /// Helper function to obtain the 64 least significant bits of the balance.
708    pub const fn lower_half(self) -> u64 {
709        self.0 as u64
710    }
711
712    /// Divides this by the other amount. If the other is 0, it returns `u128::MAX`.
713    pub fn saturating_div(self, other: Amount) -> u128 {
714        self.0.checked_div(other.0).unwrap_or(u128::MAX)
715    }
716
717    /// Returns whether this amount is 0.
718    pub fn is_zero(&self) -> bool {
719        *self == Amount::ZERO
720    }
721}
722
723/// What created a chain.
724#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash, Debug, Serialize, Deserialize)]
725pub enum ChainOrigin {
726    /// The chain was created by the genesis configuration.
727    Root(u32),
728    /// The chain was created by a call from another chain.
729    Child {
730        /// The parent of this chain.
731        parent: ChainId,
732        /// The block height in the parent at which this chain was created.
733        block_height: BlockHeight,
734        /// The index of this chain among chains created at the same block height in the parent
735        /// chain.
736        chain_index: u32,
737    },
738}
739
740impl ChainOrigin {
741    /// Whether the chain was created by another chain.
742    pub fn is_child(&self) -> bool {
743        matches!(self, ChainOrigin::Child { .. })
744    }
745}
746
747/// A number identifying the configuration of the chain (aka the committee).
748#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash, Default, Debug)]
749pub struct Epoch(pub u32);
750
751impl Epoch {
752    /// The zero epoch.
753    pub const ZERO: Epoch = Epoch(0);
754}
755
756impl Serialize for Epoch {
757    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
758    where
759        S: serde::ser::Serializer,
760    {
761        if serializer.is_human_readable() {
762            serializer.serialize_str(&self.0.to_string())
763        } else {
764            serializer.serialize_newtype_struct("Epoch", &self.0)
765        }
766    }
767}
768
769impl<'de> Deserialize<'de> for Epoch {
770    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
771    where
772        D: serde::de::Deserializer<'de>,
773    {
774        if deserializer.is_human_readable() {
775            let s = String::deserialize(deserializer)?;
776            Ok(Epoch(u32::from_str(&s).map_err(serde::de::Error::custom)?))
777        } else {
778            #[derive(Deserialize)]
779            #[serde(rename = "Epoch")]
780            struct EpochDerived(u32);
781
782            let value = EpochDerived::deserialize(deserializer)?;
783            Ok(Self(value.0))
784        }
785    }
786}
787
788impl std::fmt::Display for Epoch {
789    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
790        write!(f, "{}", self.0)
791    }
792}
793
794impl std::str::FromStr for Epoch {
795    type Err = CryptoError;
796
797    fn from_str(s: &str) -> Result<Self, Self::Err> {
798        Ok(Epoch(s.parse()?))
799    }
800}
801
802impl From<u32> for Epoch {
803    fn from(value: u32) -> Self {
804        Epoch(value)
805    }
806}
807
808impl Epoch {
809    /// Tries to return an epoch with a number increased by one. Returns an error if an overflow
810    /// happens.
811    #[inline]
812    pub fn try_add_one(self) -> Result<Self, ArithmeticError> {
813        let val = self.0.checked_add(1).ok_or(ArithmeticError::Overflow)?;
814        Ok(Self(val))
815    }
816
817    /// Tries to return an epoch with a number decreased by one. Returns an error if an underflow
818    /// happens.
819    pub fn try_sub_one(self) -> Result<Self, ArithmeticError> {
820        let val = self.0.checked_sub(1).ok_or(ArithmeticError::Underflow)?;
821        Ok(Self(val))
822    }
823
824    /// Tries to add one to this epoch's number. Returns an error if an overflow happens.
825    #[inline]
826    pub fn try_add_assign_one(&mut self) -> Result<(), ArithmeticError> {
827        self.0 = self.0.checked_add(1).ok_or(ArithmeticError::Overflow)?;
828        Ok(())
829    }
830}
831
832/// The initial configuration for a new chain.
833#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
834pub struct InitialChainConfig {
835    /// The ownership configuration of the new chain.
836    pub ownership: ChainOwnership,
837    /// The epoch in which the chain is created.
838    pub epoch: Epoch,
839    /// Set of epochs active at the time of creation of the chain.
840    pub active_epochs: BTreeSet<Epoch>,
841    /// The initial chain balance.
842    pub balance: Amount,
843    /// The initial application permissions.
844    pub application_permissions: ApplicationPermissions,
845}
846
847/// Initial chain configuration and chain origin.
848#[derive(Eq, PartialEq, Clone, Hash, Debug, Serialize, Deserialize)]
849pub struct ChainDescription {
850    origin: ChainOrigin,
851    timestamp: Timestamp,
852    config: InitialChainConfig,
853}
854
855impl ChainDescription {
856    /// Creates a new [`ChainDescription`].
857    pub fn new(origin: ChainOrigin, config: InitialChainConfig, timestamp: Timestamp) -> Self {
858        Self {
859            origin,
860            config,
861            timestamp,
862        }
863    }
864
865    /// Returns the [`ChainId`] based on this [`ChainDescription`].
866    pub fn id(&self) -> ChainId {
867        ChainId::from(self)
868    }
869
870    /// Returns the [`ChainOrigin`] describing who created this chain.
871    pub fn origin(&self) -> ChainOrigin {
872        self.origin
873    }
874
875    /// Returns a reference to the [`InitialChainConfig`] of the chain.
876    pub fn config(&self) -> &InitialChainConfig {
877        &self.config
878    }
879
880    /// Returns the timestamp of when the chain was created.
881    pub fn timestamp(&self) -> Timestamp {
882        self.timestamp
883    }
884
885    /// Whether the chain was created by another chain.
886    pub fn is_child(&self) -> bool {
887        self.origin.is_child()
888    }
889}
890
891impl BcsHashable<'_> for ChainDescription {}
892
893/// A description of the current Linera network to be stored in every node's database.
894#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
895pub struct NetworkDescription {
896    /// The name of the network.
897    pub name: String,
898    /// Hash of the network's genesis config.
899    pub genesis_config_hash: CryptoHash,
900    /// Genesis timestamp.
901    pub genesis_timestamp: Timestamp,
902    /// Hash of the blob containing the genesis committee.
903    pub genesis_committee_blob_hash: CryptoHash,
904    /// The chain ID of the admin chain.
905    pub admin_chain_id: ChainId,
906}
907
908/// Permissions for applications on a chain.
909#[derive(
910    Default,
911    Debug,
912    PartialEq,
913    Eq,
914    PartialOrd,
915    Ord,
916    Hash,
917    Clone,
918    Serialize,
919    Deserialize,
920    WitType,
921    WitLoad,
922    WitStore,
923    InputObject,
924)]
925pub struct ApplicationPermissions {
926    /// If this is `None`, all system operations and application operations are allowed.
927    /// If it is `Some`, only operations from the specified applications are allowed, and
928    /// no system operations.
929    #[debug(skip_if = Option::is_none)]
930    pub execute_operations: Option<Vec<ApplicationId>>,
931    /// At least one operation or incoming message from each of these applications must occur in
932    /// every block.
933    #[graphql(default)]
934    #[debug(skip_if = Vec::is_empty)]
935    pub mandatory_applications: Vec<ApplicationId>,
936    /// These applications are allowed to close the current chain using the system API.
937    #[graphql(default)]
938    #[debug(skip_if = Vec::is_empty)]
939    pub close_chain: Vec<ApplicationId>,
940    /// These applications are allowed to change the application permissions using the system API.
941    #[graphql(default)]
942    #[debug(skip_if = Vec::is_empty)]
943    pub change_application_permissions: Vec<ApplicationId>,
944    /// These applications are allowed to perform calls to services as oracles.
945    #[graphql(default)]
946    #[debug(skip_if = Option::is_none)]
947    pub call_service_as_oracle: Option<Vec<ApplicationId>>,
948    /// These applications are allowed to perform HTTP requests.
949    #[graphql(default)]
950    #[debug(skip_if = Option::is_none)]
951    pub make_http_requests: Option<Vec<ApplicationId>>,
952}
953
954impl ApplicationPermissions {
955    /// Creates new `ApplicationPermissions` where the given application is the only one
956    /// whose operations are allowed and mandatory, and it can also close the chain.
957    pub fn new_single(app_id: ApplicationId) -> Self {
958        Self {
959            execute_operations: Some(vec![app_id]),
960            mandatory_applications: vec![app_id],
961            close_chain: vec![app_id],
962            change_application_permissions: vec![app_id],
963            call_service_as_oracle: Some(vec![app_id]),
964            make_http_requests: Some(vec![app_id]),
965        }
966    }
967
968    /// Creates new `ApplicationPermissions` where the given applications are the only ones
969    /// whose operations are allowed and mandatory, and they can also close the chain.
970    pub fn new_multiple(app_ids: Vec<ApplicationId>) -> Self {
971        Self {
972            execute_operations: Some(app_ids.clone()),
973            mandatory_applications: app_ids.clone(),
974            close_chain: app_ids.clone(),
975            change_application_permissions: app_ids.clone(),
976            call_service_as_oracle: Some(app_ids.clone()),
977            make_http_requests: Some(app_ids),
978        }
979    }
980
981    /// Returns whether operations with the given application ID are allowed on this chain.
982    pub fn can_execute_operations(&self, app_id: &GenericApplicationId) -> bool {
983        match (app_id, &self.execute_operations) {
984            (_, None) => true,
985            (GenericApplicationId::System, Some(_)) => false,
986            (GenericApplicationId::User(app_id), Some(app_ids)) => app_ids.contains(app_id),
987        }
988    }
989
990    /// Returns whether the given application is allowed to close this chain.
991    pub fn can_close_chain(&self, app_id: &ApplicationId) -> bool {
992        self.close_chain.contains(app_id)
993    }
994
995    /// Returns whether the given application is allowed to change the application
996    /// permissions for this chain.
997    pub fn can_change_application_permissions(&self, app_id: &ApplicationId) -> bool {
998        self.change_application_permissions.contains(app_id)
999    }
1000
1001    /// Returns whether the given application can call services.
1002    pub fn can_call_services(&self, app_id: &ApplicationId) -> bool {
1003        self.call_service_as_oracle
1004            .as_ref()
1005            .map(|app_ids| app_ids.contains(app_id))
1006            .unwrap_or(true)
1007    }
1008
1009    /// Returns whether the given application can make HTTP requests.
1010    pub fn can_make_http_requests(&self, app_id: &ApplicationId) -> bool {
1011        self.make_http_requests
1012            .as_ref()
1013            .map(|app_ids| app_ids.contains(app_id))
1014            .unwrap_or(true)
1015    }
1016}
1017
1018/// A record of a single oracle response.
1019#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
1020pub enum OracleResponse {
1021    /// The response from a service query.
1022    Service(
1023        #[debug(with = "hex_debug")]
1024        #[serde(with = "serde_bytes")]
1025        Vec<u8>,
1026    ),
1027    /// The response from an HTTP request.
1028    Http(http::Response),
1029    /// A successful read or write of a blob.
1030    Blob(BlobId),
1031    /// An assertion oracle that passed.
1032    Assert,
1033    /// The block's validation round.
1034    Round(Option<u32>),
1035    /// An event was read.
1036    Event(EventId, Vec<u8>),
1037}
1038
1039impl BcsHashable<'_> for OracleResponse {}
1040
1041/// Description of a user application.
1042#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Hash, Serialize)]
1043pub struct ApplicationDescription {
1044    /// The unique ID of the bytecode to use for the application.
1045    pub module_id: ModuleId,
1046    /// The chain ID that created the application.
1047    pub creator_chain_id: ChainId,
1048    /// Height of the block that created this application.
1049    pub block_height: BlockHeight,
1050    /// The index of the application among those created in the same block.
1051    pub application_index: u32,
1052    /// The parameters of the application.
1053    #[serde(with = "serde_bytes")]
1054    #[debug(with = "hex_debug")]
1055    pub parameters: Vec<u8>,
1056    /// Required dependencies.
1057    pub required_application_ids: Vec<ApplicationId>,
1058}
1059
1060impl From<&ApplicationDescription> for ApplicationId {
1061    fn from(description: &ApplicationDescription) -> Self {
1062        let mut hash = CryptoHash::new(&BlobContent::new_application_description(description));
1063        if matches!(description.module_id.vm_runtime, VmRuntime::Evm) {
1064            hash.make_evm_compatible();
1065        }
1066        ApplicationId::new(hash)
1067    }
1068}
1069
1070impl BcsHashable<'_> for ApplicationDescription {}
1071
1072impl ApplicationDescription {
1073    /// Gets the serialized bytes for this `ApplicationDescription`.
1074    pub fn to_bytes(&self) -> Vec<u8> {
1075        bcs::to_bytes(self).expect("Serializing blob bytes should not fail!")
1076    }
1077
1078    /// Gets the `BlobId` of the contract
1079    pub fn contract_bytecode_blob_id(&self) -> BlobId {
1080        self.module_id.contract_bytecode_blob_id()
1081    }
1082
1083    /// Gets the `BlobId` of the service
1084    pub fn service_bytecode_blob_id(&self) -> BlobId {
1085        self.module_id.service_bytecode_blob_id()
1086    }
1087}
1088
1089/// A WebAssembly module's bytecode.
1090#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
1091pub struct Bytecode {
1092    /// Bytes of the bytecode.
1093    #[serde(with = "serde_bytes")]
1094    #[debug(with = "hex_debug")]
1095    pub bytes: Vec<u8>,
1096}
1097
1098impl Bytecode {
1099    /// Creates a new [`Bytecode`] instance using the provided `bytes`.
1100    pub fn new(bytes: Vec<u8>) -> Self {
1101        Bytecode { bytes }
1102    }
1103
1104    /// Load bytecode from a Wasm module file.
1105    pub async fn load_from_file(path: impl AsRef<std::path::Path>) -> std::io::Result<Self> {
1106        let bytes = fs::read(path)?;
1107        Ok(Bytecode { bytes })
1108    }
1109
1110    /// Compresses the [`Bytecode`] into a [`CompressedBytecode`].
1111    #[cfg(not(target_arch = "wasm32"))]
1112    pub fn compress(&self) -> CompressedBytecode {
1113        #[cfg(with_metrics)]
1114        let _compression_latency = metrics::BYTECODE_COMPRESSION_LATENCY.measure_latency();
1115        let compressed_bytes = zstd::stream::encode_all(&*self.bytes, 19)
1116            .expect("Compressing bytes in memory should not fail");
1117
1118        CompressedBytecode { compressed_bytes }
1119    }
1120}
1121
1122impl AsRef<[u8]> for Bytecode {
1123    fn as_ref(&self) -> &[u8] {
1124        self.bytes.as_ref()
1125    }
1126}
1127
1128/// A type for errors happening during decompression.
1129#[derive(Error, Debug)]
1130pub enum DecompressionError {
1131    /// Compressed bytecode is invalid, and could not be decompressed.
1132    #[error("Bytecode could not be decompressed: {0}")]
1133    InvalidCompressedBytecode(#[from] io::Error),
1134}
1135
1136/// A compressed WebAssembly module's bytecode.
1137#[derive(Clone, Debug, Deserialize, Hash, Serialize, WitType, WitStore)]
1138#[cfg_attr(with_testing, derive(Eq, PartialEq))]
1139pub struct CompressedBytecode {
1140    /// Compressed bytes of the bytecode.
1141    #[serde(with = "serde_bytes")]
1142    #[debug(with = "hex_debug")]
1143    pub compressed_bytes: Vec<u8>,
1144}
1145
1146#[cfg(not(target_arch = "wasm32"))]
1147impl CompressedBytecode {
1148    /// Returns `true` if the decompressed size does not exceed the limit.
1149    pub fn decompressed_size_at_most(
1150        compressed_bytes: &[u8],
1151        limit: u64,
1152    ) -> Result<bool, DecompressionError> {
1153        let mut decoder = zstd::stream::Decoder::new(compressed_bytes)?;
1154        let limit = usize::try_from(limit).unwrap_or(usize::MAX);
1155        let mut writer = LimitedWriter::new(io::sink(), limit);
1156        match io::copy(&mut decoder, &mut writer) {
1157            Ok(_) => Ok(true),
1158            Err(error) => {
1159                error.downcast::<LimitedWriterError>()?;
1160                Ok(false)
1161            }
1162        }
1163    }
1164
1165    /// Decompresses a [`CompressedBytecode`] into a [`Bytecode`].
1166    pub fn decompress(&self) -> Result<Bytecode, DecompressionError> {
1167        #[cfg(with_metrics)]
1168        let _decompression_latency = metrics::BYTECODE_DECOMPRESSION_LATENCY.measure_latency();
1169        let bytes = zstd::stream::decode_all(&*self.compressed_bytes)?;
1170
1171        Ok(Bytecode { bytes })
1172    }
1173}
1174
1175#[cfg(target_arch = "wasm32")]
1176impl CompressedBytecode {
1177    /// Returns `true` if the decompressed size does not exceed the limit.
1178    pub fn decompressed_size_at_most(
1179        compressed_bytes: &[u8],
1180        limit: u64,
1181    ) -> Result<bool, DecompressionError> {
1182        let limit = usize::try_from(limit).unwrap_or(usize::MAX);
1183        let mut writer = LimitedWriter::new(io::sink(), limit);
1184        let mut decoder = ruzstd::streaming_decoder::StreamingDecoder::new(compressed_bytes)
1185            .map_err(io::Error::other)?;
1186
1187        // TODO(#2710): Decode multiple frames, if present
1188        match io::copy(&mut decoder, &mut writer) {
1189            Ok(_) => Ok(true),
1190            Err(error) => {
1191                error.downcast::<LimitedWriterError>()?;
1192                Ok(false)
1193            }
1194        }
1195    }
1196
1197    /// Decompresses a [`CompressedBytecode`] into a [`Bytecode`].
1198    pub fn decompress(&self) -> Result<Bytecode, DecompressionError> {
1199        use ruzstd::{io::Read, streaming_decoder::StreamingDecoder};
1200
1201        #[cfg(with_metrics)]
1202        let _decompression_latency = BYTECODE_DECOMPRESSION_LATENCY.measure_latency();
1203
1204        let compressed_bytes = &*self.compressed_bytes;
1205        let mut bytes = Vec::new();
1206        let mut decoder = StreamingDecoder::new(compressed_bytes).map_err(io::Error::other)?;
1207
1208        // TODO(#2710): Decode multiple frames, if present
1209        while !decoder.get_ref().is_empty() {
1210            decoder
1211                .read_to_end(&mut bytes)
1212                .expect("Reading from a slice in memory should not result in I/O errors");
1213        }
1214
1215        Ok(Bytecode { bytes })
1216    }
1217}
1218
1219impl BcsHashable<'_> for BlobContent {}
1220
1221/// A blob of binary data.
1222#[derive(Hash, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
1223pub struct BlobContent {
1224    /// The type of data represented by the bytes.
1225    blob_type: BlobType,
1226    /// The binary data.
1227    #[serde(with = "serde_bytes")]
1228    #[debug(skip)]
1229    bytes: Box<[u8]>,
1230}
1231
1232impl BlobContent {
1233    /// Creates a new [`BlobContent`] from the provided bytes and [`BlobId`].
1234    pub fn new(blob_type: BlobType, bytes: impl Into<Box<[u8]>>) -> Self {
1235        let bytes = bytes.into();
1236        BlobContent { blob_type, bytes }
1237    }
1238
1239    /// Creates a new data [`BlobContent`] from the provided bytes.
1240    pub fn new_data(bytes: impl Into<Box<[u8]>>) -> Self {
1241        BlobContent::new(BlobType::Data, bytes)
1242    }
1243
1244    /// Creates a new contract bytecode [`BlobContent`] from the provided bytes.
1245    pub fn new_contract_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1246        BlobContent::new(
1247            BlobType::ContractBytecode,
1248            compressed_bytecode.compressed_bytes,
1249        )
1250    }
1251
1252    /// Creates a new contract bytecode [`BlobContent`] from the provided bytes.
1253    pub fn new_evm_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1254        BlobContent::new(BlobType::EvmBytecode, compressed_bytecode.compressed_bytes)
1255    }
1256
1257    /// Creates a new service bytecode [`BlobContent`] from the provided bytes.
1258    pub fn new_service_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1259        BlobContent::new(
1260            BlobType::ServiceBytecode,
1261            compressed_bytecode.compressed_bytes,
1262        )
1263    }
1264
1265    /// Creates a new application description [`BlobContent`] from a [`ApplicationDescription`].
1266    pub fn new_application_description(application_description: &ApplicationDescription) -> Self {
1267        let bytes = application_description.to_bytes();
1268        BlobContent::new(BlobType::ApplicationDescription, bytes)
1269    }
1270
1271    /// Creates a new committee [`BlobContent`] from the provided serialized committee.
1272    pub fn new_committee(committee: impl Into<Box<[u8]>>) -> Self {
1273        BlobContent::new(BlobType::Committee, committee)
1274    }
1275
1276    /// Creates a new chain description [`BlobContent`] from a [`ChainDescription`].
1277    pub fn new_chain_description(chain_description: &ChainDescription) -> Self {
1278        let bytes = bcs::to_bytes(&chain_description)
1279            .expect("Serializing a ChainDescription should not fail!");
1280        BlobContent::new(BlobType::ChainDescription, bytes)
1281    }
1282
1283    /// Gets a reference to the blob's bytes.
1284    pub fn bytes(&self) -> &[u8] {
1285        &self.bytes
1286    }
1287
1288    /// Gets the inner blob's bytes, consuming the blob.
1289    pub fn into_bytes(self) -> Box<[u8]> {
1290        self.bytes
1291    }
1292
1293    /// Returns the type of data represented by this blob's bytes.
1294    pub fn blob_type(&self) -> BlobType {
1295        self.blob_type
1296    }
1297}
1298
1299impl From<Blob> for BlobContent {
1300    fn from(blob: Blob) -> BlobContent {
1301        blob.content
1302    }
1303}
1304
1305/// A blob of binary data, with its hash.
1306#[derive(Debug, Hash, PartialEq, Eq, Clone)]
1307pub struct Blob {
1308    /// ID of the blob.
1309    hash: CryptoHash,
1310    /// A blob of binary data.
1311    content: BlobContent,
1312}
1313
1314impl Blob {
1315    /// Computes the hash and returns the hashed blob for the given content.
1316    pub fn new(content: BlobContent) -> Self {
1317        let mut hash = CryptoHash::new(&content);
1318        if matches!(content.blob_type, BlobType::ApplicationDescription) {
1319            let application_description = bcs::from_bytes::<ApplicationDescription>(&content.bytes)
1320                .expect("to obtain an application description");
1321            if matches!(application_description.module_id.vm_runtime, VmRuntime::Evm) {
1322                hash.make_evm_compatible();
1323            }
1324        }
1325        Blob { hash, content }
1326    }
1327
1328    /// Creates a blob without checking that the hash actually matches the content.
1329    pub fn new_with_id_unchecked(blob_id: BlobId, bytes: impl Into<Box<[u8]>>) -> Self {
1330        Blob {
1331            hash: blob_id.hash,
1332            content: BlobContent {
1333                blob_type: blob_id.blob_type,
1334                bytes: bytes.into(),
1335            },
1336        }
1337    }
1338
1339    /// Creates a new data [`Blob`] from the provided bytes.
1340    pub fn new_data(bytes: impl Into<Box<[u8]>>) -> Self {
1341        Blob::new(BlobContent::new_data(bytes))
1342    }
1343
1344    /// Creates a new contract bytecode [`Blob`] from the provided bytes.
1345    pub fn new_contract_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1346        Blob::new(BlobContent::new_contract_bytecode(compressed_bytecode))
1347    }
1348
1349    /// Creates a new contract bytecode [`BlobContent`] from the provided bytes.
1350    pub fn new_evm_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1351        Blob::new(BlobContent::new_evm_bytecode(compressed_bytecode))
1352    }
1353
1354    /// Creates a new service bytecode [`Blob`] from the provided bytes.
1355    pub fn new_service_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1356        Blob::new(BlobContent::new_service_bytecode(compressed_bytecode))
1357    }
1358
1359    /// Creates a new application description [`Blob`] from the provided description.
1360    pub fn new_application_description(application_description: &ApplicationDescription) -> Self {
1361        Blob::new(BlobContent::new_application_description(
1362            application_description,
1363        ))
1364    }
1365
1366    /// Creates a new committee [`Blob`] from the provided bytes.
1367    pub fn new_committee(committee: impl Into<Box<[u8]>>) -> Self {
1368        Blob::new(BlobContent::new_committee(committee))
1369    }
1370
1371    /// Creates a new chain description [`Blob`] from a [`ChainDescription`].
1372    pub fn new_chain_description(chain_description: &ChainDescription) -> Self {
1373        Blob::new(BlobContent::new_chain_description(chain_description))
1374    }
1375
1376    /// A content-addressed blob ID i.e. the hash of the `Blob`.
1377    pub fn id(&self) -> BlobId {
1378        BlobId {
1379            hash: self.hash,
1380            blob_type: self.content.blob_type,
1381        }
1382    }
1383
1384    /// Returns a reference to the inner `BlobContent`, without the hash.
1385    pub fn content(&self) -> &BlobContent {
1386        &self.content
1387    }
1388
1389    /// Moves ownership of the blob of binary data
1390    pub fn into_content(self) -> BlobContent {
1391        self.content
1392    }
1393
1394    /// Gets a reference to the inner blob's bytes.
1395    pub fn bytes(&self) -> &[u8] {
1396        self.content.bytes()
1397    }
1398
1399    /// Gets the inner blob's bytes.
1400    pub fn into_bytes(self) -> Box<[u8]> {
1401        self.content.into_bytes()
1402    }
1403
1404    /// Loads data blob from a file.
1405    pub async fn load_data_blob_from_file(path: impl AsRef<Path>) -> io::Result<Self> {
1406        Ok(Self::new_data(fs::read(path)?))
1407    }
1408
1409    /// Returns whether the blob is of [`BlobType::Committee`] variant.
1410    pub fn is_committee_blob(&self) -> bool {
1411        self.content().blob_type().is_committee_blob()
1412    }
1413}
1414
1415impl Serialize for Blob {
1416    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1417    where
1418        S: Serializer,
1419    {
1420        if serializer.is_human_readable() {
1421            let blob_bytes = bcs::to_bytes(&self.content).map_err(serde::ser::Error::custom)?;
1422            serializer.serialize_str(&hex::encode(blob_bytes))
1423        } else {
1424            BlobContent::serialize(self.content(), serializer)
1425        }
1426    }
1427}
1428
1429impl<'a> Deserialize<'a> for Blob {
1430    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1431    where
1432        D: Deserializer<'a>,
1433    {
1434        if deserializer.is_human_readable() {
1435            let s = String::deserialize(deserializer)?;
1436            let content_bytes = hex::decode(s).map_err(serde::de::Error::custom)?;
1437            let content: BlobContent =
1438                bcs::from_bytes(&content_bytes).map_err(serde::de::Error::custom)?;
1439
1440            Ok(Blob::new(content))
1441        } else {
1442            let content = BlobContent::deserialize(deserializer)?;
1443            Ok(Blob::new(content))
1444        }
1445    }
1446}
1447
1448impl BcsHashable<'_> for Blob {}
1449
1450/// An event recorded in a block.
1451#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, SimpleObject)]
1452pub struct Event {
1453    /// The ID of the stream this event belongs to.
1454    pub stream_id: StreamId,
1455    /// The event index, i.e. the number of events in the stream before this one.
1456    pub index: u32,
1457    /// The payload data.
1458    #[debug(with = "hex_debug")]
1459    #[serde(with = "serde_bytes")]
1460    pub value: Vec<u8>,
1461}
1462
1463impl Event {
1464    /// Returns the ID of this event record, given the publisher chain ID.
1465    pub fn id(&self, chain_id: ChainId) -> EventId {
1466        EventId {
1467            chain_id,
1468            stream_id: self.stream_id.clone(),
1469            index: self.index,
1470        }
1471    }
1472}
1473
1474/// An update for a stream with new events.
1475#[derive(Clone, Debug, Serialize, Deserialize, WitType, WitLoad, WitStore)]
1476pub struct StreamUpdate {
1477    /// The publishing chain.
1478    pub chain_id: ChainId,
1479    /// The stream ID.
1480    pub stream_id: StreamId,
1481    /// The lowest index of a new event. See [`StreamUpdate::new_indices`].
1482    pub previous_index: u32,
1483    /// The index of the next event, i.e. the lowest for which no event is known yet.
1484    pub next_index: u32,
1485}
1486
1487impl StreamUpdate {
1488    /// Returns the indices of all new events in the stream.
1489    pub fn new_indices(&self) -> impl Iterator<Item = u32> {
1490        self.previous_index..self.next_index
1491    }
1492}
1493
1494impl BcsHashable<'_> for Event {}
1495
1496doc_scalar!(Bytecode, "A WebAssembly module's bytecode");
1497doc_scalar!(Amount, "A non-negative amount of tokens.");
1498doc_scalar!(
1499    Epoch,
1500    "A number identifying the configuration of the chain (aka the committee)"
1501);
1502doc_scalar!(BlockHeight, "A block height to identify blocks in a chain");
1503doc_scalar!(
1504    Timestamp,
1505    "A timestamp, in microseconds since the Unix epoch"
1506);
1507doc_scalar!(TimeDelta, "A duration in microseconds");
1508doc_scalar!(
1509    Round,
1510    "A number to identify successive attempts to decide a value in a consensus protocol."
1511);
1512doc_scalar!(
1513    ChainDescription,
1514    "Initial chain configuration and chain origin."
1515);
1516doc_scalar!(OracleResponse, "A record of a single oracle response.");
1517doc_scalar!(BlobContent, "A blob of binary data.");
1518doc_scalar!(
1519    Blob,
1520    "A blob of binary data, with its content-addressed blob ID."
1521);
1522doc_scalar!(ApplicationDescription, "Description of a user application");
1523
1524#[cfg(with_metrics)]
1525mod metrics {
1526    use std::sync::LazyLock;
1527
1528    use prometheus::HistogramVec;
1529
1530    use crate::prometheus_util::{exponential_bucket_latencies, register_histogram_vec};
1531
1532    /// The time it takes to compress a bytecode.
1533    pub static BYTECODE_COMPRESSION_LATENCY: LazyLock<HistogramVec> = LazyLock::new(|| {
1534        register_histogram_vec(
1535            "bytecode_compression_latency",
1536            "Bytecode compression latency",
1537            &[],
1538            exponential_bucket_latencies(10.0),
1539        )
1540    });
1541
1542    /// The time it takes to decompress a bytecode.
1543    pub static BYTECODE_DECOMPRESSION_LATENCY: LazyLock<HistogramVec> = LazyLock::new(|| {
1544        register_histogram_vec(
1545            "bytecode_decompression_latency",
1546            "Bytecode decompression latency",
1547            &[],
1548            exponential_bucket_latencies(10.0),
1549        )
1550    });
1551}
1552
1553#[cfg(test)]
1554mod tests {
1555    use std::str::FromStr;
1556
1557    use super::Amount;
1558
1559    #[test]
1560    fn display_amount() {
1561        assert_eq!("1.", Amount::ONE.to_string());
1562        assert_eq!("1.", Amount::from_str("1.").unwrap().to_string());
1563        assert_eq!(
1564            Amount(10_000_000_000_000_000_000),
1565            Amount::from_str("10").unwrap()
1566        );
1567        assert_eq!("10.", Amount(10_000_000_000_000_000_000).to_string());
1568        assert_eq!(
1569            "1001.3",
1570            (Amount::from_str("1.1")
1571                .unwrap()
1572                .saturating_add(Amount::from_str("1_000.2").unwrap()))
1573            .to_string()
1574        );
1575        assert_eq!(
1576            "   1.00000000000000000000",
1577            format!("{:25.20}", Amount::ONE)
1578        );
1579        assert_eq!(
1580            "~+12.34~~",
1581            format!("{:~^+9.1}", Amount::from_str("12.34").unwrap())
1582        );
1583    }
1584}