From dfc7adc0ac5487f475df4b0512e14d73d3514e49 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 11:13:24 +0200 Subject: [PATCH 01/16] add commitment and block issuance credit inputs --- .../context_input/block_issuance_credit.rs | 55 +++++++++++++++++++ .../types/block/context_input/commitment.rs | 53 ++++++++++++++++++ sdk/src/types/block/context_input/mod.rs | 41 +++++++++++--- 3 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 sdk/src/types/block/context_input/block_issuance_credit.rs create mode 100644 sdk/src/types/block/context_input/commitment.rs diff --git a/sdk/src/types/block/context_input/block_issuance_credit.rs b/sdk/src/types/block/context_input/block_issuance_credit.rs new file mode 100644 index 0000000000..b47fdda791 --- /dev/null +++ b/sdk/src/types/block/context_input/block_issuance_credit.rs @@ -0,0 +1,55 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use derive_more::{Display, From}; + +use crate::types::block::output::AccountId; + +/// A Block Issuance Credit Input provides the VM with context for the value of +/// the BIC vector of a specific slot. +#[derive(Clone, Copy, Debug, Display, Eq, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] +pub struct BlockIssuanceCreditContextInput(AccountId); + +impl BlockIssuanceCreditContextInput { + /// The context input kind of a [`BlockIssuanceCreditContextInput`]. + pub const KIND: u8 = 1; + + /// Creates a new [`BlockIssuanceCreditContextInput`]. + pub fn new(account_id: AccountId) -> Self { + Self(account_id) + } + + pub fn account_id(&self) -> AccountId { + self.0 + } +} + +pub(crate) mod dto { + use serde::{Deserialize, Serialize}; + + use super::*; + + /// A Block Issuance Credit Input provides the VM with context for the value of + /// the BIC vector of a specific slot. + #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] + pub struct BlockIssuanceCreditContextInputDto { + #[serde(rename = "type")] + pub kind: u8, + pub account_id: AccountId, + } + + impl From<&BlockIssuanceCreditContextInput> for BlockIssuanceCreditContextInputDto { + fn from(value: &BlockIssuanceCreditContextInput) -> Self { + Self { + kind: BlockIssuanceCreditContextInput::KIND, + account_id: value.account_id(), + } + } + } + + impl From for BlockIssuanceCreditContextInput { + fn from(value: BlockIssuanceCreditContextInputDto) -> Self { + Self::new(value.account_id) + } + } +} diff --git a/sdk/src/types/block/context_input/commitment.rs b/sdk/src/types/block/context_input/commitment.rs new file mode 100644 index 0000000000..c665c87954 --- /dev/null +++ b/sdk/src/types/block/context_input/commitment.rs @@ -0,0 +1,53 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use derive_more::{Display, From}; + +use crate::types::block::slot::SlotCommitmentId; + +/// A Commitment Context indicates that the input references a commitment to a certain slot. +#[derive(Clone, Copy, Display, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] +pub struct CommitmentContextInput(SlotCommitmentId); + +impl CommitmentContextInput { + /// The context input kind of a [`CommitmentContextInput`]. + pub const KIND: u8 = 0; + + /// Creates a new [`CommitmentContextInput`]. + pub fn new(commitment_id: SlotCommitmentId) -> Self { + Self(commitment_id) + } + + pub fn commitment_id(&self) -> SlotCommitmentId { + self.0 + } +} + +pub(crate) mod dto { + use serde::{Deserialize, Serialize}; + + use super::*; + + /// A Commitment Context indicates that the input references a commitment to a certain slot. + #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] + pub struct CommitmentContextInputDto { + #[serde(rename = "type")] + pub kind: u8, + pub commitment_id: SlotCommitmentId, + } + + impl From<&CommitmentContextInput> for CommitmentContextInputDto { + fn from(value: &CommitmentContextInput) -> Self { + Self { + kind: CommitmentContextInput::KIND, + commitment_id: value.commitment_id(), + } + } + } + + impl From for CommitmentContextInput { + fn from(value: CommitmentContextInputDto) -> Self { + Self::new(value.commitment_id) + } + } +} diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index 140eec203f..55c7de2e4d 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -1,28 +1,42 @@ // Copyright 2023 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +mod block_issuance_credit; +mod commitment; mod reward; -use derive_more::From; - +pub use self::block_issuance_credit::BlockIssuanceCreditContextInput; +pub use self::commitment::CommitmentContextInput; pub use self::reward::RewardContextInput; + use crate::types::block::Error; +use derive_more::Display; +use derive_more::From; /// A Context Input provides additional contextual information for the execution of a transaction, such as for different /// functionality related to accounts, commitments, or Mana rewards. A Context Input does not need to be unlocked. -#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] +#[derive(Clone, Eq, Display, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] #[packable(unpack_error = Error)] #[packable(tag_type = u8, with_error = Error::InvalidContextInputKind)] pub enum ContextInput { + /// A [`CommitmentContextInput`]. + #[packable(tag = CommitmentContextInput::KIND)] + Commitment(CommitmentContextInput), + + /// A [`CommitmentContextInput`]. + #[packable(tag = BlockIssuanceCreditContextInput::KIND)] + BlockIssuanceCredit(BlockIssuanceCreditContextInput), + /// A [`RewardContextInput`]. #[packable(tag = RewardContextInput::KIND)] Reward(RewardContextInput), - // TODO: Commitment Input https://github.com/iotaledger/iota-sdk/issues/901 and Block Issuance Credit Input https://github.com/iotaledger/iota-sdk/issues/906 } impl core::fmt::Debug for ContextInput { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { + Self::Commitment(input) => input.fmt(f), + Self::BlockIssuanceCredit(input) => input.fmt(f), Self::Reward(input) => input.fmt(f), } } @@ -32,6 +46,8 @@ impl ContextInput { /// Returns the context input kind of a `ContextInput`. pub fn kind(&self) -> u8 { match self { + Self::Commitment(_) => CommitmentContextInput::KIND, + Self::BlockIssuanceCredit(_) => BlockIssuanceCreditContextInput::KIND, Self::Reward(_) => RewardContextInput::KIND, } } @@ -44,8 +60,11 @@ impl ContextInput { /// Gets the input as an actual [`RewardContextInput`]. /// PANIC: do not call on a non-reward context input. pub fn as_reward(&self) -> &RewardContextInput { - let Self::Reward(input) = self; - input + if let Self::Reward(input) = self { + input + } else { + panic!("context input is not of type reward {}", self); + } } } @@ -53,19 +72,25 @@ pub mod dto { use serde::{Deserialize, Serialize}; pub use super::reward::dto::RewardContextInputDto; - use super::*; + use super::{ + block_issuance_credit::dto::BlockIssuanceCreditContextInputDto, commitment::dto::CommitmentContextInputDto, *, + }; use crate::types::block::Error; /// Describes all the different context input types. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, From)] #[serde(untagged)] pub enum ContextInputDto { + Commitment(CommitmentContextInputDto), + BlockIssuanceCredit(BlockIssuanceCreditContextInputDto), Reward(RewardContextInputDto), } impl From<&ContextInput> for ContextInputDto { fn from(value: &ContextInput) -> Self { match value { + ContextInput::Commitment(u) => Self::Commitment(u.into()), + ContextInput::BlockIssuanceCredit(u) => Self::BlockIssuanceCredit(u.into()), ContextInput::Reward(u) => Self::Reward(u.into()), } } @@ -76,6 +101,8 @@ pub mod dto { fn try_from(value: ContextInputDto) -> Result { match value { + ContextInputDto::Commitment(u) => Ok(Self::Commitment(u.try_into()?)), + ContextInputDto::BlockIssuanceCredit(u) => Ok(Self::BlockIssuanceCredit(u.try_into()?)), ContextInputDto::Reward(u) => Ok(Self::Reward(u.try_into()?)), } } From 5f628d153862c019efcc36d5fdc22b2a66408c67 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 12:03:46 +0200 Subject: [PATCH 02/16] add tests --- sdk/src/types/block/context_input/mod.rs | 60 +++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index 55c7de2e4d..41bc9dd370 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -57,13 +57,42 @@ impl ContextInput { matches!(self, Self::Reward(_)) } + /// Checks whether the context input is a [`CommitmentContextInput`]. + pub fn is_commitment(&self) -> bool { + matches!(self, Self::Commitment(_)) + } + + /// Checks whether the context input is a [`BlockIssuanceCreditContextInput`]. + pub fn is_block_issuance_credit(&self) -> bool { + matches!(self, Self::BlockIssuanceCredit(_)) + } + /// Gets the input as an actual [`RewardContextInput`]. /// PANIC: do not call on a non-reward context input. pub fn as_reward(&self) -> &RewardContextInput { if let Self::Reward(input) = self { input } else { - panic!("context input is not of type reward {}", self); + panic!("context input is not of type reward: {:?}", self); + } + } + + /// Gets the input as an actual [`CommitmentContextInput`]. + /// PANIC: do not call on a non-commitment context input. + pub fn as_commitment(&self) -> &CommitmentContextInput { + if let Self::Commitment(input) = self { + input + } else { + panic!("context input is not of type commitment: {:?}", self); + } + } + /// Gets the input as an actual [`BlockIssuanceCreditContextInput`]. + /// PANIC: do not call on a non-block-issuance-credit context input. + pub fn as_block_issuance_credit(&self) -> &BlockIssuanceCreditContextInput { + if let Self::BlockIssuanceCredit(input) = self { + input + } else { + panic!("context input is not of type block issuance credit: {:?}", self); } } } @@ -108,3 +137,32 @@ pub mod dto { } } } + +#[cfg(test)] +mod tests { + use super::{CommitmentContextInput, ContextInput, RewardContextInput}; + use crate::types::block::{ + context_input::BlockIssuanceCreditContextInput, output::AccountId, slot::SlotCommitmentId, + }; + use core::str::FromStr; + + #[test] + fn test_context_input() { + let reward = ContextInput::Reward(RewardContextInput::new(10)); + let reward: &RewardContextInput = reward.as_reward(); + assert_eq!(reward.to_string(), "10"); + + let slot_commitment_id_str = + "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689"; + let slot_commitment_id = SlotCommitmentId::from_str(slot_commitment_id_str).unwrap(); + let commitment = ContextInput::Commitment(CommitmentContextInput::new(slot_commitment_id)); + let commitment: &CommitmentContextInput = commitment.as_commitment(); + assert_eq!(commitment.to_string(), slot_commitment_id_str); + + let account_id_str = "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649"; + let account_id = AccountId::from_str(account_id_str).unwrap(); + let block_issuance_credit = ContextInput::BlockIssuanceCredit(BlockIssuanceCreditContextInput::new(account_id)); + let block_issuance_credit: &BlockIssuanceCreditContextInput = block_issuance_credit.as_block_issuance_credit(); + assert_eq!(block_issuance_credit.to_string(), account_id_str); + } +} From 2d78d929bd22f4f6a783f5c86d2e58d30e1a560f Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 12:09:27 +0200 Subject: [PATCH 03/16] add fn documentation --- sdk/src/types/block/context_input/block_issuance_credit.rs | 1 + sdk/src/types/block/context_input/commitment.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/sdk/src/types/block/context_input/block_issuance_credit.rs b/sdk/src/types/block/context_input/block_issuance_credit.rs index b47fdda791..72d7e0c8d2 100644 --- a/sdk/src/types/block/context_input/block_issuance_credit.rs +++ b/sdk/src/types/block/context_input/block_issuance_credit.rs @@ -19,6 +19,7 @@ impl BlockIssuanceCreditContextInput { Self(account_id) } + /// Returns the account id of the [`BlockIssuanceCreditContextInput`]. pub fn account_id(&self) -> AccountId { self.0 } diff --git a/sdk/src/types/block/context_input/commitment.rs b/sdk/src/types/block/context_input/commitment.rs index c665c87954..e29834cb4d 100644 --- a/sdk/src/types/block/context_input/commitment.rs +++ b/sdk/src/types/block/context_input/commitment.rs @@ -18,6 +18,7 @@ impl CommitmentContextInput { Self(commitment_id) } + /// Returns the commitment id of the [`CommitmentContextInput`]. pub fn commitment_id(&self) -> SlotCommitmentId { self.0 } From 5c84265808168a435c2055b601b6450cce12e1cb Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 12:14:17 +0200 Subject: [PATCH 04/16] improve test --- sdk/src/types/block/context_input/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index 41bc9dd370..04f8d7d17a 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -149,6 +149,7 @@ mod tests { #[test] fn test_context_input() { let reward = ContextInput::Reward(RewardContextInput::new(10)); + assert!(reward.is_reward()); let reward: &RewardContextInput = reward.as_reward(); assert_eq!(reward.to_string(), "10"); @@ -156,12 +157,14 @@ mod tests { "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689"; let slot_commitment_id = SlotCommitmentId::from_str(slot_commitment_id_str).unwrap(); let commitment = ContextInput::Commitment(CommitmentContextInput::new(slot_commitment_id)); + assert!(commitment.is_commitment()); let commitment: &CommitmentContextInput = commitment.as_commitment(); assert_eq!(commitment.to_string(), slot_commitment_id_str); let account_id_str = "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649"; let account_id = AccountId::from_str(account_id_str).unwrap(); let block_issuance_credit = ContextInput::BlockIssuanceCredit(BlockIssuanceCreditContextInput::new(account_id)); + assert!(block_issuance_credit.is_block_issuance_credit()); let block_issuance_credit: &BlockIssuanceCreditContextInput = block_issuance_credit.as_block_issuance_credit(); assert_eq!(block_issuance_credit.to_string(), account_id_str); } From 7768dc9108ccbb3ca8a16cb979ddeb404689e74a Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 12:16:04 +0200 Subject: [PATCH 05/16] fix --- sdk/src/types/block/context_input/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index 04f8d7d17a..dcc74be0de 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -23,7 +23,7 @@ pub enum ContextInput { #[packable(tag = CommitmentContextInput::KIND)] Commitment(CommitmentContextInput), - /// A [`CommitmentContextInput`]. + /// A [`BlockIssuanceCreditContextInput`]. #[packable(tag = BlockIssuanceCreditContextInput::KIND)] BlockIssuanceCredit(BlockIssuanceCreditContextInput), From 10ffe84586d0a16ec0635f9629638020c0fb0729 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 12:25:33 +0200 Subject: [PATCH 06/16] fmt --- sdk/src/types/block/context_input/mod.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index dcc74be0de..472d0cf4bd 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -5,13 +5,13 @@ mod block_issuance_credit; mod commitment; mod reward; -pub use self::block_issuance_credit::BlockIssuanceCreditContextInput; -pub use self::commitment::CommitmentContextInput; -pub use self::reward::RewardContextInput; +use derive_more::{Display, From}; +pub use self::{ + block_issuance_credit::BlockIssuanceCreditContextInput, commitment::CommitmentContextInput, + reward::RewardContextInput, +}; use crate::types::block::Error; -use derive_more::Display; -use derive_more::From; /// A Context Input provides additional contextual information for the execution of a transaction, such as for different /// functionality related to accounts, commitments, or Mana rewards. A Context Input does not need to be unlocked. @@ -140,11 +140,12 @@ pub mod dto { #[cfg(test)] mod tests { + use core::str::FromStr; + use super::{CommitmentContextInput, ContextInput, RewardContextInput}; use crate::types::block::{ context_input::BlockIssuanceCreditContextInput, output::AccountId, slot::SlotCommitmentId, }; - use core::str::FromStr; #[test] fn test_context_input() { From 5fcd4bcc9981819c7508d2a1cf36cf4e279bdf40 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 12:28:29 +0200 Subject: [PATCH 07/16] remove spaces between fields --- sdk/src/types/block/context_input/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index 472d0cf4bd..b44a81102a 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -22,11 +22,9 @@ pub enum ContextInput { /// A [`CommitmentContextInput`]. #[packable(tag = CommitmentContextInput::KIND)] Commitment(CommitmentContextInput), - /// A [`BlockIssuanceCreditContextInput`]. #[packable(tag = BlockIssuanceCreditContextInput::KIND)] BlockIssuanceCredit(BlockIssuanceCreditContextInput), - /// A [`RewardContextInput`]. #[packable(tag = RewardContextInput::KIND)] Reward(RewardContextInput), From c0e9ce49cf71b98f1c2e4f28c1d37a6e1ec8362e Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 12:30:05 +0200 Subject: [PATCH 08/16] imporve order of methods --- sdk/src/types/block/context_input/mod.rs | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index b44a81102a..5b1141d9ca 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -50,11 +50,6 @@ impl ContextInput { } } - /// Checks whether the context input is a [`RewardContextInput`]. - pub fn is_reward(&self) -> bool { - matches!(self, Self::Reward(_)) - } - /// Checks whether the context input is a [`CommitmentContextInput`]. pub fn is_commitment(&self) -> bool { matches!(self, Self::Commitment(_)) @@ -65,14 +60,9 @@ impl ContextInput { matches!(self, Self::BlockIssuanceCredit(_)) } - /// Gets the input as an actual [`RewardContextInput`]. - /// PANIC: do not call on a non-reward context input. - pub fn as_reward(&self) -> &RewardContextInput { - if let Self::Reward(input) = self { - input - } else { - panic!("context input is not of type reward: {:?}", self); - } + /// Checks whether the context input is a [`RewardContextInput`]. + pub fn is_reward(&self) -> bool { + matches!(self, Self::Reward(_)) } /// Gets the input as an actual [`CommitmentContextInput`]. @@ -93,6 +83,16 @@ impl ContextInput { panic!("context input is not of type block issuance credit: {:?}", self); } } + + /// Gets the input as an actual [`RewardContextInput`]. + /// PANIC: do not call on a non-reward context input. + pub fn as_reward(&self) -> &RewardContextInput { + if let Self::Reward(input) = self { + input + } else { + panic!("context input is not of type reward: {:?}", self); + } + } } pub mod dto { From f65846d7c18c40a0b96b692bb57b5e3f8fe661a1 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 13:07:22 +0200 Subject: [PATCH 09/16] improve panic message --- sdk/src/types/block/context_input/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index 5b1141d9ca..ab62b02c48 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -71,7 +71,7 @@ impl ContextInput { if let Self::Commitment(input) = self { input } else { - panic!("context input is not of type commitment: {:?}", self); + panic!("invalid downcast of non-CommitmentContextInput"); } } /// Gets the input as an actual [`BlockIssuanceCreditContextInput`]. @@ -80,7 +80,7 @@ impl ContextInput { if let Self::BlockIssuanceCredit(input) = self { input } else { - panic!("context input is not of type block issuance credit: {:?}", self); + panic!("invalid downcast of non-BlockIssuanceCreditContextInput"); } } @@ -90,7 +90,7 @@ impl ContextInput { if let Self::Reward(input) = self { input } else { - panic!("context input is not of type reward: {:?}", self); + panic!("invalid downcast of non-RewardContextInput"); } } } From 2f49f19235396f920bacc70076ca5bb0ab89f7c2 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 13:22:50 +0200 Subject: [PATCH 10/16] alternate `is_` and `as_` methods --- sdk/src/types/block/context_input/mod.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index ab62b02c48..01cc0fbab5 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -55,16 +55,6 @@ impl ContextInput { matches!(self, Self::Commitment(_)) } - /// Checks whether the context input is a [`BlockIssuanceCreditContextInput`]. - pub fn is_block_issuance_credit(&self) -> bool { - matches!(self, Self::BlockIssuanceCredit(_)) - } - - /// Checks whether the context input is a [`RewardContextInput`]. - pub fn is_reward(&self) -> bool { - matches!(self, Self::Reward(_)) - } - /// Gets the input as an actual [`CommitmentContextInput`]. /// PANIC: do not call on a non-commitment context input. pub fn as_commitment(&self) -> &CommitmentContextInput { @@ -74,6 +64,12 @@ impl ContextInput { panic!("invalid downcast of non-CommitmentContextInput"); } } + + /// Checks whether the context input is a [`BlockIssuanceCreditContextInput`]. + pub fn is_block_issuance_credit(&self) -> bool { + matches!(self, Self::BlockIssuanceCredit(_)) + } + /// Gets the input as an actual [`BlockIssuanceCreditContextInput`]. /// PANIC: do not call on a non-block-issuance-credit context input. pub fn as_block_issuance_credit(&self) -> &BlockIssuanceCreditContextInput { @@ -84,6 +80,11 @@ impl ContextInput { } } + /// Checks whether the context input is a [`RewardContextInput`]. + pub fn is_reward(&self) -> bool { + matches!(self, Self::Reward(_)) + } + /// Gets the input as an actual [`RewardContextInput`]. /// PANIC: do not call on a non-reward context input. pub fn as_reward(&self) -> &RewardContextInput { From 21e7e4174bf701e3f0c0bb2f6ace5d4f4825fb4b Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 13:24:23 +0200 Subject: [PATCH 11/16] fix commitment documentation --- sdk/src/types/block/context_input/commitment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/src/types/block/context_input/commitment.rs b/sdk/src/types/block/context_input/commitment.rs index e29834cb4d..c6aff2541f 100644 --- a/sdk/src/types/block/context_input/commitment.rs +++ b/sdk/src/types/block/context_input/commitment.rs @@ -5,7 +5,7 @@ use derive_more::{Display, From}; use crate::types::block::slot::SlotCommitmentId; -/// A Commitment Context indicates that the input references a commitment to a certain slot. +/// A Commitment Input indicates that the input references a commitment to a certain slot. #[derive(Clone, Copy, Display, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] pub struct CommitmentContextInput(SlotCommitmentId); @@ -29,7 +29,7 @@ pub(crate) mod dto { use super::*; - /// A Commitment Context indicates that the input references a commitment to a certain slot. + /// A Commitment Input indicates that the input references a commitment to a certain slot. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct CommitmentContextInputDto { #[serde(rename = "type")] From f482fb1e407a831883ee04e8ee5cdc596718ab27 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 22:21:02 +0200 Subject: [PATCH 12/16] improve DTOs --- .../context_input/block_issuance_credit.rs | 17 ++- .../types/block/context_input/commitment.rs | 10 +- sdk/src/types/block/context_input/mod.rs | 141 ++++++++++-------- sdk/src/types/block/context_input/reward.rs | 10 +- 4 files changed, 103 insertions(+), 75 deletions(-) diff --git a/sdk/src/types/block/context_input/block_issuance_credit.rs b/sdk/src/types/block/context_input/block_issuance_credit.rs index 72d7e0c8d2..a591509d20 100644 --- a/sdk/src/types/block/context_input/block_issuance_credit.rs +++ b/sdk/src/types/block/context_input/block_issuance_credit.rs @@ -5,7 +5,7 @@ use derive_more::{Display, From}; use crate::types::block::output::AccountId; -/// A Block Issuance Credit Input provides the VM with context for the value of +/// A Block Issuance Credit Input (BIC Input) provides the VM with context for the value of /// the BIC vector of a specific slot. #[derive(Clone, Copy, Debug, Display, Eq, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] pub struct BlockIssuanceCreditContextInput(AccountId); @@ -25,7 +25,7 @@ impl BlockIssuanceCreditContextInput { } } -pub(crate) mod dto { +mod dto { use serde::{Deserialize, Serialize}; use super::*; @@ -33,10 +33,11 @@ pub(crate) mod dto { /// A Block Issuance Credit Input provides the VM with context for the value of /// the BIC vector of a specific slot. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] - pub struct BlockIssuanceCreditContextInputDto { + #[serde(rename_all = "camelCase")] + struct BlockIssuanceCreditContextInputDto { #[serde(rename = "type")] - pub kind: u8, - pub account_id: AccountId, + kind: u8, + account_id: AccountId, } impl From<&BlockIssuanceCreditContextInput> for BlockIssuanceCreditContextInputDto { @@ -53,4 +54,10 @@ pub(crate) mod dto { Self::new(value.account_id) } } + + impl_serde_typed_dto!( + BlockIssuanceCreditContextInput, + BlockIssuanceCreditContextInputDto, + "block issuance credit input" + ); } diff --git a/sdk/src/types/block/context_input/commitment.rs b/sdk/src/types/block/context_input/commitment.rs index c6aff2541f..67d6da5549 100644 --- a/sdk/src/types/block/context_input/commitment.rs +++ b/sdk/src/types/block/context_input/commitment.rs @@ -24,17 +24,18 @@ impl CommitmentContextInput { } } -pub(crate) mod dto { +mod dto { use serde::{Deserialize, Serialize}; use super::*; /// A Commitment Input indicates that the input references a commitment to a certain slot. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] - pub struct CommitmentContextInputDto { + #[serde(rename_all = "camelCase")] + struct CommitmentContextInputDto { #[serde(rename = "type")] - pub kind: u8, - pub commitment_id: SlotCommitmentId, + kind: u8, + commitment_id: SlotCommitmentId, } impl From<&CommitmentContextInput> for CommitmentContextInputDto { @@ -51,4 +52,5 @@ pub(crate) mod dto { Self::new(value.commitment_id) } } + impl_serde_typed_dto!(CommitmentContextInput, CommitmentContextInputDto, "commitment input"); } diff --git a/sdk/src/types/block/context_input/mod.rs b/sdk/src/types/block/context_input/mod.rs index 01cc0fbab5..33e9ed107a 100644 --- a/sdk/src/types/block/context_input/mod.rs +++ b/sdk/src/types/block/context_input/mod.rs @@ -18,6 +18,7 @@ use crate::types::block::Error; #[derive(Clone, Eq, Display, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] #[packable(unpack_error = Error)] #[packable(tag_type = u8, with_error = Error::InvalidContextInputKind)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(untagged))] pub enum ContextInput { /// A [`CommitmentContextInput`]. #[packable(tag = CommitmentContextInput::KIND)] @@ -96,76 +97,92 @@ impl ContextInput { } } -pub mod dto { - use serde::{Deserialize, Serialize}; - - pub use super::reward::dto::RewardContextInputDto; - use super::{ - block_issuance_credit::dto::BlockIssuanceCreditContextInputDto, commitment::dto::CommitmentContextInputDto, *, - }; - use crate::types::block::Error; - - /// Describes all the different context input types. - #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, From)] - #[serde(untagged)] - pub enum ContextInputDto { - Commitment(CommitmentContextInputDto), - BlockIssuanceCredit(BlockIssuanceCreditContextInputDto), - Reward(RewardContextInputDto), - } +#[cfg(test)] +mod tests { - impl From<&ContextInput> for ContextInputDto { - fn from(value: &ContextInput) -> Self { - match value { - ContextInput::Commitment(u) => Self::Commitment(u.into()), - ContextInput::BlockIssuanceCredit(u) => Self::BlockIssuanceCredit(u.into()), - ContextInput::Reward(u) => Self::Reward(u.into()), + use super::ContextInput; + + #[test] + fn test_commitment() { + let commitment: ContextInput = serde_json::from_str( + r#" + { + "type": 0, + "commitmentId": "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689" } - } + "#, + ) + .unwrap(); + assert!(commitment.is_commitment()); + assert_eq!( + commitment.as_commitment().commitment_id().to_string(), + "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689" + ); + + // Test wrong type returns error. + let commitment_deserialization_result: Result = serde_json::from_str( + r#" + { + "type": 2, + "commitmentId": "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689" + } + "#, + ); + assert!(commitment_deserialization_result.is_err()); } - impl TryFrom for ContextInput { - type Error = Error; - - fn try_from(value: ContextInputDto) -> Result { - match value { - ContextInputDto::Commitment(u) => Ok(Self::Commitment(u.try_into()?)), - ContextInputDto::BlockIssuanceCredit(u) => Ok(Self::BlockIssuanceCredit(u.try_into()?)), - ContextInputDto::Reward(u) => Ok(Self::Reward(u.try_into()?)), + #[test] + fn test_block_issuance_credit() { + let bic: ContextInput = serde_json::from_str( + r#" + { + "type": 1, + "accountId": "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649" } - } + "#, + ) + .unwrap(); + assert!(bic.is_block_issuance_credit()); + assert_eq!( + bic.as_block_issuance_credit().account_id().to_string(), + "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649" + ); + + // Test wrong type returns error. + let bic_deserialization_result: Result = serde_json::from_str( + r#" + { + "type": 2, + "accountId": "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649" + } + "#, + ); + assert!(bic_deserialization_result.is_err()); } -} - -#[cfg(test)] -mod tests { - use core::str::FromStr; - - use super::{CommitmentContextInput, ContextInput, RewardContextInput}; - use crate::types::block::{ - context_input::BlockIssuanceCreditContextInput, output::AccountId, slot::SlotCommitmentId, - }; #[test] - fn test_context_input() { - let reward = ContextInput::Reward(RewardContextInput::new(10)); + fn test_reward() { + let reward: ContextInput = serde_json::from_str( + r#" + { + "type": 2, + "index": 10 + } + "#, + ) + .unwrap(); assert!(reward.is_reward()); - let reward: &RewardContextInput = reward.as_reward(); - assert_eq!(reward.to_string(), "10"); - - let slot_commitment_id_str = - "0xedf5f572c58ddf4b4f9567d82bf96689cc68b730df796d822b4b9fb643f5efda4f9567d82bf96689"; - let slot_commitment_id = SlotCommitmentId::from_str(slot_commitment_id_str).unwrap(); - let commitment = ContextInput::Commitment(CommitmentContextInput::new(slot_commitment_id)); - assert!(commitment.is_commitment()); - let commitment: &CommitmentContextInput = commitment.as_commitment(); - assert_eq!(commitment.to_string(), slot_commitment_id_str); - - let account_id_str = "0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649"; - let account_id = AccountId::from_str(account_id_str).unwrap(); - let block_issuance_credit = ContextInput::BlockIssuanceCredit(BlockIssuanceCreditContextInput::new(account_id)); - assert!(block_issuance_credit.is_block_issuance_credit()); - let block_issuance_credit: &BlockIssuanceCreditContextInput = block_issuance_credit.as_block_issuance_credit(); - assert_eq!(block_issuance_credit.to_string(), account_id_str); + assert_eq!(reward.as_reward().index(), 10); + + // Test wrong type returns error. + let reward_serialization_result: Result = serde_json::from_str( + r#" + { + "type": 0, + "index": 10 + } + "#, + ); + assert!(reward_serialization_result.is_err()) } } diff --git a/sdk/src/types/block/context_input/reward.rs b/sdk/src/types/block/context_input/reward.rs index 3ee3afb106..8681f8a818 100644 --- a/sdk/src/types/block/context_input/reward.rs +++ b/sdk/src/types/block/context_input/reward.rs @@ -22,17 +22,17 @@ impl RewardContextInput { } } -pub(crate) mod dto { +mod dto { use serde::{Deserialize, Serialize}; use super::*; /// A Reward Context Input is an input that indicates which transaction Input is claiming Mana rewards. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] - pub struct RewardContextInputDto { + struct RewardContextInputDto { #[serde(rename = "type")] - pub kind: u8, - pub index: u16, + kind: u8, + index: u16, } impl From<&RewardContextInput> for RewardContextInputDto { @@ -49,4 +49,6 @@ pub(crate) mod dto { Self::new(value.index) } } + + impl_serde_typed_dto!(RewardContextInput, RewardContextInputDto, "reward input"); } From 1f66a3f038186d35a240d6da2d8478bb6f5daa11 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 22:34:57 +0200 Subject: [PATCH 13/16] fix missing import --- sdk/src/types/block/context_input/block_issuance_credit.rs | 2 ++ sdk/src/types/block/context_input/commitment.rs | 2 ++ sdk/src/types/block/context_input/reward.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/sdk/src/types/block/context_input/block_issuance_credit.rs b/sdk/src/types/block/context_input/block_issuance_credit.rs index a591509d20..ba0eae3dc2 100644 --- a/sdk/src/types/block/context_input/block_issuance_credit.rs +++ b/sdk/src/types/block/context_input/block_issuance_credit.rs @@ -26,6 +26,8 @@ impl BlockIssuanceCreditContextInput { } mod dto { + use alloc::format; + use serde::{Deserialize, Serialize}; use super::*; diff --git a/sdk/src/types/block/context_input/commitment.rs b/sdk/src/types/block/context_input/commitment.rs index 67d6da5549..d28c4aa89d 100644 --- a/sdk/src/types/block/context_input/commitment.rs +++ b/sdk/src/types/block/context_input/commitment.rs @@ -25,6 +25,8 @@ impl CommitmentContextInput { } mod dto { + use alloc::format; + use serde::{Deserialize, Serialize}; use super::*; diff --git a/sdk/src/types/block/context_input/reward.rs b/sdk/src/types/block/context_input/reward.rs index 8681f8a818..dfe33de409 100644 --- a/sdk/src/types/block/context_input/reward.rs +++ b/sdk/src/types/block/context_input/reward.rs @@ -23,6 +23,8 @@ impl RewardContextInput { } mod dto { + use alloc::format; + use serde::{Deserialize, Serialize}; use super::*; From 462ef9ae3ea767bb64bebc6e36124e116c7f881f Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 22:36:51 +0200 Subject: [PATCH 14/16] fix macro call --- sdk/src/types/block/context_input/reward.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/context_input/reward.rs b/sdk/src/types/block/context_input/reward.rs index dfe33de409..3c01197ef4 100644 --- a/sdk/src/types/block/context_input/reward.rs +++ b/sdk/src/types/block/context_input/reward.rs @@ -52,5 +52,5 @@ mod dto { } } - impl_serde_typed_dto!(RewardContextInput, RewardContextInputDto, "reward input"); + impl_serde_typed_dto!(RewardContextInput, RewardContextInputDto, "reward context input"); } From 2f347c20d3258af1deb6e1cad14641a03116db51 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab Date: Tue, 1 Aug 2023 22:43:29 +0200 Subject: [PATCH 15/16] fix macro calls --- sdk/src/types/block/context_input/block_issuance_credit.rs | 2 +- sdk/src/types/block/context_input/commitment.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sdk/src/types/block/context_input/block_issuance_credit.rs b/sdk/src/types/block/context_input/block_issuance_credit.rs index ba0eae3dc2..ddd1ebe733 100644 --- a/sdk/src/types/block/context_input/block_issuance_credit.rs +++ b/sdk/src/types/block/context_input/block_issuance_credit.rs @@ -60,6 +60,6 @@ mod dto { impl_serde_typed_dto!( BlockIssuanceCreditContextInput, BlockIssuanceCreditContextInputDto, - "block issuance credit input" + "block issuance credit context input" ); } diff --git a/sdk/src/types/block/context_input/commitment.rs b/sdk/src/types/block/context_input/commitment.rs index d28c4aa89d..2e00488779 100644 --- a/sdk/src/types/block/context_input/commitment.rs +++ b/sdk/src/types/block/context_input/commitment.rs @@ -54,5 +54,9 @@ mod dto { Self::new(value.commitment_id) } } - impl_serde_typed_dto!(CommitmentContextInput, CommitmentContextInputDto, "commitment input"); + impl_serde_typed_dto!( + CommitmentContextInput, + CommitmentContextInputDto, + "commitment context input" + ); } From 4e1e22c374ac0da8af5460239c2721385d2dae44 Mon Sep 17 00:00:00 2001 From: Abdulrahim Al Methiab <31316147+abdulmth@users.noreply.github.com> Date: Wed, 2 Aug 2023 15:54:16 +0200 Subject: [PATCH 16/16] Update sdk/src/types/block/context_input/block_issuance_credit.rs Co-authored-by: Alexandcoats --- sdk/src/types/block/context_input/block_issuance_credit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/types/block/context_input/block_issuance_credit.rs b/sdk/src/types/block/context_input/block_issuance_credit.rs index ddd1ebe733..3a1b0fcec5 100644 --- a/sdk/src/types/block/context_input/block_issuance_credit.rs +++ b/sdk/src/types/block/context_input/block_issuance_credit.rs @@ -5,7 +5,7 @@ use derive_more::{Display, From}; use crate::types::block::output::AccountId; -/// A Block Issuance Credit Input (BIC Input) provides the VM with context for the value of +/// A Block Issuance Credit (BIC) Input provides the VM with context for the value of /// the BIC vector of a specific slot. #[derive(Clone, Copy, Debug, Display, Eq, PartialEq, Hash, Ord, PartialOrd, From, packable::Packable)] pub struct BlockIssuanceCreditContextInput(AccountId);