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