Skip to content

Commit

Permalink
feat: impl serde::Serialize for block related models
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexagon committed Aug 9, 2024
1 parent 0013459 commit dfdf981
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 2 deletions.
53 changes: 53 additions & 0 deletions src/models/block/block_extra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use super::ShardBlockRefs;

/// Block content.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct BlockExtra {
/// Inbound message description.
pub in_msg_description: Lazy<InMsgDescr>,
Expand Down Expand Up @@ -182,6 +183,7 @@ pub type AccountBlocks = AugDict<HashBytes, CurrencyCollection, AccountBlock>;

/// A group of account transactions.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct AccountBlock {
/// Account id.
pub account: HashBytes,
Expand Down Expand Up @@ -237,6 +239,7 @@ pub type OutMsgDescr = AugDict<HashBytes, CurrencyCollection, OutMsg>;

/// Additional content for masterchain blocks.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct McBlockExtra {
/// A tree of the most recent descriptions for all currently existing shards
/// for all workchains except the masterchain.
Expand All @@ -250,6 +253,7 @@ pub struct McBlockExtra {
/// An optional message with minting.
pub mint_msg: Option<Lazy<InMsg>>,
/// Copyleft messages if present.
#[cfg_attr(feature = "serde", serde(skip))]
pub copyleft_msgs: Dict<Uint15, Cell>,
/// Blockchain config (if the block is a key block).
pub config: Option<BlockchainConfig>,
Expand Down Expand Up @@ -409,8 +413,20 @@ impl From<ShardIdent> for ShardIdentFull {
}
}

#[cfg(feature = "serde")]
impl serde::Serialize for ShardIdentFull {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
if serializer.is_human_readable() {
serializer.collect_str(&format_args!("{}:{:08x}", self.workchain, self.prefix))
} else {
(self.workchain, self.prefix).serialize(serializer)
}
}
}

/// Collected fees/created funds.
#[derive(Debug, Clone, Default, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ShardFeeCreated {
/// Collected fees.
pub fees: CurrencyCollection,
Expand All @@ -437,6 +453,7 @@ impl AugDictExtra for ShardFeeCreated {

/// Block signature pair.
#[derive(Debug, Clone, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct BlockSignature {
/// Signer node short id.
pub node_id_short: HashBytes,
Expand Down Expand Up @@ -527,3 +544,39 @@ impl<'a> Load<'a> for Signature {
}
}
}

#[cfg(feature = "serde")]
impl serde::Serialize for Signature {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use base64::prelude::{Engine as _, BASE64_STANDARD};

const fn encoded_len(len: usize) -> usize {
(len * 4 / 3 + 3) & !3
}

if serializer.is_human_readable() {
const BUFFER_SIZE: usize = encoded_len(64);

let mut buffer = [0; { BUFFER_SIZE }];
let n = BASE64_STANDARD
.encode_slice(self.0.as_slice(), &mut buffer)
.unwrap();
debug_assert_eq!(n, BUFFER_SIZE);

// SAFETY: `BASE64_STANDARD` always returns a valid UTF-8 string.
serializer.serialize_str(unsafe { std::str::from_utf8_unchecked(&buffer) })
} else {
self.0.serialize(serializer)
}
}
}

#[cfg(test)]
mod tests {
#[cfg(feature = "serde")]
#[test]
fn serde_signature() {
let res = super::Signature([123; 64]);
serde_json::to_string(&res).unwrap();
}
}
1 change: 1 addition & 0 deletions src/models/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ mod tests;

/// Shard block.
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Block {
/// Global network id.
pub global_id: i32,
Expand Down
38 changes: 38 additions & 0 deletions src/models/block/shard_hashes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,26 @@ impl Iterator for WorkchainLatestBlocksIter<'_> {
}
}

#[cfg(feature = "serde")]
impl serde::Serialize for ShardHashes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::{Error, SerializeMap};

let mut map = serializer.serialize_map(None)?;
for entry in self.iter() {
let (shard, descr) = entry.map_err(Error::custom)?;
map.serialize_entry(&shard, &descr)?;
}
map.end()
}
}

