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