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