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