diff --git a/Cargo.lock b/Cargo.lock index bb571a87d41..21c0eff2613 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4079,6 +4079,7 @@ dependencies = [ "async-trait", "bcs", "cfg_aliases", + "custom_debug_derive", "futures", "hex", "linera-base", @@ -4089,6 +4090,7 @@ dependencies = [ "rand_chacha", "rand_distr", "serde", + "serde_bytes", "thiserror", "tokio", "tracing", @@ -4169,6 +4171,7 @@ dependencies = [ "clap", "counter", "criterion", + "custom_debug_derive", "dashmap 5.5.3", "fungible", "futures", diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 42df494a619..14b1d2ddffe 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -3259,6 +3259,7 @@ dependencies = [ "async-graphql", "async-trait", "cfg_aliases", + "custom_debug_derive", "futures", "hex", "linera-base", @@ -3268,6 +3269,7 @@ dependencies = [ "rand_chacha", "rand_distr", "serde", + "serde_bytes", "thiserror", "tokio", "tracing", @@ -3283,6 +3285,7 @@ dependencies = [ "bcs", "cfg_aliases", "clap", + "custom_debug_derive", "dashmap 5.5.3", "futures", "linera-base", diff --git a/linera-base/src/data_types.rs b/linera-base/src/data_types.rs index 55256bac784..569492a0434 100644 --- a/linera-base/src/data_types.rs +++ b/linera-base/src/data_types.rs @@ -675,6 +675,11 @@ impl Amount { pub fn saturating_div(self, other: Amount) -> u128 { self.0.checked_div(other.0).unwrap_or(u128::MAX) } + + /// Returns whether this amount is 0. + pub fn is_zero(&self) -> bool { + *self == Amount::ZERO + } } /// Permissions for applications on a chain. @@ -696,13 +701,16 @@ pub struct ApplicationPermissions { /// If this is `None`, all system operations and application operations are allowed. /// If it is `Some`, only operations from the specified applications are allowed, and /// no system operations. + #[debug(skip_if = Option::is_none)] pub execute_operations: Option>, /// At least one operation or incoming message from each of these applications must occur in /// every block. #[graphql(default)] + #[debug(skip_if = Vec::is_empty)] pub mandatory_applications: Vec, /// These applications are allowed to close the current chain using the system API. #[graphql(default)] + #[debug(skip_if = Vec::is_empty)] pub close_chain: Vec, } @@ -736,9 +744,9 @@ impl ApplicationPermissions { #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)] pub enum OracleResponse { /// The response from a service query. - Service(Vec), + Service(#[debug(with = "hex_debug")] Vec), /// The response from an HTTP POST request. - Post(Vec), + Post(#[debug(with = "hex_debug")] Vec), /// A successful read or write of a blob. Blob(BlobId), /// An assertion oracle that passed. @@ -815,10 +823,11 @@ impl From<&UserApplicationDescription> for UserApplicationId { } /// A WebAssembly module's bytecode. -#[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct Bytecode { /// Bytes of the bytecode. #[serde(with = "serde_bytes")] + #[debug(with = "hex_debug")] pub bytes: Vec, } @@ -852,12 +861,6 @@ impl AsRef<[u8]> for Bytecode { } } -impl fmt::Debug for Bytecode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.debug_struct("Bytecode").finish_non_exhaustive() - } -} - /// A type for errors happening during decompression. #[derive(Error, Debug)] pub enum DecompressionError { @@ -867,11 +870,12 @@ pub enum DecompressionError { } /// A compressed WebAssembly module's bytecode. -#[derive(Clone, Deserialize, Hash, Serialize, WitType, WitStore)] +#[derive(Clone, Debug, Deserialize, Hash, Serialize, WitType, WitStore)] #[cfg_attr(with_testing, derive(Eq, PartialEq))] pub struct CompressedBytecode { /// Compressed bytes of the bytecode. #[serde(with = "serde_bytes")] + #[debug(with = "hex_debug")] pub compressed_bytes: Vec, } @@ -943,12 +947,6 @@ impl CompressedBytecode { } } -impl fmt::Debug for CompressedBytecode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CompressedBytecode").finish_non_exhaustive() - } -} - /// Internal bytes of a blob. #[derive(Clone, Serialize, Deserialize, WitType, WitStore)] #[cfg_attr(with_testing, derive(Eq, PartialEq))] @@ -964,25 +962,19 @@ impl Hash for BlobBytes { } /// A blob of binary data. -#[derive(Hash, Clone, Serialize, Deserialize, WitType, WitStore)] +#[derive(Hash, Clone, Debug, Serialize, Deserialize, WitType, WitStore)] #[cfg_attr(with_testing, derive(Eq, PartialEq))] pub enum BlobContent { /// A generic data blob. - Data(#[serde(with = "serde_bytes")] Vec), + Data( + #[serde(with = "serde_bytes")] + #[debug(skip)] + Vec, + ), /// A blob containing contract bytecode. - ContractBytecode(CompressedBytecode), + ContractBytecode(#[debug(skip)] CompressedBytecode), /// A blob containing service bytecode. - ServiceBytecode(CompressedBytecode), -} - -impl fmt::Debug for BlobContent { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - BlobContent::Data(_) => write!(f, "BlobContent::Data"), - BlobContent::ContractBytecode(_) => write!(f, "BlobContent::ContractBytecode"), - BlobContent::ServiceBytecode(_) => write!(f, "BlobContent::ServiceBytecode"), - } - } + ServiceBytecode(#[debug(skip)] CompressedBytecode), } impl BlobContent { diff --git a/linera-base/src/identifiers.rs b/linera-base/src/identifiers.rs index d599518f47d..e2a83d056d6 100644 --- a/linera-base/src/identifiers.rs +++ b/linera-base/src/identifiers.rs @@ -4,7 +4,7 @@ //! Core identifiers used by the Linera protocol. use std::{ - fmt::{self, Debug, Display, Formatter}, + fmt::{self, Display, Formatter}, hash::{Hash, Hasher}, marker::PhantomData, str::FromStr, @@ -12,6 +12,7 @@ use std::{ use anyhow::{anyhow, Context}; use async_graphql::SimpleObject; +use custom_debug_derive::Debug; use linera_witty::{WitLoad, WitStore, WitType}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -19,7 +20,7 @@ use crate::{ bcs_scalar, crypto::{BcsHashable, CryptoError, CryptoHash, PublicKey}, data_types::{BlobContent, BlockHeight}, - doc_scalar, + doc_scalar, hex_debug, }; /// The owner of a chain. This is currently the hash of the owner's public key used to @@ -45,6 +46,7 @@ pub struct Account { /// The chain of the account. pub chain_id: ChainId, /// The owner of the account, or `None` for the chain balance. + #[debug(skip_if = Option::is_none)] pub owner: Option, } @@ -301,7 +303,7 @@ pub struct MessageId { } /// A unique identifier for a user application. -#[derive(WitLoad, WitStore, WitType)] +#[derive(Debug, WitLoad, WitStore, WitType)] #[cfg_attr(with_testing, derive(Default))] pub struct ApplicationId { /// The bytecode to use for the application. @@ -355,7 +357,7 @@ impl From for GenericApplicationId { } /// A unique identifier for an application bytecode. -#[derive(WitLoad, WitStore, WitType)] +#[derive(Debug, WitLoad, WitStore, WitType)] #[cfg_attr(with_testing, derive(Default))] pub struct BytecodeId { /// The hash of the blob containing the contract bytecode. @@ -363,6 +365,7 @@ pub struct BytecodeId { /// The hash of the blob containing the service bytecode. pub service_blob_hash: CryptoHash, #[witty(skip)] + #[debug(skip)] _phantom: PhantomData<(Abi, Parameters, InstantiationArgument)>, } @@ -381,7 +384,11 @@ pub struct BytecodeId { WitStore, WitType, )] -pub struct ChannelName(#[serde(with = "serde_bytes")] Vec); +pub struct ChannelName( + #[serde(with = "serde_bytes")] + #[debug(with = "hex_debug")] + Vec, +); /// The name of an event stream. #[derive( @@ -398,7 +405,11 @@ pub struct ChannelName(#[serde(with = "serde_bytes")] Vec); WitStore, WitType, )] -pub struct StreamName(#[serde(with = "serde_bytes")] pub Vec); +pub struct StreamName( + #[serde(with = "serde_bytes")] + #[debug(with = "hex_debug")] + pub Vec, +); /// An event stream ID. #[derive( @@ -559,22 +570,6 @@ impl Hash } } -impl Debug - for BytecodeId -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let BytecodeId { - contract_blob_hash: contract_blob_id, - service_blob_hash: service_blob_id, - _phantom, - } = self; - f.debug_struct("BytecodeId") - .field("contract_blob_id", contract_blob_id) - .field("service_blob_id", service_blob_id) - .finish_non_exhaustive() - } -} - #[derive(Serialize, Deserialize)] #[serde(rename = "BytecodeId")] struct SerializableBytecodeId { @@ -731,19 +726,6 @@ impl Hash for ApplicationId { } } -impl Debug for ApplicationId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let ApplicationId { - bytecode_id, - creation, - } = self; - f.debug_struct("ApplicationId") - .field("bytecode_id", bytecode_id) - .field("creation", creation) - .finish() - } -} - #[derive(Serialize, Deserialize)] #[serde(rename = "ApplicationId")] struct SerializableApplicationId { diff --git a/linera-base/src/lib.rs b/linera-base/src/lib.rs index b220bcdbda0..2473212b503 100644 --- a/linera-base/src/lib.rs +++ b/linera-base/src/lib.rs @@ -8,6 +8,8 @@ #![deny(missing_docs)] #![deny(clippy::large_futures)] +use std::fmt; + #[doc(hidden)] pub use async_trait::async_trait; @@ -93,7 +95,7 @@ macro_rules! ensure { /// "Message { bytes: 20202020202020203130202020202020..20202020343020202020202020203530 }" /// ); /// ``` -pub fn hex_debug>(bytes: &T, f: &mut std::fmt::Formatter) -> std::fmt::Result { +pub fn hex_debug>(bytes: &T, f: &mut fmt::Formatter) -> fmt::Result { const ELIDE_AFTER: usize = 16; let bytes = bytes.as_ref(); if bytes.len() <= 2 * ELIDE_AFTER { @@ -108,3 +110,38 @@ pub fn hex_debug>(bytes: &T, f: &mut std::fmt::Formatter) -> std: } Ok(()) } + +/// Applies `hex_debug` to a slice of byte vectors. +/// +/// # Examples +/// +/// ``` +/// # use linera_base::hex_vec_debug; +/// use custom_debug_derive::Debug; +/// +/// #[derive(Debug)] +/// struct Messages { +/// #[debug(with = "hex_vec_debug")] +/// byte_vecs: Vec>, +/// } +/// +/// let msgs = Messages { +/// byte_vecs: vec![vec![0x12, 0x34, 0x56, 0x78], vec![0x9A]], +/// }; +/// +/// assert_eq!( +/// format!("{:?}", msgs), +/// "Messages { byte_vecs: [12345678, 9a] }" +/// ); +/// ``` +#[allow(clippy::ptr_arg)] // This only works with custom_debug_derive if it's &Vec. +pub fn hex_vec_debug(list: &Vec>, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[")?; + for (i, bytes) in list.iter().enumerate() { + if i != 0 { + write!(f, ", ")?; + } + hex_debug(bytes, f)?; + } + write!(f, "]") +} diff --git a/linera-base/src/ownership.rs b/linera-base/src/ownership.rs index 69a899afbe6..dfe3780188d 100644 --- a/linera-base/src/ownership.rs +++ b/linera-base/src/ownership.rs @@ -6,6 +6,7 @@ use std::{collections::BTreeMap, iter}; +use custom_debug_derive::Debug; use linera_witty::{WitLoad, WitStore, WitType}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -21,6 +22,7 @@ use crate::{ #[derive(PartialEq, Eq, Clone, Hash, Debug, Serialize, Deserialize, WitLoad, WitStore, WitType)] pub struct TimeoutConfig { /// The duration of the fast round. + #[debug(skip_if = Option::is_none)] pub fast_round_duration: Option, /// The duration of the first single-leader and all multi-leader rounds. pub base_timeout: TimeDelta, @@ -48,8 +50,10 @@ impl Default for TimeoutConfig { )] pub struct ChainOwnership { /// Super owners can propose fast blocks in the first round, and regular blocks in any round. + #[debug(skip_if = BTreeMap::is_empty)] pub super_owners: BTreeMap, /// The regular owners, with their weights that determine how often they are round leader. + #[debug(skip_if = BTreeMap::is_empty)] pub owners: BTreeMap, /// The number of initial rounds after 0 in which all owners are allowed to propose blocks. pub multi_leader_rounds: u32, diff --git a/linera-chain/Cargo.toml b/linera-chain/Cargo.toml index 6de7f737063..ff7dce24ae3 100644 --- a/linera-chain/Cargo.toml +++ b/linera-chain/Cargo.toml @@ -20,6 +20,7 @@ benchmark = ["linera-base/test"] [dependencies] async-graphql.workspace = true async-trait.workspace = true +custom_debug_derive.workspace = true futures.workspace = true hex.workspace = true linera-base.workspace = true @@ -29,6 +30,7 @@ prometheus = { workspace = true, optional = true } rand_chacha.workspace = true rand_distr = { workspace = true, features = ["alloc", "serde1"] } serde.workspace = true +serde_bytes.workspace = true thiserror.workspace = true tokio.workspace = true tracing.workspace = true @@ -42,4 +44,4 @@ linera-chain = { path = ".", default-features = false, features = ["test"] } cfg_aliases.workspace = true [package.metadata.cargo-machete] -ignored = ["async-trait"] +ignored = ["async-trait", "serde_bytes"] diff --git a/linera-chain/src/certificate/generic.rs b/linera-chain/src/certificate/generic.rs index 11cd01e4be2..7d5257d9200 100644 --- a/linera-chain/src/certificate/generic.rs +++ b/linera-chain/src/certificate/generic.rs @@ -2,8 +2,7 @@ // Copyright (c) Zefchain Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use std::fmt::{Debug, Formatter}; - +use custom_debug_derive::Debug; use linera_base::{ crypto::{CryptoHash, Signature}, data_types::Round, @@ -14,6 +13,7 @@ use super::hashed::Hashed; use crate::ChainError; /// Generic type representing a certificate for `value` of type `T`. +#[derive(Debug)] pub struct GenericCertificate { value: Hashed, pub round: Round, @@ -105,16 +105,6 @@ impl Clone for GenericCertificate { } } -impl Debug for GenericCertificate { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("CertificateT") - .field("value", &self.value) - .field("round", &self.round) - .field("signatures", &self.signatures) - .finish() - } -} - #[cfg(with_testing)] impl Eq for GenericCertificate {} #[cfg(with_testing)] diff --git a/linera-chain/src/certificate/hashed.rs b/linera-chain/src/certificate/hashed.rs index 73b8c4ed871..626498bdbd2 100644 --- a/linera-chain/src/certificate/hashed.rs +++ b/linera-chain/src/certificate/hashed.rs @@ -2,11 +2,11 @@ // Copyright (c) Zefchain Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use std::fmt::{Debug, Formatter}; - +use custom_debug_derive::Debug; use linera_base::crypto::{BcsHashable, CryptoHash}; /// Wrapper type around hashed instance of `T` type. +#[derive(Debug)] pub struct Hashed { value: T, /// Hash of the value (used as key for storage). @@ -48,15 +48,6 @@ impl Hashed { } } -impl Debug for Hashed { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("HashedT") - .field("value", &self.value) - .field("hash", &self.hash()) - .finish() - } -} - impl Clone for Hashed { fn clone(&self) -> Self { Self { diff --git a/linera-chain/src/data_types.rs b/linera-chain/src/data_types.rs index dd28ef97248..b8b1a6a2b8c 100644 --- a/linera-chain/src/data_types.rs +++ b/linera-chain/src/data_types.rs @@ -5,10 +5,11 @@ use std::{collections::HashSet, fmt}; use async_graphql::SimpleObject; +use custom_debug_derive::Debug; use linera_base::{ crypto::{BcsHashable, BcsSignable, CryptoError, CryptoHash, KeyPair, PublicKey, Signature}, data_types::{Amount, Blob, BlockHeight, OracleResponse, Round, Timestamp}, - doc_scalar, ensure, + doc_scalar, ensure, hex_debug, identifiers::{ Account, BlobId, BlobType, ChainId, ChannelName, Destination, GenericApplicationId, MessageId, Owner, StreamId, @@ -48,8 +49,10 @@ pub struct Block { pub epoch: Epoch, /// A selection of incoming messages to be executed first. Successive messages of same /// sender and height are grouped together for conciseness. + #[debug(skip_if = Vec::is_empty)] pub incoming_bundles: Vec, /// The operations to execute. + #[debug(skip_if = Vec::is_empty)] pub operations: Vec, /// The block height. pub height: BlockHeight, @@ -60,6 +63,7 @@ pub struct Block { /// fees. If set, this must be the `owner` in the block proposal. `None` means that /// the default account of the chain is used. This value is also used as recipient of /// potential refunds for the message grants created by the operations. + #[debug(skip_if = Option::is_none)] pub authenticated_signer: Option, /// Certified hash (see `Certificate` below) of the previous block in the /// chain, if any. @@ -286,7 +290,9 @@ pub struct BlockProposal { pub content: ProposalContent, pub owner: Owner, pub signature: Signature, + #[debug(skip_if = Vec::is_empty)] pub blobs: Vec, + #[debug(skip_if = Option::is_none)] pub validated_block_certificate: Option>, } @@ -296,10 +302,13 @@ pub struct OutgoingMessage { /// The destination of the message. pub destination: Destination, /// The user authentication carried by the message, if any. + #[debug(skip_if = Option::is_none)] pub authenticated_signer: Option, /// A grant to pay for the message execution. + #[debug(skip_if = Amount::is_zero)] pub grant: Amount, /// Where to send a refund for the unused part of the grant after execution, if any. + #[debug(skip_if = Option::is_none)] pub refund_grant_to: Option, /// The kind of message being sent. pub kind: MessageKind, @@ -311,10 +320,13 @@ pub struct OutgoingMessage { #[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, SimpleObject)] pub struct PostedMessage { /// The user authentication carried by the message, if any. + #[debug(skip_if = Option::is_none)] pub authenticated_signer: Option, /// A grant to pay for the message execution. + #[debug(skip_if = Amount::is_zero)] pub grant: Amount, /// Where to send a refund for the unused part of the grant after execution, if any. + #[debug(skip_if = Option::is_none)] pub refund_grant_to: Option, /// The kind of message being sent. pub kind: MessageKind, @@ -391,8 +403,10 @@ pub struct EventRecord { /// The ID of the stream this event belongs to. pub stream_id: StreamId, /// The event key. + #[debug(with = "hex_debug")] pub key: Vec, /// The payload data. + #[debug(with = "hex_debug")] pub value: Vec, } @@ -699,6 +713,7 @@ pub struct ProposalContent { pub round: Round, /// If this is a retry from an earlier round, the oracle responses from when the block was /// first validated. These are reused so the execution outcome remains the same. + #[debug(skip_if = Option::is_none)] pub forced_oracle_responses: Option>>, } diff --git a/linera-chain/src/manager.rs b/linera-chain/src/manager.rs index 5787cd380f9..3a9ef40fece 100644 --- a/linera-chain/src/manager.rs +++ b/linera-chain/src/manager.rs @@ -70,6 +70,7 @@ use std::collections::BTreeMap; +use custom_debug_derive::Debug; use linera_base::{ crypto::{KeyPair, PublicKey}, data_types::{ArithmeticError, Blob, BlockHeight, Round, Timestamp}, @@ -106,24 +107,33 @@ pub struct ChainManager { /// The seed for the pseudo-random number generator that determines the round leaders. pub seed: u64, /// The probability distribution for choosing a round leader. + #[debug(skip_if = Option::is_none)] pub distribution: Option>, /// The probability distribution for choosing a fallback round leader. + #[debug(skip_if = Option::is_none)] pub fallback_distribution: Option>, /// Highest-round authenticated block that we have received and checked. If there are multiple /// proposals in the same round, this contains only the first one. + #[debug(skip_if = Option::is_none)] pub proposed: Option, /// Latest validated proposal that we have voted to confirm (or would have, if we are not a /// validator). + #[debug(skip_if = Option::is_none)] pub locked: Option, /// Latest leader timeout certificate we have received. + #[debug(skip_if = Option::is_none)] pub timeout: Option, /// Latest vote we have cast, to validate or confirm. + #[debug(skip_if = Option::is_none)] pub pending: Option, /// Latest timeout vote we cast. + #[debug(skip_if = Option::is_none)] pub timeout_vote: Option, /// Fallback vote we cast. + #[debug(skip_if = Option::is_none)] pub fallback_vote: Option, /// The time after which we are ready to sign a timeout certificate for the current round. + #[debug(skip_if = Option::is_none)] pub round_timeout: Option, /// The lowest round where we can still vote to validate or confirm a block. This is /// the round to which the timeout applies. @@ -133,8 +143,10 @@ pub struct ChainManager { /// round to become current, unless a higher one already is. pub current_round: Round, /// The owners that take over in fallback mode. + #[debug(skip_if = BTreeMap::is_empty)] pub fallback_owners: BTreeMap, /// These are blobs belonging to proposed or validated blocks that have not been confirmed yet. + #[debug(skip_if = BTreeMap::is_empty)] pub pending_blobs: BTreeMap, } @@ -558,28 +570,38 @@ pub struct ChainManagerInfo { /// The configuration of the chain's owners. pub ownership: ChainOwnership, /// Latest authenticated block that we have received, if requested. + #[debug(skip_if = Option::is_none)] pub requested_proposed: Option>, /// Latest validated proposal that we have voted to confirm (or would have, if we are not a /// validator). + #[debug(skip_if = Option::is_none)] pub requested_locked: Option>, /// Latest timeout certificate we have seen. + #[debug(skip_if = Option::is_none)] pub timeout: Option>, /// Latest vote we cast (either to validate or to confirm a block). + #[debug(skip_if = Option::is_none)] pub pending: Option, /// Latest timeout vote we cast. + #[debug(skip_if = Option::is_none)] pub timeout_vote: Option, /// Fallback vote we cast. + #[debug(skip_if = Option::is_none)] pub fallback_vote: Option, /// The value we voted for, if requested. + #[debug(skip_if = Option::is_none)] pub requested_pending_value: Option>, /// The current round, i.e. the lowest round where we can still vote to validate a block. pub current_round: Round, /// The current leader, who is allowed to propose the next block. /// `None` if everyone is allowed to propose. + #[debug(skip_if = Option::is_none)] pub leader: Option, /// The timestamp when the current round times out. + #[debug(skip_if = Option::is_none)] pub round_timeout: Option, /// These are blobs belonging to proposed or validated blocks that have not been confirmed yet. + #[debug(skip_if = BTreeMap::is_empty)] pub pending_blobs: BTreeMap, } diff --git a/linera-core/Cargo.toml b/linera-core/Cargo.toml index 23cc20dc273..ca305ab232f 100644 --- a/linera-core/Cargo.toml +++ b/linera-core/Cargo.toml @@ -55,6 +55,7 @@ async-graphql.workspace = true async-trait.workspace = true bcs.workspace = true clap.workspace = true +custom_debug_derive.workspace = true dashmap.workspace = true futures.workspace = true linera-base.workspace = true diff --git a/linera-core/src/chain_worker/actor.rs b/linera-core/src/chain_worker/actor.rs index e84874b54d7..56bcb9316c7 100644 --- a/linera-core/src/chain_worker/actor.rs +++ b/linera-core/src/chain_worker/actor.rs @@ -5,10 +5,11 @@ use std::{ collections::HashSet, - fmt::{self, Debug, Formatter}, + fmt, sync::{Arc, RwLock}, }; +use custom_debug_derive::Debug; use linera_base::{ crypto::CryptoHash, data_types::{Blob, BlockHeight, Timestamp, UserApplicationDescription}, @@ -37,6 +38,7 @@ use crate::{ }; /// A request for the [`ChainWorkerActor`]. +#[derive(Debug)] pub enum ChainWorkerRequest where Context: linera_views::context::Context + Clone + Send + Sync + 'static, @@ -45,6 +47,7 @@ where #[cfg(with_testing)] ReadCertificate { height: BlockHeight, + #[debug(skip)] callback: oneshot::Sender, WorkerError>>, }, @@ -55,11 +58,13 @@ where certificate_hash: CryptoHash, height: BlockHeight, index: u32, + #[debug(skip)] callback: oneshot::Sender, WorkerError>>, }, /// Request a read-only view of the [`ChainStateView`]. GetChainStateView { + #[debug(skip)] callback: oneshot::Sender>, WorkerError>>, }, @@ -67,30 +72,35 @@ where /// Query an application's state. QueryApplication { query: Query, + #[debug(skip)] callback: oneshot::Sender>, }, /// Describe an application. DescribeApplication { application_id: UserApplicationId, + #[debug(skip)] callback: oneshot::Sender>, }, /// Execute a block but discard any changes to the chain state. StageBlockExecution { block: Block, + #[debug(skip)] callback: oneshot::Sender>, }, /// Process a leader timeout issued for this multi-owner chain. ProcessTimeout { certificate: TimeoutCertificate, + #[debug(skip)] callback: oneshot::Sender>, }, /// Handle a proposal for the next block on this chain. HandleBlockProposal { proposal: BlockProposal, + #[debug(skip)] callback: oneshot::Sender>, }, @@ -98,6 +108,7 @@ where ProcessValidatedBlock { certificate: ValidatedBlockCertificate, blobs: Vec, + #[debug(skip)] callback: oneshot::Sender>, }, @@ -105,7 +116,9 @@ where ProcessConfirmedBlock { certificate: ConfirmedBlockCertificate, blobs: Vec, + #[debug(with = "elide_option")] notify_when_messages_are_delivered: Option>, + #[debug(skip)] callback: oneshot::Sender>, }, @@ -113,18 +126,21 @@ where ProcessCrossChainUpdate { origin: Origin, bundles: Vec<(Epoch, MessageBundle)>, + #[debug(skip)] callback: oneshot::Sender, WorkerError>>, }, /// Handle cross-chain request to confirm that the recipient was updated. ConfirmUpdatedRecipient { latest_heights: Vec<(Target, BlockHeight)>, + #[debug(skip)] callback: oneshot::Sender>, }, /// Handle a [`ChainInfoQuery`]. HandleChainInfoQuery { query: ChainInfoQuery, + #[debug(skip)] callback: oneshot::Sender>, }, } @@ -332,120 +348,10 @@ where } } -impl Debug for ChainWorkerRequest -where - Context: linera_views::context::Context + Clone + Send + Sync + 'static, -{ - fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { - match self { - #[cfg(with_testing)] - ChainWorkerRequest::ReadCertificate { - height, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::ReadCertificate") - .field("height", &height) - .finish_non_exhaustive(), - #[cfg(with_testing)] - ChainWorkerRequest::FindBundleInInbox { - inbox_id, - certificate_hash, - height, - index, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::FindBundleInInbox") - .field("inbox_id", &inbox_id) - .field("certificate_hash", &certificate_hash) - .field("height", &height) - .field("index", &index) - .finish_non_exhaustive(), - ChainWorkerRequest::GetChainStateView { - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::GetChainStateView") - .finish_non_exhaustive(), - ChainWorkerRequest::QueryApplication { - query, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::QueryApplication") - .field("query", &query) - .finish_non_exhaustive(), - ChainWorkerRequest::DescribeApplication { - application_id, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::DescribeApplication") - .field("application_id", &application_id) - .finish_non_exhaustive(), - ChainWorkerRequest::StageBlockExecution { - block, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::StageBlockExecution") - .field("block", &block) - .finish_non_exhaustive(), - ChainWorkerRequest::ProcessTimeout { - certificate, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::ProcessTimeout") - .field("certificate", &certificate) - .finish_non_exhaustive(), - ChainWorkerRequest::HandleBlockProposal { - proposal, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::HandleBlockProposal") - .field("proposal", &proposal) - .finish_non_exhaustive(), - ChainWorkerRequest::ProcessValidatedBlock { - certificate, - blobs, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::ProcessValidatedBlock") - .field("certificate", &certificate) - .field("blobs", &blobs) - .finish_non_exhaustive(), - ChainWorkerRequest::ProcessConfirmedBlock { - certificate, - blobs, - notify_when_messages_are_delivered, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::ProcessConfirmedBlock") - .field("certificate", &certificate) - .field("blobs", &blobs) - .field( - "notify_when_messages_are_delivered", - ¬ify_when_messages_are_delivered.as_ref().map(|_| "..."), - ) - .finish_non_exhaustive(), - ChainWorkerRequest::ProcessCrossChainUpdate { - origin, - bundles, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::ProcessCrossChainUpdate") - .field("origin", &origin) - .field("bundles", &bundles) - .finish_non_exhaustive(), - ChainWorkerRequest::ConfirmUpdatedRecipient { - latest_heights, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::ConfirmUpdatedRecipient") - .field("latest_heights", &latest_heights) - .finish_non_exhaustive(), - ChainWorkerRequest::HandleChainInfoQuery { - query, - callback: _callback, - } => formatter - .debug_struct("ChainWorkerRequest::HandleChainInfoQuery") - .field("query", &query) - .finish_non_exhaustive(), - } +/// Writes an option as `Some(..)` or `None`. +fn elide_option(option: &Option, f: &mut fmt::Formatter) -> fmt::Result { + match option { + Some(_) => write!(f, "Some(..)"), + None => write!(f, "None"), } } diff --git a/linera-core/src/client/mod.rs b/linera-core/src/client/mod.rs index fdd377964c9..4ffaf7ace5e 100644 --- a/linera-core/src/client/mod.rs +++ b/linera-core/src/client/mod.rs @@ -12,6 +12,7 @@ use std::{ }; use chain_client_state::ChainClientState; +use custom_debug_derive::Debug; use dashmap::{ mapref::one::{MappedRef as DashMapMappedRef, Ref as DashMapRef, RefMut as DashMapRefMut}, DashMap, @@ -493,17 +494,21 @@ pub struct ChainClientOptions { /// * The chain being operated is called the "local chain" or just the "chain". /// * As a rule, operations are considered successful (and communication may stop) when /// they succeeded in gathering a quorum of responses. +#[derive(Debug)] pub struct ChainClient where Storage: linera_storage::Storage, { /// The Linera [`Client`] that manages operations for this chain client. + #[debug(skip)] client: Arc>, /// The off-chain chain ID. chain_id: ChainId, /// The ID of the admin chain. + #[debug(skip)] admin_id: ChainId, /// The client options. + #[debug(skip)] options: ChainClientOptions, } @@ -521,18 +526,6 @@ where } } -impl std::fmt::Debug for ChainClient -where - S: linera_storage::Storage, -{ - fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter - .debug_struct("ChainClient") - .field("chain_id", &format!("{:.8}", self.chain_id)) - .finish_non_exhaustive() - } -} - /// Error type for [`ChainClient`]. #[derive(Debug, Error)] pub enum ChainClientError { diff --git a/linera-core/src/data_types.rs b/linera-core/src/data_types.rs index 228d7d1b8bd..8fc7b6ca767 100644 --- a/linera-core/src/data_types.rs +++ b/linera-core/src/data_types.rs @@ -2,8 +2,9 @@ // Copyright (c) Zefchain Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use std::collections::BTreeMap; +use std::{collections::BTreeMap, ops::Not}; +use custom_debug_derive::Debug; use linera_base::{ crypto::{BcsSignable, CryptoError, CryptoHash, KeyPair, Signature}, data_types::{Amount, BlockHeight, Round, Timestamp}, @@ -31,6 +32,7 @@ pub struct BlockHeightRange { /// Starting point pub start: BlockHeight, /// Optional limit on the number of elements. + #[debug(skip_if = Option::is_none)] pub limit: Option, } @@ -63,22 +65,31 @@ pub struct ChainInfoQuery { /// The chain ID. pub chain_id: ChainId, /// Optionally test that the block height is the one expected. + #[debug(skip_if = Option::is_none)] pub test_next_block_height: Option, /// Request the balance of a given `Owner`. + #[debug(skip_if = Option::is_none)] pub request_owner_balance: Option, /// Query the current committees. + #[debug(skip_if = Not::not)] pub request_committees: bool, /// Query the received messages that are waiting be picked in the next block. + #[debug(skip_if = Not::not)] pub request_pending_message_bundles: bool, /// Query a range of certificate hashes sent from the chain. + #[debug(skip_if = Option::is_none)] pub request_sent_certificate_hashes_in_range: Option, /// Query new certificate sender chain IDs and block heights received from the chain. + #[debug(skip_if = Option::is_none)] pub request_received_log_excluding_first_n: Option, /// Query values from the chain manager, not just votes. + #[debug(skip_if = Not::not)] pub request_manager_values: bool, /// Include a timeout vote for the current round, if appropriate. + #[debug(skip_if = Not::not)] pub request_leader_timeout: bool, /// Include a vote to switch to fallback mode, if appropriate. + #[debug(skip_if = Not::not)] pub request_fallback: bool, } @@ -150,32 +161,41 @@ pub struct ChainInfo { /// The chain ID. pub chain_id: ChainId, /// The number identifying the current configuration. + #[debug(skip_if = Option::is_none)] pub epoch: Option, /// The chain description. + #[debug(skip_if = Option::is_none)] pub description: Option, /// The state of the chain authentication. pub manager: Box, /// The current balance. pub chain_balance: Amount, /// The last block hash, if any. + #[debug(skip_if = Option::is_none)] pub block_hash: Option, /// The earliest possible timestamp for the next block. pub timestamp: Timestamp, /// The height after the latest block in the chain. pub next_block_height: BlockHeight, /// The hash of the current execution state. + #[debug(skip_if = Option::is_none)] pub state_hash: Option, /// The requested owner balance, if any. + #[debug(skip_if = Option::is_none)] pub requested_owner_balance: Option, /// The current committees. + #[debug(skip_if = Option::is_none)] pub requested_committees: Option>, /// The received messages that are waiting be picked in the next block (if requested). + #[debug(skip_if = Vec::is_empty)] pub requested_pending_message_bundles: Vec, /// The response to `request_sent_certificate_hashes_in_range` + #[debug(skip_if = Vec::is_empty)] pub requested_sent_certificate_hashes: Vec, /// The current number of received certificates (useful for `request_received_log_excluding_first_n`) pub count_received_log: usize, /// The response to `request_received_certificates_excluding_first_n` + #[debug(skip_if = Vec::is_empty)] pub requested_received_log: Vec, } diff --git a/linera-core/src/remote_node.rs b/linera-core/src/remote_node.rs index 699f2a81451..ac778e85040 100644 --- a/linera-core/src/remote_node.rs +++ b/linera-core/src/remote_node.rs @@ -1,8 +1,9 @@ // Copyright (c) Zefchain Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use std::{collections::HashMap, fmt}; +use std::collections::HashMap; +use custom_debug_derive::Debug; use futures::{stream::FuturesUnordered, StreamExt}; use linera_base::{ crypto::CryptoHash, @@ -24,20 +25,13 @@ use crate::{ }; /// A validator node together with the validator's name. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct RemoteNode { pub name: ValidatorName, + #[debug(skip)] pub node: N, } -impl fmt::Debug for RemoteNode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("RemoteNode") - .field("name", &self.name) - .finish_non_exhaustive() - } -} - #[allow(clippy::result_large_err)] impl RemoteNode { pub(crate) async fn handle_chain_info_query( diff --git a/linera-execution/src/execution_state_actor.rs b/linera-execution/src/execution_state_actor.rs index 19244f34c32..c22653159fe 100644 --- a/linera-execution/src/execution_state_actor.rs +++ b/linera-execution/src/execution_state_actor.rs @@ -3,15 +3,16 @@ //! Handle requests from the synchronous execution thread of user applications. -use std::fmt::{self, Debug, Formatter}; #[cfg(with_metrics)] use std::sync::LazyLock; +use custom_debug_derive::Debug; use futures::channel::mpsc; #[cfg(with_metrics)] use linera_base::prometheus_util::{self, MeasureLatency as _}; use linera_base::{ data_types::{Amount, ApplicationPermissions, BlobContent, Timestamp}, + hex_debug, hex_vec_debug, identifiers::{Account, BlobId, MessageId, Owner}, ownership::ChainOwnership, }; @@ -323,39 +324,49 @@ where } /// Requests to the execution state. +#[derive(Debug)] pub enum ExecutionRequest { LoadContract { id: UserApplicationId, + #[debug(skip)] callback: Sender<(UserContractCode, UserApplicationDescription)>, }, LoadService { id: UserApplicationId, + #[debug(skip)] callback: Sender<(UserServiceCode, UserApplicationDescription)>, }, ChainBalance { + #[debug(skip)] callback: Sender, }, OwnerBalance { owner: Owner, + #[debug(skip)] callback: Sender, }, OwnerBalances { + #[debug(skip)] callback: Sender>, }, BalanceOwners { + #[debug(skip)] callback: Sender>, }, Transfer { + #[debug(skip_if = Option::is_none)] source: Option, destination: Account, amount: Amount, + #[debug(skip_if = Option::is_none)] signer: Option, + #[debug(skip)] callback: Sender>, }, @@ -363,236 +374,115 @@ pub enum ExecutionRequest { source: Account, destination: Account, amount: Amount, + #[debug(skip_if = Option::is_none)] signer: Option, + #[debug(skip)] callback: Sender>, }, SystemTimestamp { + #[debug(skip)] callback: Sender, }, ChainOwnership { + #[debug(skip)] callback: Sender, }, ReadValueBytes { id: UserApplicationId, + #[debug(with = hex_debug)] key: Vec, + #[debug(skip)] callback: Sender>>, }, ContainsKey { id: UserApplicationId, key: Vec, + #[debug(skip)] callback: Sender, }, ContainsKeys { id: UserApplicationId, + #[debug(with = hex_vec_debug)] keys: Vec>, callback: Sender>, }, ReadMultiValuesBytes { id: UserApplicationId, + #[debug(with = hex_vec_debug)] keys: Vec>, + #[debug(skip)] callback: Sender>>>, }, FindKeysByPrefix { id: UserApplicationId, + #[debug(with = hex_debug)] key_prefix: Vec, + #[debug(skip)] callback: Sender>>, }, FindKeyValuesByPrefix { id: UserApplicationId, + #[debug(with = hex_debug)] key_prefix: Vec, + #[debug(skip)] callback: Sender, Vec)>>, }, WriteBatch { id: UserApplicationId, batch: Batch, + #[debug(skip)] callback: Sender<()>, }, OpenChain { ownership: ChainOwnership, + #[debug(skip_if = Amount::is_zero)] balance: Amount, next_message_id: MessageId, application_permissions: ApplicationPermissions, + #[debug(skip)] callback: Sender<[RawOutgoingMessage; 2]>, }, CloseChain { application_id: UserApplicationId, + #[debug(skip)] callback: oneshot::Sender>, }, FetchUrl { url: String, + #[debug(skip)] callback: Sender>, }, HttpPost { url: String, content_type: String, + #[debug(with = hex_debug)] payload: Vec, + #[debug(skip)] callback: oneshot::Sender>, }, ReadBlobContent { blob_id: BlobId, + #[debug(skip)] callback: Sender, }, AssertBlobExists { blob_id: BlobId, + #[debug(skip)] callback: Sender<()>, }, } - -impl Debug for ExecutionRequest { - fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { - match self { - ExecutionRequest::LoadContract { id, .. } => formatter - .debug_struct("ExecutionRequest::LoadContract") - .field("id", id) - .finish_non_exhaustive(), - - ExecutionRequest::LoadService { id, .. } => formatter - .debug_struct("ExecutionRequest::LoadService") - .field("id", id) - .finish_non_exhaustive(), - - ExecutionRequest::ChainBalance { .. } => formatter - .debug_struct("ExecutionRequest::ChainBalance") - .finish_non_exhaustive(), - - ExecutionRequest::OwnerBalance { owner, .. } => formatter - .debug_struct("ExecutionRequest::OwnerBalance") - .field("owner", owner) - .finish_non_exhaustive(), - - ExecutionRequest::OwnerBalances { .. } => formatter - .debug_struct("ExecutionRequest::OwnerBalances") - .finish_non_exhaustive(), - - ExecutionRequest::BalanceOwners { .. } => formatter - .debug_struct("ExecutionRequest::BalanceOwners") - .finish_non_exhaustive(), - - ExecutionRequest::Transfer { - source, - destination, - amount, - signer, - .. - } => formatter - .debug_struct("ExecutionRequest::Transfer") - .field("source", source) - .field("destination", destination) - .field("amount", amount) - .field("signer", signer) - .finish_non_exhaustive(), - - ExecutionRequest::Claim { - source, - destination, - amount, - signer, - .. - } => formatter - .debug_struct("ExecutionRequest::Claim") - .field("source", source) - .field("destination", destination) - .field("amount", amount) - .field("signer", signer) - .finish_non_exhaustive(), - - ExecutionRequest::SystemTimestamp { .. } => formatter - .debug_struct("ExecutionRequest::SystemTimestamp") - .finish_non_exhaustive(), - - ExecutionRequest::ChainOwnership { .. } => formatter - .debug_struct("ExecutionRequest::ChainOwnership") - .finish_non_exhaustive(), - - ExecutionRequest::ReadValueBytes { id, key, .. } => formatter - .debug_struct("ExecutionRequest::ReadValueBytes") - .field("id", id) - .field("key", key) - .finish_non_exhaustive(), - - ExecutionRequest::ContainsKey { id, key, .. } => formatter - .debug_struct("ExecutionRequest::ContainsKey") - .field("id", id) - .field("key", key) - .finish_non_exhaustive(), - - ExecutionRequest::ContainsKeys { id, keys, .. } => formatter - .debug_struct("ExecutionRequest::ContainsKeys") - .field("id", id) - .field("keys", keys) - .finish_non_exhaustive(), - - ExecutionRequest::ReadMultiValuesBytes { id, keys, .. } => formatter - .debug_struct("ExecutionRequest::ReadMultiValuesBytes") - .field("id", id) - .field("keys", keys) - .finish_non_exhaustive(), - - ExecutionRequest::FindKeysByPrefix { id, key_prefix, .. } => formatter - .debug_struct("ExecutionRequest::FindKeysByPrefix") - .field("id", id) - .field("key_prefix", key_prefix) - .finish_non_exhaustive(), - - ExecutionRequest::FindKeyValuesByPrefix { id, key_prefix, .. } => formatter - .debug_struct("ExecutionRequest::FindKeyValuesByPrefix") - .field("id", id) - .field("key_prefix", key_prefix) - .finish_non_exhaustive(), - - ExecutionRequest::WriteBatch { id, batch, .. } => formatter - .debug_struct("ExecutionRequest::WriteBatch") - .field("id", id) - .field("batch", batch) - .finish_non_exhaustive(), - - ExecutionRequest::OpenChain { balance, .. } => formatter - .debug_struct("ExecutionRequest::OpenChain") - .field("balance", balance) - .finish_non_exhaustive(), - - ExecutionRequest::CloseChain { application_id, .. } => formatter - .debug_struct("ExecutionRequest::CloseChain") - .field("application_id", application_id) - .finish_non_exhaustive(), - - ExecutionRequest::FetchUrl { url, .. } => formatter - .debug_struct("ExecutionRequest::FetchUrl") - .field("url", url) - .finish_non_exhaustive(), - - ExecutionRequest::HttpPost { - url, content_type, .. - } => formatter - .debug_struct("ExecutionRequest::HttpPost") - .field("url", url) - .field("content_type", content_type) - .finish_non_exhaustive(), - - ExecutionRequest::ReadBlobContent { blob_id, .. } => formatter - .debug_struct("ExecutionRequest::ReadBlob") - .field("blob_id", blob_id) - .finish_non_exhaustive(), - - ExecutionRequest::AssertBlobExists { blob_id, .. } => formatter - .debug_struct("ExecutionRequest::AssertBlobExists") - .field("blob_id", blob_id) - .finish_non_exhaustive(), - } - } -} diff --git a/linera-execution/src/lib.rs b/linera-execution/src/lib.rs index a1c419c1b0d..c1b3b515555 100644 --- a/linera-execution/src/lib.rs +++ b/linera-execution/src/lib.rs @@ -356,13 +356,16 @@ pub struct OperationContext { /// The current chain ID. pub chain_id: ChainId, /// The authenticated signer of the operation, if any. + #[debug(skip_if = Option::is_none)] pub authenticated_signer: Option, /// `None` if this is the transaction entrypoint or the caller doesn't want this particular /// call to be authenticated (e.g. for safety reasons). + #[debug(skip_if = Option::is_none)] pub authenticated_caller_id: Option, /// The current block height. pub height: BlockHeight, /// The current index of the operation. + #[debug(skip_if = Option::is_none)] pub index: Option, } @@ -373,8 +376,10 @@ pub struct MessageContext { /// Whether the message was rejected by the original receiver and is now bouncing back. pub is_bouncing: bool, /// The authenticated signer of the operation that created the message, if any. + #[debug(skip_if = Option::is_none)] pub authenticated_signer: Option, /// Where to send a refund for the unused part of each grant after execution, if any. + #[debug(skip_if = Option::is_none)] pub refund_grant_to: Option, /// The current block height. pub height: BlockHeight, @@ -390,6 +395,7 @@ pub struct FinalizeContext { /// The current chain ID. pub chain_id: ChainId, /// The authenticated signer of the operation, if any. + #[debug(skip_if = Option::is_none)] pub authenticated_signer: Option, /// The current block height. pub height: BlockHeight, diff --git a/linera-execution/src/runtime.rs b/linera-execution/src/runtime.rs index ace33f9ce1c..132a4c913be 100644 --- a/linera-execution/src/runtime.rs +++ b/linera-execution/src/runtime.rs @@ -67,8 +67,10 @@ pub struct SyncRuntimeInternal { /// The current local time. local_time: Timestamp, /// The authenticated signer of the operation or message, if any. + #[debug(skip_if = Option::is_none)] authenticated_signer: Option, /// The current message being executed, if there is one. + #[debug(skip_if = Option::is_none)] executing_message: Option, /// How to interact with the storage view of the execution state. @@ -94,6 +96,7 @@ pub struct SyncRuntimeInternal { view_user_states: BTreeMap, /// Where to send a refund for the unused part of the grant after execution, if any. + #[debug(skip_if = Option::is_none)] refund_grant_to: Option, /// Controller to track fuel and storage consumption. resource_controller: ResourceController, diff --git a/linera-execution/src/system.rs b/linera-execution/src/system.rs index 2e1339d4997..2cfeaa30c6d 100644 --- a/linera-execution/src/system.rs +++ b/linera-execution/src/system.rs @@ -110,6 +110,7 @@ pub enum SystemOperation { /// Transfers `amount` units of value from the given owner's account to the recipient. /// If no owner is given, try to take the units out of the unattributed account. Transfer { + #[debug(skip_if = Option::is_none)] owner: Option, recipient: Recipient, amount: Amount, @@ -131,8 +132,10 @@ pub enum SystemOperation { /// Changes the ownership of the chain. ChangeOwnership { /// Super owners can propose fast blocks in the first round, and regular blocks in any round. + #[debug(skip_if = Vec::is_empty)] super_owners: Vec, /// The regular owners, with their weights that determine how often they are round leader. + #[debug(skip_if = Vec::is_empty)] owners: Vec<(PublicKey, u64)>, /// The number of initial rounds after 0 in which all owners are allowed to propose blocks. multi_leader_rounds: u32, @@ -165,8 +168,9 @@ pub enum SystemOperation { #[debug(with = "hex_debug")] parameters: Vec, #[serde(with = "serde_bytes")] - #[debug(with = "hex_debug")] + #[debug(with = "hex_debug", skip_if = Vec::is_empty)] instantiation_argument: Vec, + #[debug(skip_if = Vec::is_empty)] required_application_ids: Vec, }, /// Requests a message from another chain to register a user application on this chain. @@ -197,8 +201,10 @@ pub enum SystemMessage { /// Credits `amount` units of value to the account `target` -- unless the message is /// bouncing, in which case `source` is credited instead. Credit { + #[debug(skip_if = Option::is_none)] target: Option, amount: Amount, + #[debug(skip_if = Option::is_none)] source: Option, }, /// Withdraws `amount` units of value from the account and starts a transfer to credit diff --git a/linera-execution/src/test_utils/system_execution_state.rs b/linera-execution/src/test_utils/system_execution_state.rs index 3bb5c885515..33fe4a3cdf5 100644 --- a/linera-execution/src/test_utils/system_execution_state.rs +++ b/linera-execution/src/test_utils/system_execution_state.rs @@ -3,9 +3,11 @@ use std::{ collections::{BTreeMap, BTreeSet}, + ops::Not, sync::Arc, }; +use custom_debug_derive::Debug; use linera_base::{ crypto::CryptoHash, data_types::{Amount, ApplicationPermissions, Timestamp}, @@ -39,9 +41,11 @@ pub struct SystemExecutionState { pub committees: BTreeMap, pub ownership: ChainOwnership, pub balance: Amount, + #[debug(skip_if = BTreeMap::is_empty)] pub balances: BTreeMap, pub timestamp: Timestamp, pub registry: ApplicationRegistry, + #[debug(skip_if = Not::not)] pub closed: bool, pub application_permissions: ApplicationPermissions, } diff --git a/linera-execution/src/transaction_tracker.rs b/linera-execution/src/transaction_tracker.rs index ad505c277bb..00a15dee229 100644 --- a/linera-execution/src/transaction_tracker.rs +++ b/linera-execution/src/transaction_tracker.rs @@ -3,6 +3,7 @@ use std::vec; +use custom_debug_derive::Debug; use linera_base::{ data_types::{Amount, ArithmeticError, OracleResponse}, ensure, @@ -17,8 +18,11 @@ use crate::{ /// as replayed oracle responses. #[derive(Debug, Default)] pub struct TransactionTracker { + #[debug(skip_if = Option::is_none)] replaying_oracle_responses: Option>, + #[debug(skip_if = Vec::is_empty)] oracle_responses: Vec, + #[debug(skip_if = Vec::is_empty)] outcomes: Vec, next_message_index: u32, }