linera_base/
data_types.rs

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