/// Description of the most recent state of the shard.
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ShardDescription {
/// Sequence number of the latest block in the shard.
pub seqno: u32,
Expand Down Expand Up @@ -401,6 +419,7 @@ pub struct ShardDescription {
/// Copyleft rewards if present.
pub copyleft_rewards: Dict<HashBytes, Tokens>,
/// Proofs from other workchains.
#[cfg_attr(feature = "serde", serde(skip))]
pub proof_chain: Option<ProofChain>,
/// Collator ranges for all possible validator sets.
#[cfg(feature = "venom")]
Expand Down Expand Up @@ -613,6 +632,8 @@ fn parse_block_id(shard: ShardIdent, mut value: CellSlice) -> Result<BlockId, Er

/// Time window for shard split/merge.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "ty"))]
pub enum FutureSplitMerge {
/// Shard split window info.
Split {
Expand Down Expand Up @@ -705,6 +726,7 @@ impl<'a> Load<'a> for ProofChain {
/// Collator range description.
#[cfg(feature = "venom")]
#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct CollatorRange {
/// Collator index in validator set.
pub collator: u16,
Expand All @@ -717,6 +739,7 @@ pub struct CollatorRange {
/// Collator ranges for all possible validator sets.
#[cfg(feature = "venom")]
#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[tlb(tag = "#1")]
pub struct ShardCollators {
/// Range for the previous collator.
Expand All @@ -736,6 +759,7 @@ pub struct ShardCollators {
/// Shard block reference.
#[cfg(feature = "venom")]
#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ShardBlockRef {
/// Sequence number of the referenced block.
pub seqno: u32,
Expand Down Expand Up @@ -791,6 +815,20 @@ impl ShardBlockRefs {
}
}

#[cfg(all(feature = "venom", feature = "serde"))]
impl serde::Serialize for ShardBlockRefs {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::{Error, SerializeMap};

let mut map = serializer.serialize_map(None)?;
for entry in self.iter() {
let (shard, descr) = entry.map_err(Error::custom)?;
map.serialize_entry(&shard, &descr)?;
}
map.end()
}
}

/// An iterator over the entries of a [`ShardBlockRefs`].
///
/// This struct is created by the [`iter`] method on [`ShardBlockRefs`].
Expand Down
20 changes: 19 additions & 1 deletion src/models/message/envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use super::IntMsgInfo;

/// Next-hop address for a message.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "ty"))]
pub enum IntermediateAddr {
/// Destination prefix length whithin the same workchain.
Regular(IntermediateAddrRegular),
Expand Down Expand Up @@ -113,6 +115,7 @@ impl<'a> Load<'a> for IntermediateAddr {

/// Destination prefix length whithin the same workchain.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[tlb(validate_with = "Self::is_valid")]
pub struct IntermediateAddrRegular {
/// Destination address prefix length in bits.
Expand Down Expand Up @@ -153,6 +156,7 @@ impl IntermediateAddrRegular {

/// Address prefix with a basic workchain id.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Load, Store)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct IntermediateAddrSimple {
/// Basic workchain id.
///
Expand All @@ -162,20 +166,25 @@ pub struct IntermediateAddrSimple {
pub workchain: i8,

/// High 64 bits of the address.
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_account_prefix"))]
pub address_prefix: u64,
}

/// Address prefix with an extended workchain id.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct IntermediateAddrExt {
/// Workchain ID
pub workchain: i32,
/// Address prefix

/// High 64 bits of the address.
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_account_prefix"))]
pub address_prefix: u64,
}

/// Message with routing information.
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[tlb(tag = "#4")]
pub struct MsgEnvelope {
/// Current address.
Expand All @@ -185,6 +194,7 @@ pub struct MsgEnvelope {
/// Remaining transit fee.
pub fwd_fee_remaining: Tokens,
/// The message itself.
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub message: Lazy<OwnedMessage>,
}

Expand Down Expand Up @@ -224,3 +234,11 @@ impl MsgEnvelope {
}
}
}

#[cfg(feature = "serde")]
fn serialize_account_prefix<S>(prefix: &u64, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&format!("{:08x}", prefix))
}
10 changes: 10 additions & 0 deletions src/models/message/in_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::num::Tokens;

/// Inbound message import fees.
#[derive(Default, PartialEq, Eq, Clone, Debug, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ImportFees {
/// Fees collected from the message.
pub fees_collected: Tokens,
Expand Down Expand Up @@ -39,6 +40,8 @@ impl AugDictExtra for ImportFees {

/// Inbound message.
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "ty"))]
pub enum InMsg {
/// Inbound external message.
External(InMsgExternal),
Expand Down Expand Up @@ -242,10 +245,14 @@ impl<'a> Load<'a> for InMsg {

/// Inbound external message.
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "ty"))]
pub struct InMsgExternal {
/// External message itself.
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub in_msg: Lazy<OwnedMessage>,
/// Executed transaction for this external message.
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub transaction: Lazy<Transaction>,
}

Expand Down Expand Up @@ -277,10 +284,12 @@ impl InMsgExternal {

/// Executed inbound internal message.
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct InMsgFinal {
/// Old envelope.
pub in_msg_envelope: Lazy<MsgEnvelope>,
/// Transaction
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub transaction: Lazy<Transaction>,
/// Forward fee.
pub fwd_fee: Tokens,
Expand Down Expand Up @@ -333,6 +342,7 @@ impl InMsgFinal {

/// Internal message that was not processed in this block.
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct InMsgTransit {
/// Old envelope.
pub in_msg_envelope: Lazy<MsgEnvelope>,
Expand Down
13 changes: 13 additions & 0 deletions src/models/message/out_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::models::{

/// Outbound message queue entry.
#[derive(Debug, Clone, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct EnqueuedMsg {
/// Enqueued message lt.
pub enqueued_lt: u64,
Expand Down Expand Up @@ -45,6 +46,8 @@ impl EnqueuedMsg {

/// Outbound message.
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "ty"))]
pub enum OutMsg {
/// External outbound message.
External(OutMsgExternal),
Expand Down Expand Up @@ -215,10 +218,14 @@ impl<'a> Load<'a> for OutMsg {

/// External outbound message.
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct OutMsgExternal {
/// External message itself.
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub out_msg: Lazy<OwnedMessage>,

/// The source transaction of this external message.
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub transaction: Lazy<Transaction>,
}

Expand Down Expand Up @@ -250,10 +257,12 @@ impl OutMsgExternal {

/// Immediately processed internal outbound message.
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct OutMsgImmediate {
/// Outbound message envelope.
pub out_msg_envelope: Lazy<MsgEnvelope>,
/// The source transaction of this message.
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub transaction: Lazy<Transaction>,
/// The destination reimport message.
pub reimport: Lazy<InMsg>,
Expand Down Expand Up @@ -302,10 +311,12 @@ impl OutMsgImmediate {
/// Ordinary (internal) outbound message, generated in this block and
/// included into the outbound queue.
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct OutMsgNew {
/// Outbound message envelope.
pub out_msg_envelope: Lazy<MsgEnvelope>,
/// The source transaction of this message.
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub transaction: Lazy<Transaction>,
}

Expand Down Expand Up @@ -347,6 +358,7 @@ impl OutMsgNew {
/// A message that was dequeued from the outbound queue
/// and immediately queued in the same block.
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct OutMsgDequeueImmediate {
/// Outbound message envelope.
pub out_msg_envelope: Lazy<MsgEnvelope>,
Expand Down Expand Up @@ -391,6 +403,7 @@ impl OutMsgDequeueImmediate {

/// A message that was dequeued from the outbound queue.
#[derive(Clone, Debug, Default, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct OutMsgDequeueShort {
/// Message envelope hash.
pub msg_env_hash: HashBytes,
Expand Down
Loading

0 comments on commit dfdf981

Please sign in to comment.