linera_base/
data_types.rs

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