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